Posted on

Tim[后端技术]

Tim's blog, 关于后端架构、互联网技术、分布式、大型网络应用、NoSQL、技术感悟等

Tuesday, Aug 11th, 2009 by Tim | Tags: English, memcachedb, redis, tokyo cabinet, tokyo tyrant

I had tested the following key-value store for set() and get()

1. Test environment

1.1 Hardware/OS

2 Linux boxes in a LAN, 1 server and 1 test client Linux Centos 5.2 64bit Intel(R) Xeon(R) CPU E5410 @ 2.33GHz (L2 cache: 6M), Quad-Core /* 2 8G memory SCSI disk (standalone disk, no other access)

1.2 Software version

db-4.7.25.tar.gz libevent-1.4.11-stable.tar.gz memcached-1.2.8.tar.gz memcachedb-1.2.1-beta.tar.gz redis-0.900_2.tar.gz tokyocabinet-1.4.9.tar.gz tokyotyrant-1.1.9.tar.gz

1.3 Configuration

Memcachedb startup parameter Test 100 bytes ./memcachedb -H /data5/kvtest/bdb/data -d -p 11212 -m 2048 -N -L 8192 (Update: As mentioned by Steve, the 100-byte-test missed the -N paramter, so I added it and updated the data) Test 20k bytes ./memcachedb -H /data5/kvtest/mcdb/data -d -p 11212 -b 21000 -N -m 2048

Tokyo Tyrant (Tokyo Cabinet) configuration Use default Tokyo Tyrant sbin/ttservctl use .tch database, hashtable database

ulimsiz=”256m” sid=1 dbname=”$basedir/casket.tch/#bnum=50000000″ /# default 1M is not enough! maxcon=”65536″ retval=0 Redis configuration timeout 300 save 900 1 save 300 10 save 60 10000 /# no maxmemory settings 1.4 Test client Client in Java, JDK1.6.0, 16 threads Use Memcached client java_memcached-release_2.0.1.jar JRedis client for Redis test, another JDBC-Redis has poor performance. 2. Small data size test result Test 1, 1-5,000,000 as key, 100 bytes string value, do set, then get test, all get test has result. Request per second(mean)") Store Write Read Memcached 55,989 50,974 Memcachedb 25,583 35,260 Tokyo Tyrant 42,988 46,238 Redis 85,765 71,708 Server Load Average Store Write Read Memcached 1.80, 1.53, 0.87 1.17, 1.16, 0.83 MemcacheDB 1.44, 0.93, 0.64 4.35, 1.94, 1.05 Tokyo Tyrant 3.70, 1.71, 1.14 2.98, 1.81, 1.26 Redis 1.06, 0.32, 0.18 1.56, 1.00, 0.54 3. Larger data size test result Test 2, 1-500,000 as key, 20k bytes string value, do set, then get test, all get test has result. Request per second(mean) (Aug 13 Update: fixed a bug on get() that read non-exist key) ") Store Write Read Memcachedb 357 327 Tokyo Tyrant 3,501 257 Redis 1,542 957 4. Some notes about the test When test Redis server, the memory goes up steadily, consumed all 8G and then use swap(and write speed slow down), after all memory and swap space is used, the client will get exceptions. So use Redis in a productive environment should limit to a small data size. It is another cache solution rather than a persistent storage. So compare Redis together with MemcacheDB/TC may not fair because Redis actually does not save data to disk during the test. Tokyo cabinet and memcachedb are very stable during heavy load, use very little memory in set test and less than physical memory in get test. MemcacheDB peformance is poor for write large data size(20k). The call response time was not monitored in this test. 101 Comments » 1. Leechael says: Aug 12th 2009 at 04:47 这次的测试结果显然更新了，虽然还是不敌，不过这次 TT/TC write 的性能显然提高了。 1. Brendan O'Connor says: Aug 12th 2009 at 11:32 very interesting, thanks! 1. Jon Hancock says: Aug 13th 2009 at 00:46 good info. One thing missing in these types of comparisons is a baseline against an RDB. Adding postgres 8.4 to this comparison might help. 1. vicaya says: Aug 13th 2009 at 03:28 You should really test memcached 1.4.0, which actually can use multi-cores. 1. Asaf says: Aug 13th 2009 at 03:51 Thanks for the info, Can you please detail the ratio of read / write operations and the order of the operations? did you first write all the data than read all the data or was it intermittent? 1. Tim says: Aug 13th 2009 at 14:39 @asaf I do read test after finish all writes. Write test: key: 1-5,000,000 value: 100-byte-string After write all, then do read test client.get(random(5,000,000)); 1. Joshua Zhu says: Aug 13th 2009 at 16:51 This benchmark is very helpful to me in evaluating those K/V stores. Thanks a lot. 1. Guo Du says: Aug 13th 2009 at 19:31 Very interesting result. Any significant cpu usage difference between those stores? 1. Joubin says: Aug 14th 2009 at 10:08 Hi Tim, Thanks for the test! Just curious: 1) Try changing the tcp buffer sizes in class org.jredis.ri.alphazero.connection.ConnectionBase$DefaultConnectionBase. On my mac, the default values are always fairly quite large so perhaps this is something that was missed:

change the tcp rcv and snd buffer size values:

public static final class DefaultConnectionSpec implements ConnectionSpec {

/// // private static final int DEFAULT_RCV_BUFF_SIZE = 1024 / 48; // << increased /// // private static final int DEFAULT_SND_BUFF_SIZE = 1024 / 48; // << increased

2) May also try changing the tcp socket prefs (same inner class):

Try this:

public static final class DefaultConnectionSpec implements ConnectionSpec { …

@Override public Integer getSocketProperty(SocketProperty property) { int value = 0; switch (property){ case SO_PREF_BANDWIDTH: value = 0; // changed break; case SO_PREF_CONN_TIME: value = 2; break; case SO_PREF_LATENCY: value = 1; // changed break; case SO_RCVBUF: value = DEFAULT_RCV_BUFF_SIZE; break; case SO_SNDBUF: value = DEFAULT_SND_BUFF_SIZE; break; case SO_TIMEOUT: value = DEFAULT_READ_TIMEOUT_MSEC; break; } return value; } … }

I assume you’ve downloaded the full distribution from github. “mvn install” to build and run the test again. Curious to see if it makes any diffs. That fails we’ll try switching to buffered io streams.

/R

1. Gabriel says:

Aug 15th 2009 at 02:30

Can you post the actual model/# for the Xeon CPU along with operating frequency?

1. Tim says:

Aug 17th 2009 at 16:45

@Joubin I’ve changed DEFAULT_RCV_BUFF_SIZE/DEFAULT_SND_BUFF_SIZE from 48k to 256k, both for small data size and larger data size, but there is not significant improvement. The bottleneck here may not on the client side.

1. mongofan says:

Aug 19th 2009 at 07:47

hi Tim very nice!

can you add mongodb to the benchmark? I would love to see how it performs against redis

1. Joubin says:

Aug 23rd 2009 at 22:04

Tim,

Thanks. That confirms my owns tests that stressed on just one key to isolate the client overhead.

A cursory look at the TT’s Java client seems to indicate that payloads are gzip’d (which JRedis does not, given that the baseline assumption is that you may be using a variety of clients for your db, in which case client specific optimizations are not viable unless the compression algorithm is shared by all client types.)

I’ll update when I have something to add here, but safe assumption here is that compressing the 20K payload has a significant positive impact on the performance of the TT setup.

1. arden says:

Sep 3rd 2009 at 11:44

redis有没有象memcached这样的过期时间设置？

1. Jonathan says:

Sep 11th 2009 at 04:37

I assume this tests write once?

You may see something interesting from Tokyo Tyrant if you test modification in random order. Write performance should drop to match read performance.

1. Henry says:

Oct 3rd 2009 at 06:10

Thanks for the Test, we will test Redis in one of the next Projects

1. Gregory Burd says:

Nov 19th 2009 at 03:12

To match Redis’s durability (“D” in ACID) using Berkeley DB simply set the DB_TXN flags to DB_TXN_NOSYNC. A transaction will be consider “durable” when the data is flushed from the log-buffers in-memory to the operating system’s filesystem buffers rather than waiting for the disk to actually write the data (which is much slower). There are many other configuration parameters that can be tuned, you don’t list them in your description so I can’t say if they were optimal or not (really, “auto-tuning” a database is something that BDB should do for you, but we’re not there yet). If these tests run entirely in cache (can load the entire dataset into memory) then this isn’t a realistic scenario, increase the dataset until the data is 10x the cache size. Also, as someone mentioned you may want to test under a highly concurrent, and highly contentious workload as that will push the locking systems and create very different results. Finally, update to Berkeley DB 4.8. In 4.8 we’ve dramatically improved our locking subsystem for modern multi-core CPU architectures.

Benchmarks are always tricky. Apples-to-apples tests are rare because they are hard to design and harder to run. There is almost always some degree of bias or some overlooked element. It’s unavoidable. That said, benchmarks do serve a purpose so thank you for doing the tests. We hope that you do more. We’re always looking for ways to improve performance.

-greg

Berkeley DB Product Manager, Oracle Corp

1. Tim says:

Nov 20th 2009 at 11:16

Greg, already enable DB_TXN_NOSYNC by add -N to memcachedb in this test. Will evaluated bdb 4.8

1. Tim says:

Nov 25th 2009 at 09:47

Greg, tested bdb 4.8, there is significant improvent. Great! but after I compare with TC(tokyocabinet-1.4.39.tar.gz) and TT(tokyotyrant-1.1.37.tar.gz) new version, they also had improvement, so the result doesn’t changed much.

FYI, I’ve tested read/write 100 byte with 50 threads, the request per second result are, Tokyo Tyrant(Tokyo Cabinet) Write 54,189, Read 73,384 Memcachedb(Berkekey DB 4.8) Write 32,985 Read 59,178 Memcached Write 103,242, Read 106,102

Because the new test donen’t change the situation, the test in blog post still make sense.

1. eric says:

Jan 6th 2010 at 13:45

1. focusheart says:

Feb 26th 2010 at 10:25

Redis应用在一个多层的存储结构中用来处理经常发生变化的数据部分很合适，存储结构的层次不同，适用不同的解决方案。

1. faryang says:

Jul 2nd 2010 at 00:15

1. jtong11 says:

Mar 17th 2011 at 16:36

1. Louis says:

Mar 23rd 2012 at 17:20

I am a newer for Redis.Can I just ask a primary question?How did you get the value of Request per second?

1. hunter says:

Oct 11th 2012 at 20:42