Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
e1e3d140
Commit
e1e3d140
authored
Dec 14, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of github.com:kentonv/capnproto
parents
c70c6d38
32836bb3
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
96 additions
and
5 deletions
+96
-5
2013-12-12-capnproto-0.4-time-travel.md
doc/_posts/2013-12-12-capnproto-0.4-time-travel.md
+9
-1
2013-12-13-promise-pipelining-capnproto-vs-ice.md
doc/_posts/2013-12-13-promise-pipelining-capnproto-vs-ice.md
+76
-0
capnp-vs-ice.png
doc/images/capnp-vs-ice.png
+0
-0
capnp-vs-thrift-vs-ice.png
doc/images/capnp-vs-thrift-vs-ice.png
+0
-0
rpc.md
doc/rpc.md
+11
-4
No files found.
doc/_posts/2013-12-12-capnproto-0.4-time-travel.md
View file @
e1e3d140
...
@@ -24,10 +24,18 @@ _UPDATE: There has been some confusion about what I'm claiming. I am NOT sayin
...
@@ -24,10 +24,18 @@ _UPDATE: There has been some confusion about what I'm claiming. I am NOT sayin
promises alone (i.e. being asynchronous) constitutes "time travel". Cap'n Proto implements a
promises alone (i.e. being asynchronous) constitutes "time travel". Cap'n Proto implements a
technique called Promise Pipelining which allows a new request to be formed based on the content
technique called Promise Pipelining which allows a new request to be formed based on the content
of a previous result (in part or in whole) before that previous result is returned. Notice in the
of a previous result (in part or in whole) before that previous result is returned. Notice in the
diagram that the result of foo() is being passed to bar()._
diagram that the result of foo() is being passed to bar(). Please
[
see the docs
](
{{
site.baseurl }}rpc.html) or
[
check out the calculator example
](
https://github.com/kentonv/capnproto/blob/master/c++/samples
)
for more._
### Promises in C++
### Promises in C++
_UPDATE: More confusion. This section is
**not**
about pipelining ("time travel"). This section
is just talking about implementing a promise API in C++. Pipelining is another feature on top of
that. Please
[
see the RPC page
](
{{
site.baseurl }}rpc.html) if you want to know more about
pipelining._
If you do a lot of serious Javascript programming, you've probably heard of
If you do a lot of serious Javascript programming, you've probably heard of
[
Promises/A+
](
http://promisesaplus.com/
)
and similar proposals. Cap'n Proto RPC introduces a
[
Promises/A+
](
http://promisesaplus.com/
)
and similar proposals. Cap'n Proto RPC introduces a
similar construct in C++. In fact, the API is nearly identical, and its semantics are nearly
similar construct in C++. In fact, the API is nearly identical, and its semantics are nearly
...
...
doc/_posts/2013-12-13-promise-pipelining-capnproto-vs-ice.md
0 → 100644
View file @
e1e3d140
---
layout
:
post
title
:
"
Promise
Pipelining
and
Dependent
Calls:
Cap'n
Proto
vs.
Thrift
vs.
Ice"
author
:
kentonv
---
_UPDATED: Added Thrift to the comparison._
So, I totally botched the 0.4 release announcement yesterday. I was excited about promise
pipelining, but I wasn't sure how to describe it in headline form. I decided to be a bit
silly and call it "time travel", tongue-in-cheek. My hope was that people would then be
curious, read the docs, find out that this is actually a really cool feature, and start doing
stuff with it.
Unfortunately,
[
my post
](
2013-12-12-capnproto-0.4-time-travel.html
)
only contained a link to
the full explanation and then confusingly followed the "time travel" section with a separate section
describing the fact that I had implemented a promise API in C++. Half the readers clicked through
to the documentation and understood. The other half thought I was claiming that promises alone
constituted "time travel", and thought I was ridiculously over-hyping an already-well-known
technique. My HN post was subsequently flagged into oblivion.
Let me be clear:
**Promises alone are _not_ what I meant by "time travel"!**
<img
src=
'{{ site.baseurl }}images/capnp-vs-thrift-vs-ice.png'
style=
'width:350px; height:275px; float: right;'
>
So what did I mean? Perhaps
[
this benchmark
](
https://github.com/kentonv/capnp-vs-ice
)
will
make things clearer. Here, I've defined a server that exports a simple four-function calculator
interface, with
`add()`
,
`sub()`
,
`mult()`
, and
`div()`
calls, each taking two integers and
\
returning a result.
You are probably already thinking: That's a ridiculously bad way to define an RPC interface!
You want to have _one_ method
`eval()`
that takes an expression tree (or graph, even), otherwise
you will have ridiculous latency. But this is exactly the point.
**
With promise pipelining, simple,
composable methods work fine.
**
To prove the point, I've implemented servers in Cap'n Proto,
[
Apache Thrift
](
http://thrift.apache.org/
)
,
and
[
ZeroC Ice
](
http://www.zeroc.com/
)
. I then implemented clients against each one, where the
client attempts to evaluate the expression:
((5 * 2) + ((7 - 3) * 10)) / (6 - 4)
All three frameworks support asynchronous calls with a promise/future-like interface, and all of my
clients use these interfaces to parallelize calls. However, notice that even with parallelization,
it takes four steps to compute the result:
# Even with parallelization, this takes four steps!
((5 * 2) + ((7 - 3) * 10)) / (6 - 4)
(10 + ( 4 * 10)) / 2 # 1
(10 + 40) / 2 # 2
50 / 2 # 3
25 # 4
As such, the Thrift and Ice clients take four network round trips. Cap'n Proto, however, takes
only one.
Cap'n Proto, you see, sends all six calls from the client to the server at one time. For the
latter calls, it simply tells the server to substitute the former calls' results into the new
requests, once those dependency calls finish. Typical RPC systems can only send three calls to
start, then must wait for some to finish before it can continue with the remaining calls. Over
a high-latency connection, this means they take 4x longer than Cap'n Proto to do their work in
this test.
So, does this matter outside of a contrived example case? Yes, it does, because it allows you to
write cleaner interfaces with simple, composable methods, rather than monster do-everything-at-once
methods. The four-method calculator interface is much simpler than one involving sending an
expression graph to the server in one batch. Moreover, pipelining allows you to define
object-oriented interfaces where you might otherwise be tempted to settle for singletons. See
[
my extended argument
](
{{
site.baseurl }}rpc.html#introduction) (this is what I was trying to get
people to click on yesterday :) ).
Hopefully now it is clearer what I was trying to illustrate with this diagram, and what I meant
by "time travel"!
<img
src=
'{{ site.baseurl }}images/time-travel.png'
style=
'max-width:639px'
>
doc/images/capnp-vs-ice.png
0 → 100644
View file @
e1e3d140
7.1 KB
doc/images/capnp-vs-thrift-vs-ice.png
0 → 100644
View file @
e1e3d140
8.38 KB
doc/rpc.md
View file @
e1e3d140
...
@@ -83,10 +83,12 @@ file `foo` in directory `bar` takes four round trips!
...
@@ -83,10 +83,12 @@ file `foo` in directory `bar` takes four round trips!
{% highlight python %}
{% highlight python %}
# pseudocode
# pseudocode
foo = root.open("foo"); # 1
bar = root.open("bar"); # 1
bar = foo.open("bar"); # 2
foo = bar.open("foo"); # 2
size = bar.size(); # 3
size = foo.size(); # 3
data = bar.read(0, size); # 4
data = foo.read(0, size); # 4
# The above is four calls but takes only one network
# round trip with Cap'n Proto!
{% endhighlight %}
{% endhighlight %}
In such a high-latency scenario, making your interface elegant is simply not worth 4x the latency.
In such a high-latency scenario, making your interface elegant is simply not worth 4x the latency.
...
@@ -137,6 +139,11 @@ need to change our interface at all. We keep our simple, elegant, singleton-fre
...
@@ -137,6 +139,11 @@ need to change our interface at all. We keep our simple, elegant, singleton-fre
don't have to implement path strings, caching, authentication, or authorization, and yet everything
don't have to implement path strings, caching, authentication, or authorization, and yet everything
performs as well as we can possibly hope for.
performs as well as we can possibly hope for.
#### Example code
[
The calculator example
](
https://github.com/kentonv/capnproto/blob/master/c++/samples/calculator-client.c++
)
uses promise pipelining. Take a look at the client side in particular.
### Distributed Objects
### Distributed Objects
As you've noticed by now, Cap'n Proto RPC is a distributed object protocol. Interface references --
As you've noticed by now, Cap'n Proto RPC is a distributed object protocol. Interface references --
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment