dblock/mongoid-cached-json — pull request #8 by dblock (2013-01-17 19:56:20+00:00)
Title: @macreery => Don't query cache twice for the same keys.

You may encounter duplicate records in deeply nested or large collections of objects. For example, we return a collection of artworks that may have the same artist. Every time the artist is encountered, the cache is hit for the artist's JSON representation.

We avoid the second lookup by collecting a JSON partial first, then passing around a local JSON cache which is used to lookup data by the existing key.

Thanks to @macreery for the concept behind this.

## Benchmarks

The performance of this implementation in local testing is slightly worse, by about 15%, than the previous implementation, but the number of memcached GETs is significantly lower. I think it's worth spending 15% more time in Ruby and significantly reduce the number of network calls to memcached servers, which are a central bottleneck in any deployment.

In an Art.sy internal project I've setup a test that creates 100 artworks that belong to 2 artists (alternating) and the same partner. Then we query all artworks that belong to a partner, 100 times with a sliding window (artworks 1-20, 2-21, 3-22, etc.).

Between each runs we clear a local MemCached.

```
$ telnet localhost 11211
flush_all
stats reset
```

With mongoid-cached-json 1.3.0, via Grape and Mongoid, sample from 3 runs:

* 0.1296s per API call
* 0.1351
* 0.1356

Memcached stats:

```
STAT cmd_get 3463
STAT cmd_set 508
STAT get_hits 3156
STAT get_misses 307
STAT bytes_read 3134503
STAT bytes_written 2396571
STAT curr_items 3009
STAT total_items 508
```

This implementation.

```
0.1528 per API call
0.1461
0.1452
```

Memcached stats show half the number of `cmd_get`, so it works.

```
STAT cmd_get 1852
STAT cmd_set 508
STAT get_hits 1545
STAT get_misses 307
STAT bytes 13702639
STAT curr_items 3009
STAT total_items 508
```