Mir

Merge lp:~vanvugt/mir/method-index into lp:~mir-team/mir/trunk

Proposed by Daniel van Vugt
Status: Rejected
Rejected by: Daniel van Vugt
Proposed branch: lp:~vanvugt/mir/method-index
Merge into: lp:~mir-team/mir/trunk
Diff against target: 144 lines (+51/-41)
3 files modified
src/client/mir_basic_rpc_channel.cpp (+1/-1)
src/server/frontend/protobuf_message_processor.cpp (+49/-39)
src/shared/protobuf/mir_protobuf_wire.proto (+1/-1)
To merge this branch: bzr merge lp:~vanvugt/mir/method-index
Reviewer Review Type Date Requested Status
Daniel van Vugt Disapprove
Alan Griffiths Abstain
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+159782@code.launchpad.net

Commit message

Avoid passing method names as strings over the protocol. You can save time,
memory and bandwidth by using the method index (integer) instead.

Description of the change

Sad to say this only makes a very tiny performance improvement. But it was worth a try. dispatch() dropped from 15% (of Mir) to 14%. Such a small improvement is only measurable with a profiler.

So take it or leave it...

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

The performance improvement might be more significant under flooding conditions, such as when vsync is disabled (bug 1130553).

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I'm surprised that this change has any measurable effect as ProtobufMessageProcessor::dispatch() was down amongst the noise in my recent profiling runs.

Using the index is likely a little more efficient but has a risk of breaking with protocol changes. (I'm pretty sure that our messages fit in a block regardless of using an index or a name.)

If we go this way, I think we should be extracting and checking the index -> name information once on startup (not once for every client message) as this probably loses a lot of any gain.

review: Abstain
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Yeah I had another prototype that actually enumerates the method indices dynamically and matches them to names. But then realized it was pointless. The index values don't change unless the protocol does.

Also, any approach to passing the method as an integer method index (from protobuf) creates the risk of protocol breakage. You can eliminate the risk by saying the integer is instead a forever-unique method identifier (defined and allocated separately to the protobuf method index).

I wasn't aware that protobuf used "blocks" that might be so large that the strings fit into them anyway. If that's true then it explains the lack of performance benefit. Though switching transport mechanisms to something other than protobuf could result in our use of strings becoming more significant a problem.

I'm going to reject this. The gain is not significant enough, for now.

review: Disapprove
Revision history for this message
Robert Ancell (robert-ancell) wrote :

I had a play with using an enum in lp:~robert-ancell/mir/method-enum (I think it has issues because we don't expose the protobuf types into the rest of the code). Using a barely defined index is worse than sending a string. An enum would be nicer and more consistent with binary protocols, but it might take some more work to the RPC code to make this work well.

Unmerged revisions

609. By Daniel van Vugt

Avoid passing method names as strings in every single invocation. You can
use their unique integer indices instead.

608. By Robert Carr

Input configuration must be held by shared_ptr. Fixes: https://bugs.launchpad.net/bugs/1170524.

Approved by PS Jenkins bot, Kevin DuBois.

607. By Alan Griffiths

config: documentation of the DefaultServerConfiguration member functions.

Approved by Alexandros Frantzis, PS Jenkins bot.

606. By Robert Ancell

Use mir::shell:Session instead of mir::frontend::Session in mir::shell::SessionContainer and mir::shell::FocusSequence - this stops a user of these classes having to cast to mir::shell::Session objects.

Approved by PS Jenkins bot.

605. By Robert Ancell

Remove unused include

604. By Robert Ancell

Make mir::shell::SessionContainer an abstract class with a default implementation in DefaultSessionManager.

Approved by PS Jenkins bot, Kevin DuBois.

603. By Daniel van Vugt

Remember to generate debug info (LP: #1170202). Fixes: https://bugs.launchpad.net/bugs/1170202.

Approved by Alexandros Frantzis, Alan Griffiths, PS Jenkins bot.

602. By Alexandros Frantzis

Rename Shell::shutdown() and friends to ::force_requests_to_complete() and improve shutdown testing.

Approved by PS Jenkins bot, Kevin DuBois, Alan Griffiths.

601. By Daniel van Vugt

Make client API function names more consistent so that they follow the
convention: namespace_class_method(Class *x, ...).

Approved by Kevin DuBois, Alexandros Frantzis, PS Jenkins bot.

600. By Daniel van Vugt

Don't waste time clearing a depth buffer we will never use. It just slows us
down.

Certainly many clients will use depth buffers, but the compositor should
never need one.

Approved by Kevin DuBois, Alan Griffiths, PS Jenkins bot.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/client/mir_basic_rpc_channel.cpp'
2--- src/client/mir_basic_rpc_channel.cpp 2013-04-11 22:47:09 +0000
3+++ src/client/mir_basic_rpc_channel.cpp 2013-04-19 09:49:28 +0000
4@@ -92,7 +92,7 @@
5 mir::protobuf::wire::Invocation invoke;
6
7 invoke.set_id(next_id());
8- invoke.set_method_name(method->name());
9+ invoke.set_method_index(method->index());
10 invoke.set_parameters(buffer.str());
11
12 return invoke;
13
14=== modified file 'src/server/frontend/protobuf_message_processor.cpp'
15--- src/server/frontend/protobuf_message_processor.cpp 2013-04-16 09:08:29 +0000
16+++ src/server/frontend/protobuf_message_processor.cpp 2013-04-19 09:49:28 +0000
17@@ -19,10 +19,11 @@
18 #include "protobuf_message_processor.h"
19 #include "mir/frontend/message_processor_report.h"
20 #include "mir/frontend/resource_cache.h"
21-
22+#include <google/protobuf/descriptor.h>
23 #include <boost/exception/diagnostic_information.hpp>
24
25 #include <sstream>
26+#include <cassert>
27
28 namespace mfd = mir::frontend::detail;
29
30@@ -145,55 +146,64 @@
31
32 bool mfd::ProtobufMessageProcessor::dispatch(mir::protobuf::wire::Invocation const& invocation)
33 {
34- report->received_invocation(display_server.get(), invocation.id(), invocation.method_name());
35+ using namespace ::google::protobuf;
36+ const ServiceDescriptor *service = display_server->GetDescriptor();
37+ int index = invocation.method_index();
38+ const MethodDescriptor *method = service->method(index);
39+ const std::string name = method ? method->name() : to_string(index);
40+
41+ report->received_invocation(display_server.get(), invocation.id(), name);
42
43 bool result = true;
44
45 try
46 {
47- // TODO comparing strings in an if-else chain isn't efficient.
48- // It is probably possible to generate a Trie at compile time.
49- if ("connect" == invocation.method_name())
50- {
51+ switch (index)
52+ { // One feature Protobuf is missing is enums for these. So use ints..
53+ case 0:
54+ assert(name == "connect");
55 invoke(&protobuf::DisplayServer::connect, invocation);
56- }
57- else if ("create_surface" == invocation.method_name())
58- {
59+ break;
60+ case 1:
61+ assert(name == "disconnect");
62+ invoke(&protobuf::DisplayServer::disconnect, invocation);
63+ result = false;
64+ break;
65+ case 2:
66+ assert(name == "create_surface");
67 invoke(&protobuf::DisplayServer::create_surface, invocation);
68- }
69- else if ("next_buffer" == invocation.method_name())
70- {
71+ break;
72+ case 3:
73+ assert(name == "next_buffer");
74 invoke(&protobuf::DisplayServer::next_buffer, invocation);
75- }
76- else if ("release_surface" == invocation.method_name())
77- {
78+ break;
79+ case 4:
80+ assert(name == "release_surface");
81 invoke(&protobuf::DisplayServer::release_surface, invocation);
82- }
83- else if ("test_file_descriptors" == invocation.method_name())
84- {
85- invoke(&protobuf::DisplayServer::test_file_descriptors, invocation);
86- }
87- else if ("drm_auth_magic" == invocation.method_name())
88- {
89+ break;
90+ case 5:
91+ assert(name == "select_focus_by_lightdm_id");
92+ invoke(&protobuf::DisplayServer::select_focus_by_lightdm_id,
93+ invocation);
94+ break;
95+ case 6:
96+ assert(name == "drm_auth_magic");
97 invoke(&protobuf::DisplayServer::drm_auth_magic, invocation);
98- }
99- else if ("select_focus_by_lightdm_id" == invocation.method_name())
100- {
101- invoke(&protobuf::DisplayServer::select_focus_by_lightdm_id, invocation);
102- }
103- else if ("configure_surface" == invocation.method_name())
104- {
105+ break;
106+ case 7:
107+ assert(name == "test_file_descriptors");
108+ invoke(&protobuf::DisplayServer::test_file_descriptors,
109+ invocation);
110+ break;
111+ case 8:
112+ assert(name == "configure_surface");
113 invoke(&protobuf::DisplayServer::configure_surface, invocation);
114- }
115- else if ("disconnect" == invocation.method_name())
116- {
117- invoke(&protobuf::DisplayServer::disconnect, invocation);
118- result = false;
119- }
120- else
121- {
122- report->unknown_method(display_server.get(), invocation.id(), invocation.method_name());
123- result = false;
124+ break;
125+ default:
126+ report->unknown_method(display_server.get(), invocation.id(),
127+ name);
128+ result = false;
129+ break;
130 }
131 }
132 catch (std::exception const& error)
133
134=== modified file 'src/shared/protobuf/mir_protobuf_wire.proto'
135--- src/shared/protobuf/mir_protobuf_wire.proto 2012-09-14 12:03:52 +0000
136+++ src/shared/protobuf/mir_protobuf_wire.proto 2013-04-19 09:49:28 +0000
137@@ -2,7 +2,7 @@
138
139 message Invocation {
140 required uint32 id = 1;
141- required string method_name = 2;
142+ required int32 method_index = 2;
143 required bytes parameters = 3;
144 }
145

Subscribers

People subscribed via source and target branches