Re: [capnproto] Re: CapnProto vs gRPC/Protobuf differences - semantics and use case

2023-03-27 Thread 'Kenton Varda' via Cap'n Proto
Hi Jonathan,

On Fri, Mar 17, 2023 at 2:10 PM Jonathan Shapiro 
wrote:

> I missed one under semantics:
>
>- capn-proto structs are defined as reference (pointer) types, while
>protobuf message types appear to be value types.
>
> Does capn-proto support the case where a single struct is referenced from
> multiple places? That is: does it support graphs as messages?
>

I think you might be confusing semantics vs. encoding details here. Structs
are *encoded* using a pointer that points to the content located elsewhere
in the message buffer. However, they nevertheless behave like value types.
The semantics are just about exactly the same as in Protobuf.

Cap'n Proto does not support graphs. Given the use of pointers, it may be
obvious how graphs would be encoded, if we supported them. The problem with
graphs is that they make so much else in the implementation vastly more
complicated. For example, say I do `message1.setFoo(message2.getFoo())`,
where `foo` has a struct type. We have to copy `foo` from one message
buffer into another. With trees, this is a trivial recursive operation. But
if graphs are allowed, now we must maintain a lookup table to remember
which pointers we've already followed. Moreover, if on the next line I do
`message1.setBar(message2.getBar())`, and it turns out `foo` and `bar` both
pointed to a common third object, how do we make sure we don't make a
redundant copy of that? It seems we now have to maintain a mapping table
long-term for any pair of messages for which copies have occurred.

On the use case front, it seems to me that the two are optimized for
>> different situations:
>>
>>- The gRPC+protobuf encoding scheme is optimized for use over lower
>>bandwidth links, but embeds the assumption that decoding upon receipt will
>>proceed linearly and to completion (because random access isn't
>>straightforward).
>>- The capn-proto encoding scheme is optimized for local area RPC
>>and/or out-of-process plugins, where communication bandwidth isn't much of
>>a limiting factor but efficient transmission (perhaps even by mmap) 
>> matters.
>>
>> Note that Cap'n Proto's serialization is not primarily designed for RPC
at all, and indeed most users use the serialization but not the RPC. The
serialization's biggest wins come when used as a format for large files
that are read using mmap().

When it comes to RPC, the serialization might lend itself nicely to
communications via shared memory, but I'm not sure if anyone has actually
tried that (yet).

I would not necessarily say that protoobuf is "optimized" for low
bandwidth. When using a low-bandwidth link, I would highly recommend
applying compression to either format, which will have greater impact than
Protobuf's encoding techniques (and will narrow the gap created by those
techniques).

-Kenton

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/CAJouXQkWkAEZLVH2zOvywB0pf1-56WMfviQf47E1xBa4Thi%3DmA%40mail.gmail.com.


Re: [capnproto] Re: Correctly revoking capabilities holding onto resources

2023-03-27 Thread 'Kenton Varda' via Cap'n Proto
Hi Rowan,

Sorry for the slow reply, my inbox is overloaded as always.

Indeed, since the `onRevoked` mechanism is triggered by a promise, the
actual revocation and cancellation occurs asynchronously. It's possible
that some other promise will be queued in between the point where you
resolve the revoker promise and when the revocation actually takes effect.

kj::Canceler has better behavior, in that all cancellation happens
synchronously. But, capnp::Membrane does not currently use that. I have
myself hit this a couple times and ended up using hacks like you suggest.

Perhaps we should extend MembranePolicy with `getCanceler()` that returns
`kj::Maybe`. If non-null, the canceler wraps all promises
and capabilities passed through the membrane.

-Kenton

On Mon, Mar 27, 2023 at 7:35 AM Rowan Reeve  wrote:

> I've added an ugly unit test to a branch on my GitHub to illustrate:
>
>
> https://github.com/capnproto/capnproto/compare/master...Zentren:capnproto:membrane_issue?expand=1#diff-49ad79a4fffcbe88fcd8681ec67d49f5f6e5fc9010961c1b10ef1b462f0e957eR477
>
> Note line 477 in *c++/src/capnp/membrane-test.c++* where I'd expect the
> request to have been cancelled as per membrane policy *onRevoked()* docs
> ("all outstanding calls cancelled"). Looking at the behavior, it seems like
> chained promises in the request are not cancelled as part of this (only the
> initial *call(CallContext)* IF we have not yet entered its body).
>
>
> Thanks,
>
> Rowan Reeve
> On Wednesday, March 15, 2023 at 3:42:39 PM UTC+2 Rowan Reeve wrote:
>
>> Hi Kenton,
>>
>> I am encountering a problem where capabilities acting as views over some
>> resources are intermittently causing segfaults. The capability is wrapped
>> using *capnp::membrane* given a membrane policy where the promise
>> returned by *onRevoked* can be rejected on-demand via a synchronous
>> reject function (a kj::PromiseFulfillerPair is used to do this).
>>
>> The resources may be destroyed together at any time, whereby the membrane
>> managing the capabilities accessing the resource states is revoked.
>> However, this does not seem to be an instantaneous operation (presumably
>> due to revocation being managed by a promise), and I have encountered the
>> following issue as a result:
>>
>> Unresolved requests made before the membrane policy has been revoked and
>> where the resource has since been destroyed are not cancelled but will
>> rather resolve, accessing invalid memory.
>>
>> The workaround I have found to address this issue is to add a flag and a
>> *kj::Canceller* to the capability implementations whereby new requests
>> are rejected if the flag is set, and in addition when the flag is first
>> set, the canceler cancels all returned promises in cases where a chained
>> promise was returned rather than *kj::READY_NOW*. However, this is very
>> ugly and necessitates keeping around references to the capability
>> implementations before they are converted to *::Client* objects (so that
>> we can set that flag). I'm thinking that surely there has to be a better
>> way I have not considered.
>>
>> Do you have any thoughts on a better solution to this problem? If needed,
>> I can try create a minimal reproducible example to illustrate.
>>
>> In case it matters, OS is Ubuntu 20.04 and capnp version is 8.0.0, both
>> currently contained by my production environment.
>>
>> Thank you for your time,
>>
>> Rowan Reeve
>>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/capnproto/2d126940-b82e-4ef8-9f41-304d8a23c97cn%40googlegroups.com
> 
> .
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/CAJouXQmWFtAf3XzqQgm-rZ76H_c5J3XB_p1YNLBT1pHkkZPqiQ%40mail.gmail.com.


[capnproto] Re: Correctly revoking capabilities holding onto resources

2023-03-27 Thread Rowan Reeve
I've added an ugly unit test to a branch on my GitHub to illustrate:

https://github.com/capnproto/capnproto/compare/master...Zentren:capnproto:membrane_issue?expand=1#diff-49ad79a4fffcbe88fcd8681ec67d49f5f6e5fc9010961c1b10ef1b462f0e957eR477

Note line 477 in *c++/src/capnp/membrane-test.c++* where I'd expect the 
request to have been cancelled as per membrane policy *onRevoked()* docs 
("all outstanding calls cancelled"). Looking at the behavior, it seems like 
chained promises in the request are not cancelled as part of this (only the 
initial *call(CallContext)* IF we have not yet entered its body).


Thanks,

Rowan Reeve
On Wednesday, March 15, 2023 at 3:42:39 PM UTC+2 Rowan Reeve wrote:

> Hi Kenton,
>
> I am encountering a problem where capabilities acting as views over some 
> resources are intermittently causing segfaults. The capability is wrapped 
> using *capnp::membrane* given a membrane policy where the promise 
> returned by *onRevoked* can be rejected on-demand via a synchronous 
> reject function (a kj::PromiseFulfillerPair is used to do this).
>
> The resources may be destroyed together at any time, whereby the membrane 
> managing the capabilities accessing the resource states is revoked. 
> However, this does not seem to be an instantaneous operation (presumably 
> due to revocation being managed by a promise), and I have encountered the 
> following issue as a result:
>
> Unresolved requests made before the membrane policy has been revoked and 
> where the resource has since been destroyed are not cancelled but will 
> rather resolve, accessing invalid memory.
>
> The workaround I have found to address this issue is to add a flag and a 
> *kj::Canceller* to the capability implementations whereby new requests 
> are rejected if the flag is set, and in addition when the flag is first 
> set, the canceler cancels all returned promises in cases where a chained 
> promise was returned rather than *kj::READY_NOW*. However, this is very 
> ugly and necessitates keeping around references to the capability 
> implementations before they are converted to *::Client* objects (so that 
> we can set that flag). I'm thinking that surely there has to be a better 
> way I have not considered.
>
> Do you have any thoughts on a better solution to this problem? If needed, 
> I can try create a minimal reproducible example to illustrate.
>
> In case it matters, OS is Ubuntu 20.04 and capnp version is 8.0.0, both 
> currently contained by my production environment.
>
> Thank you for your time,
>
> Rowan Reeve
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/2d126940-b82e-4ef8-9f41-304d8a23c97cn%40googlegroups.com.