RocksJava 在闪存上的性能

在14年4月,我们开始为RocksDB构建一个Java扩展。这个页面显示了RocksJava在闪存上的基准测试结果。这里可以找到RocksDB C++在闪存上的基准测试结果。(https://github.com/facebook/rocksdb/wiki/Performance-Benchmarks)

设置

所有的基准测试都在同一台机器上运行,以下是测试设置的细节:

  1. * 使用10亿个键/值对进行测试。每个键是16字节,每个值是800字节。数据库总原始大小为1TB
  2. * Intel(R) Xeon(R) CPU E5-2660 v2 @ 2.20GHz, 40
  3. * 25 MB CPU缓存,144 GB RAM 内存
  4. * CentOS release 5.2 (Final) 系统
  5. * 实验在 Funtoo chroot 环境下进行
  6. * g++ (Funtoo 4.8.1-r2) 4.8.1
  7. * Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
  8. * Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, 混合模式)
  9. * 实验采用Commit 85f9bb4
  10. * 1G rocksdb 块缓存
  11. * 压缩算法采用Snappy 1.1.1
  12. * 不使用 Jemalloc

按键按顺序批量加载(测试2)

这个基准测试使用RocksJava度量将1B键加载到数据库中的性能。键按顺序插入。在基准测试运行开始时,数据库是空的,并逐渐填满。 在数据加载过程中没有读取任何数据。下面是RocksJava的批量加载性能:

  1. fillseq : 2.48233 micros/op; 311.2 MB/s; 1000000000 ops done; 1 / 1 task(s) finished.

与我们在RocksDB的c++基准测试中所做的类似,RocksJava呗配置为使用多线程压缩,以便多个线程可以同时在多个级别压缩非常重叠的键范围。 我们的结果表明,RocksJava能够写300+ MB/s,或~400K每秒。

下面是使用RocksJava批量加载数据库的命令:

  1. bpl=10485760;overlap=10;mcz=0;del=300000000;levels=6;ctrig=4; delay=8; stop=12; wbn=3; mbc=20; mb=67108864;wbs=134217728; dds=0; sync=false; t=1; vs=800; bs=65536; cs=1048576; of=500000; si=1000000;
  2. ./jdb_bench.sh --benchmarks=fillseq --disable_seek_compaction=true --mmap_read=false --statistics=true --histogram=true --threads=$t --key_size=10 --value_size=$vs
  3. --block_size=$bs --cache_size=$cs --bloom_bits=10 --compression_type=snappy --cache_numshardbits=4 --open_files=$of --verify_checksum=true --db=/rocksdb-bench/java/b2
  4. --sync=$sync --disable_wal=true --stats_interval=$si --compression_ratio=0.50 --disable_data_sync=$dds --write_buffer_size=$wbs --target_file_size_base=$mb --max_write_buffer_number=$wbn
  5. --max_background_compactions=$mbc --level0_file_num_compaction_trigger=$ctrig --level0_slowdown_writes_trigger=$delay --level0_stop_writes_trigger=$stop --num_levels=$levels --delete_obsolete_files_period_micros=$del
  6. --max_grandparent_overlap_factor=$overlap --stats_per_interval=1 --max_bytes_for_level_base=$bpl --use_existing_db=false --cache_remove_scan_count_limit=16 --num=1000000000

随机读 (测试4)

这个基准测试测试了具有10亿个键的RocksJava的随机读取性能,其中每个键为16个字节,值分别为800个字节。 在这个基准测试中,RocksJava被配置为块大小为4KB,并且启用了Snappy压缩。基准测试应用程序中有32个线程向数据库发出随机读取。 此外,RocksJava被配置为在每次读取时验证校验和。

基准测试分两部分运行。在第一部分中,首先通过将所有1B键按顺序写入数据库,将数据加载到数据库中。加载完成后,将进入第二部分,其中32个线程将并发地发出随机读请求。我们只测量了第二部分性能。

  1. readrandom : 7.67180 micros/op; 101.4 MB/s; 1000000000 / 1000000000 found; 32 / 32 task(s) finished.

我们的结果表明,RocksJava能够读取100+MB/s,或者每秒处理大约130K的读取。

下面是用RocksJava运行基准测试时使用的命令:

  1. echo "Load 1B keys sequentially into database....."
  2. n=1000000000; r=1000000000; bpl=10485760;overlap=10;mcz=2;del=300000000;levels=6;ctrig=4; delay=8; stop=12; wbn=3; mbc=20; mb=67108864;wbs=134217728; dds=1; sync=false; t=1; vs=800; bs=4096; cs=1048576; of=500000; si=1000000;
  3. ./jdb_bench.sh --benchmarks=fillseq --disable_seek_compaction=true --mmap_read=false --statistics=true --histogram=true --num=$n --threads=$t --value_size=$vs --block_size=$bs --cache_size=$cs --bloom_bits=10
  4. --cache_numshardbits=6 --open_files=$of --verify_checksum=true --db=/rocksdb-bench/java/b4 --sync=$sync --disable_wal=true --compression_type=snappy --stats_interval=$si --compression_ratio=0.50 --disable_data_sync=$dds
  5. --write_buffer_size=$wbs --target_file_size_base=$mb --max_write_buffer_number=$wbn --max_background_compactions=$mbc --level0_file_num_compaction_trigger=$ctrig --level0_slowdown_writes_trigger=$delay --level0_stop_writes_trigger=$stop
  6. --num_levels=$levels --delete_obsolete_files_period_micros=$del --min_level_to_compress=$mcz --max_grandparent_overlap_factor=$overlap --stats_per_interval=1 --max_bytes_for_level_base=$bpl --use_existing_db=false
  7. echo "Reading 1B keys in database in random order...."
  8. bpl=10485760;overlap=10;mcz=2;del=300000000;levels=6;ctrig=4; delay=8; stop=12; wbn=3; mbc=20; mb=67108864; wbs=134217728; dds=0; sync=false; t=32; vs=800; bs=4096; cs=1048576; of=500000; si=1000000;
  9. ./jdb_bench.sh --benchmarks=readrandom --disable_seek_compaction=true --mmap_read=false --statistics=true --histogram=true --num=$n --reads=$r --threads=$t --value_size=$vs --block_size=$bs --cache_size=$cs --bloom_bits=10
  10. --cache_numshardbits=6 --open_files=$of --verify_checksum=true --db=/rocksdb-bench/java/b4 --sync=$sync --disable_wal=true --compression_type=none --stats_interval=$si --compression_ratio=0.50 --disable_data_sync=$dds --write_buffer_size=$wbs
  11. --target_file_size_base=$mb --max_write_buffer_number=$wbn --max_background_compactions=$mbc --level0_file_num_compaction_trigger=$ctrig --level0_slowdown_writes_trigger=$delay --level0_stop_writes_trigger=$stop --num_levels=$levels
  12. --delete_obsolete_files_period_micros=$del --min_level_to_compress=$mcz --max_grandparent_overlap_factor=$overlap --stats_per_interval=1 --max_bytes_for_level_base=$bpl --use_existing_db=true

多线程读和单线程写 (测试5)

这个基准测试的性能是,当同时发布更新时,用1B密钥从数据库中随机读取100M密钥。为了缩短实验时间,将基准测试中的读取键数配置为100M。 与我们在测试4中使用的设置类似,每个键仍然是16字节,值分别是800字节,并且RocksJava配置为块大小为4 KB,并启用了Snappy压缩。 在这个基准测试中,基准测试中有32个专门的读线程向数据库发出随机读,而另一个线程以每秒10k的速度向数据库发出随机写。

下面是RocksJava的随机读写性能:

  1. readwhilewriting : 9.55882 micros/op; 81.4 MB/s; 100000000 / 100000000 found; 32 / 32 task(s) finished.

结果表明,RocksJava可以读取80 MB/s左右的数据,或者每秒处理大约100K的数据,同时还可以并发地发出更新。 下面是用RocksJava运行基准测试时使用的命令:

  1. echo "Load 1B keys sequentially into database....."
  2. dir="/rocksdb-bench/java/b5"
  3. num=1000000000; r=100000000; bpl=536870912; mb=67108864; overlap=10; mcz=2; del=300000000; levels=6; ctrig=4; delay=8; stop=12; wbn=3; mbc=20; wbs=134217728; dds=false; sync=false; vs=800; bs=4096; cs=17179869184; of=500000; wps=0; si=10000000;
  4. ./jdb_bench.sh --benchmarks=fillseq --disable_seek_compaction=true --mmap_read=false --statistics=true --histogram=true --num=$num --threads=1 --value_size=$vs --block_size=$bs --cache_size=$cs --bloom_bits=10 --cache_numshardbits=6 --open_files=$of
  5. --verify_checksum=true --db=$dir --sync=$sync --disable_wal=true --compression_type=snappy --stats_interval=$si --compression_ratio=0.5 --disable_data_sync=$dds --write_buffer_size=$wbs --target_file_size_base=$mb --max_write_buffer_number=$wbn
  6. --max_background_compactions=$mbc --level0_file_num_compaction_trigger=$ctrig --level0_slowdown_writes_trigger=$delay --level0_stop_writes_trigger=$stop --num_levels=$levels --delete_obsolete_files_period_micros=$del --min_level_to_compress=$mcz
  7. --max_grandparent_overlap_factor=$overlap --stats_per_interval=1 --max_bytes_for_level_base=$bpl --use_existing_db=false
  8. echo "Reading while writing 100M keys in database in random order...."
  9. bpl=536870912;mb=67108864;overlap=10;mcz=2;del=300000000;levels=6;ctrig=4;delay=8;stop=12;wbn=3;mbc=20;wbs=134217728;dds=false;sync=false;t=32;vs=800;bs=4096;cs=17179869184;of=500000;wps=10000;si=10000000;
  10. ./jdb_bench.sh --benchmarks=readwhilewriting --disable_seek_compaction=true --mmap_read=false --statistics=true --histogram=true --num=$num --reads=$r --writes_per_second=10000 --threads=$t --value_size=$vs --block_size=$bs --cache_size=$cs
  11. --bloom_bits=10 --cache_numshardbits=6 --open_files=$of --verify_checksum=true --db=$dir --sync=$sync --disable_wal=false --compression_type=snappy --stats_interval=$si --compression_ratio=0.5 --disable_data_sync=$dds --write_buffer_size=$wbs
  12. --target_file_size_base=$mb --max_write_buffer_number=$wbn --max_background_compactions=$mbc --level0_file_num_compaction_trigger=$ctrig --level0_slowdown_writes_trigger=$delay --level0_stop_writes_trigger=$stop --num_levels=$levels
  13. --delete_obsolete_files_period_micros=$del --min_level_to_compress=$mcz --max_grandparent_overlap_factor=$overlap --stats_per_interval=1 --max_bytes_for_level_base=$bpl --use_existing_db=true --writes_per_second=$wps