HashMap vs memcached vs jdbc 性能比較

ConcurrentHashMapとmemcachedjdbcの性能比較を行いました。memcachedのクライアントライブラリは、com.dangaとnet.spyの両方で実施しました。

計測は、それぞれ100万件のデータを生成したり、読み取った時間です。単位はmsecです。

対象 Create Bulk Create Read Bulk Read
ConcurrentHashMap 4,586 --- 859 ---
Memcache(com.danga) 422,290 216,359 592,190 90,960
Memcache(net.spy) 60,074 --- 425,191 49,515
jdbc(mysql) --- 88,974 654,895 11,554


計測時の注意点を列挙します。

  • com.dangaのmemcachedの「Bulk Create」は、複数スレッドでsetを実行し、最後にスレッドをshutdownしてすべてのスレッドが停止するまで待っています。
  • net.spymemcachedクライアントの「Create」は非同期APIです。同期系のsetのAPIは用意されていません。
  • jdbcの「Read」は、select * from test_users where id = ? で20000回計測し、それを5倍しました。
    id:sh2さんご指摘ありがとうございました。
  • jdbcの「Bulk Read」は'select * from test_users where ? < id and id <= ?'で10000件ずつ取得しました。

ConcurrentHashMapを1としてそれぞれどの程度遅いかの比較表です。

  • memcachedが速いとよく言われていますが、ローカルで動作するConcurrentHashMapと比較すると約495倍も遅いです。
  • net.spyとcom.dangaのライブラリの速度の違いは大きいですね。
  • 「Bulk Read」に関しては、jdbcの方がmemcachedより速いです。もしかするとmemcachedでは、シリアライズやデシリアライズのオーバヘッドが大きいのでしょうか?

対象 Create Bulk Create Read Bulk Read
ConcurrentHashMap 1 --- 1 ---
Memcache(com.danga) 92 47 689 105
Memcache(net.spy) 13 --- 495 10
jdbc(mysql) --- 19 762 13

計測用コード

public class User implements Serializable {
  String name;
  String uri;
  public User(String name){
    this.name = name; 
    this.uri = name + "@example.com";
  }
}

jdbc(mysql)では以下のテーブルを用いて計測しました。

create table if not exists test_users(
  id integer auto_increment not null,
  name varchar(128),
  uri varchar(128),
  index (name),
  index (uri),
  primary key (id)) ENGINE=InnoDB;

基本情報

  • 測定用PC
  • memcachedMySQL用のサーバ
  • ネットワーク環境
    100MbpsのSW-HUBに接続
  • 計測対象
    • ConcurrentHashMapは、測定用PCで計測
    • memcachedは、Fedora10で動作しており、ネットワーク経由でアクセス。
    • MySQLは、Fedora10で動作しており、ネットワーク経由でアクセス。