1--- 2layout: post 3title: "Promise Pipelining and Dependent Calls: Cap'n Proto vs. Thrift vs. Ice" 4author: kentonv 5--- 6 7_UPDATED: Added Thrift to the comparison._ 8 9So, I totally botched the 0.4 release announcement yesterday. I was excited about promise 10pipelining, but I wasn't sure how to describe it in headline form. I decided to be a bit 11silly and call it "time travel", tongue-in-cheek. My hope was that people would then be 12curious, read the docs, find out that this is actually a really cool feature, and start doing 13stuff with it. 14 15Unfortunately, [my post](2013-12-12-capnproto-0.4-time-travel.html) only contained a link to 16the full explanation and then confusingly followed the "time travel" section with a separate section 17describing the fact that I had implemented a promise API in C++. Half the readers clicked through 18to the documentation and understood. The other half thought I was claiming that promises alone 19constituted "time travel", and thought I was ridiculously over-hyping an already-well-known 20technique. My HN post was subsequently flagged into oblivion. 21 22Let me be clear: 23 24**Promises alone are _not_ what I meant by "time travel"!** 25 26<img src='{{ site.baseurl }}images/capnp-vs-thrift-vs-ice.png' style='width:350px; height:275px; float: right;'> 27 28So what did I mean? Perhaps [this benchmark](https://github.com/kentonv/capnp-vs-ice) will 29make things clearer. Here, I've defined a server that exports a simple four-function calculator 30interface, with `add()`, `sub()`, `mult()`, and `div()` calls, each taking two integers and\ 31returning a result. 32 33You are probably already thinking: That's a ridiculously bad way to define an RPC interface! 34You want to have _one_ method `eval()` that takes an expression tree (or graph, even), otherwise 35you will have ridiculous latency. But this is exactly the point. **With promise pipelining, simple, 36composable methods work fine.** 37 38To prove the point, I've implemented servers in Cap'n Proto, [Apache Thrift](http://thrift.apache.org/), 39and [ZeroC Ice](http://www.zeroc.com/). I then implemented clients against each one, where the 40client attempts to evaluate the expression: 41 42 ((5 * 2) + ((7 - 3) * 10)) / (6 - 4) 43 44All three frameworks support asynchronous calls with a promise/future-like interface, and all of my 45clients use these interfaces to parallelize calls. However, notice that even with parallelization, 46it takes four steps to compute the result: 47 48 # Even with parallelization, this takes four steps! 49 ((5 * 2) + ((7 - 3) * 10)) / (6 - 4) 50 (10 + ( 4 * 10)) / 2 # 1 51 (10 + 40) / 2 # 2 52 50 / 2 # 3 53 25 # 4 54 55As such, the Thrift and Ice clients take four network round trips. Cap'n Proto, however, takes 56only one. 57 58Cap'n Proto, you see, sends all six calls from the client to the server at one time. For the 59latter calls, it simply tells the server to substitute the former calls' results into the new 60requests, once those dependency calls finish. Typical RPC systems can only send three calls to 61start, then must wait for some to finish before it can continue with the remaining calls. Over 62a high-latency connection, this means they take 4x longer than Cap'n Proto to do their work in 63this test. 64 65So, does this matter outside of a contrived example case? Yes, it does, because it allows you to 66write cleaner interfaces with simple, composable methods, rather than monster do-everything-at-once 67methods. The four-method calculator interface is much simpler than one involving sending an 68expression graph to the server in one batch. Moreover, pipelining allows you to define 69object-oriented interfaces where you might otherwise be tempted to settle for singletons. See 70[my extended argument]({{ site.baseurl }}rpc.html#introduction) (this is what I was trying to get 71people to click on yesterday :) ). 72 73Hopefully now it is clearer what I was trying to illustrate with this diagram, and what I meant 74by "time travel"! 75 76<img src='{{ site.baseurl }}images/time-travel.png' style='max-width:639px'> 77