Can you tell us a bit about the code-- are you using asynchronous operations? Also, a bit more about the workload generation?
First, about the code, note that in the 1.4 client some operations like .get() are synchronous where other operations like .set() are asynchronous (returning a Future). If you port from 1.4 to 2.2 and replace simple .set() calls with simple .upsert() calls, you’re going from asynchronous to synchronous operations. and that would have a big difference.
In 2.x, we changed to separating the synchronous and asynchronous APIs pretty cleanly because the 1.x would frequently confuse people. The new SDK is more clear about what you’re doing.
Second, we have been doing our own performance testing and one thing that we’ve noted is that compared to the 1.4 client we do have some intermittently higher latencies. The median and 95th percentile latencies are pretty much the same.
The reason I asked about this in context of workload is that if the workload is a set of simple loops doing synchronous operations and occasionally hits these latencies, you’d see a drop in throughput. If, on the other hand, you’re doing event driven operations or you’re running a more normal app server with an interactive workload of a lot of users occasionally making calls, the overall difference would be negligible since it’d be a small bit of latency that occasionally affects one user. To give you an idea of this difference, it’s 595µsec compared to 797µsec at 99th percentile but that gets up to 36ms at max. These are things a real person probably wouldn’t notice, but a tight loop in a test could see a big swing in throughput.
We have some thoughts in mind on how to get back to consistently low latencies, but it will probably take a bit of time.