Re: [capnproto] RPC: simple return values and a "finish" roundtrip

2017-08-11 Thread 'Kenton Varda' via Cap'n Proto
Hi Tomáš,

I think a flag in Return will work better than one in Call because the
library doesn't know whether the caller plans to use pipelining at the time
that the Call is sent, but on the callee end the library definitely knows
when the results don't contain any capabilities.

I think this would be a good optimization to implement.

I would add a field to Return like:

finishNeeded @8 :Bool = true;


Doc comment:

If true, the receiver must send a Finish message for this call in order to
release resources and before reusing the question ID. If false, then a
Finish message is optional; the receiver can choose not to send a Finish
message, in which case it is free to reuse the question ID in a new Call
immediately.

This is useful to implement an optimization: If the call results contain no
capabilities, then there's no need for the callee to retain any state about
the call after the Return message is sent, and therefore no reason for the
caller to send a Finish. Any attempts to pipeline on the original call are
clearly invalid (because there's nothing to pipeline on), and there are no
capabilities that need to be released.


Then update whichever implementations you care about. Note that Python uses
the C++ implementation. rpc.c++ is... pretty complicated, but it might not
be too hard to add this flag. You'll also want to add a test, of course.

Alternatively, file an issue and I'll implement it when I have a chance.

-Kenton

On Wed, Aug 9, 2017 at 9:24 AM, Tomáš Gavenčiak  wrote:

> Hi Kenton,
>
> thanks for the quick reply and clarification! I was not 100% sure the
> server-side result (without capabilities) may not be reused in some way. I
> was thinking about some flag system and I like your solution. (I was
> thinking about a caller-set feature flag in addition but it is likely not
> necessary).
>
> How can I help with specifying and implementing this? I would be happy to
> give it a shot but would be grateful for some guidance. And how does it
> align with any future plans you have for capnp?
>
> All the best,
> Tomáš
>
> On Tue, Aug 8, 2017 at 6:24 PM, Kenton Varda 
> wrote:
>
>> Hi Tomáš,
>>
>> Indeed, there may be some room for optimization here. It's a little
>> tricky since *normally* the rule is that Question table entries are
>> allocated and freed strictly by the caller, hence requiring a Call and a
>> Finish. If we allow releasing a table entry to happen on the opposite side
>> from allocation (as we do with the export/import tables) then we have to
>> think carefully about race conditions.
>>
>> Perhaps we could add a bool to Return which allows the callee to say: "I
>> don't need you to send a Finish." The callee would only set this bool in
>> cases where there are no capabilities at all in the results. It would mark
>> the table entry as "optimistically freed"* and could release all associated
>> resources.
>>
>> The caller would still be allowed to send a Finish message, which it
>> might do for two reasons:
>> - Because it sent Finish before it had received Return, in an attempt to
>> cancel the call.
>> - Because it doesn't implement the new flag, so always sends Finish.
>>
>> So the callee should be prepared to receive a Finish for an
>> "optimistically freed" table entry, in which case it changes the table
>> entry's state to plain "free". It should also be prepared to receive no
>> Finish, which means it may later receive a Call that re-allocates the table
>> entry.
>>
>> Also, of course, the callee may receive promise-pipeline messages
>> referencing this table entry. This would happen if the caller *expected*
>> the results to contain a capability, which could be the case even if the
>> results ultimately did not contain any such entry. In this case the callee
>> would treat any pipelining attempts as if they were trying to pipeline on a
>> null capability.
>>
>> I think this could work, but to be sure I'd have to review all the other
>> places where question IDs are referenced.
>>
>> * Technically, it's not necessary for "optimistically freed" and "free"
>> to be separate states, but at least for common low-numbered table entries
>> this should be "almost free" to store and may help catch bugs.
>>
>> -Kenton
>>
>> On Tue, Aug 8, 2017 at 1:40 AM,  wrote:
>>
>>> Hi everyone,
>>>
>>> I apologize in advance if I have missed this in the docs or other
>>> thread, but I have not been able to understand why, when a method gets
>>> called, there are three packets being sent: call (@2), return (@3), finish
>>> (@4) even if no capabilities are involved (except for the bootstrap). The
>>> setup I have used is just plain "Hello world" type bootstrap interface like
>>> "interface Hello { hello @0 (a :Text) -> (a :Text); }" and I saw it in
>>> Python, C++ and Rust. (Same effect with any numeric call/return type).
>>> (Observing the network traffic with wireshark.)
>>>
>>> Why is there the need for a finish message even when the 

[capnproto] RPC: simple return values and a "finish" roundtrip

2017-08-08 Thread gavento
Hi everyone,

I apologize in advance if I have missed this in the docs or other thread, 
but I have not been able to understand why, when a method gets called, 
there are three packets being sent: call (@2), return (@3), finish (@4) 
even if no capabilities are involved (except for the bootstrap). The setup 
I have used is just plain "Hello world" type bootstrap interface like 
"interface Hello { hello @0 (a :Text) -> (a :Text); }" and I saw it in 
Python, C++ and Rust. (Same effect with any numeric call/return type). 
(Observing the network traffic with wireshark.)

Why is there the need for a finish message even when the returned content 
contains no capabilities? (I figure that message may only point to caps 
declared in its capTable.)

When the return payload contains no capability, is it possible to somehow 
reuse the server-side content? (I did not figure out how, wireshark shows 
the data being sent back and forth.) Is anything from the reply actually 
stored server-side after the server sends the return without caps?

Until the client does delete the replied payload (for example because it 
wants to keep the data in capnp without copying),,the finish is not sent 
which might require the server to retain some info on the call (used ID? or 
even the data?), even though I have not found it in the sources.

(I believe it is not because of IDs, as for every client independently, if 
the server receives e.g. an abort (actually a finish (@4)) with an ID it 
has not receiver a call it has not returned yet, it can be sure the abort 
is meant for an ID it has returned recently and can ignore the abort.)

Note that this is not a big performance problem for my use-case but since 
we are mostly sending simple one-time messages between long-lived caps, it 
seems like a waste.

Thanks for any clarification and all the great work!
Tomáš Gavenčiak


-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to capnproto+unsubscr...@googlegroups.com.
Visit this group at https://groups.google.com/group/capnproto.