multi_vs_mget_mset.rb 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. require "benchmark"
  2. require "redis"
  3. N = (ARGV.first || 1).to_i
  4. DOC_ID = (ARGV.last || "606072b20bb4d3109fb5b122")
  5. @r = Redis.new
  6. def get
  7. @r.get("doclines:{#{DOC_ID}}")
  8. @r.get("DocVersion:{#{DOC_ID}}")
  9. @r.get("DocHash:{#{DOC_ID}}")
  10. @r.get("ProjectId:{#{DOC_ID}}")
  11. @r.get("Ranges:{#{DOC_ID}}")
  12. @r.get("Pathname:{#{DOC_ID}}")
  13. @r.get("ProjectHistoryId:{#{DOC_ID}}")
  14. @r.get("UnflushedTime:{#{DOC_ID}}")
  15. @r.get("lastUpdatedAt:{#{DOC_ID}}")
  16. @r.get("lastUpdatedBy:{#{DOC_ID}}")
  17. end
  18. def mget
  19. @r.mget(
  20. "doclines:{#{DOC_ID}}",
  21. "DocVersion:{#{DOC_ID}}",
  22. "DocHash:{#{DOC_ID}}",
  23. "ProjectId:{#{DOC_ID}}",
  24. "Ranges:{#{DOC_ID}}",
  25. "Pathname:{#{DOC_ID}}",
  26. "ProjectHistoryId:{#{DOC_ID}}",
  27. "UnflushedTime:{#{DOC_ID}}",
  28. "lastUpdatedAt:{#{DOC_ID}}",
  29. "lastUpdatedBy:{#{DOC_ID}}",
  30. )
  31. end
  32. def set
  33. @r.set("doclines:{#{DOC_ID}}", "[\"@book{adams1995hitchhiker,\",\" title={The Hitchhiker's Guide to the Galaxy},\",\" author={Adams, D.},\",\" isbn={9781417642595},\",\" url={http://books.google.com/books?id=W-xMPgAACAAJ},\",\" year={1995},\",\" publisher={San Val}\",\"}\",\"\"]")
  34. @r.set("DocVersion:{#{DOC_ID}}", "0")
  35. @r.set("DocHash:{#{DOC_ID}}", "0075bb0629c6c13d0d68918443648bbfe7d98869")
  36. @r.set("ProjectId:{#{DOC_ID}}", "606072b20bb4d3109fb5b11e")
  37. @r.set("Ranges:{#{DOC_ID}}", "")
  38. @r.set("Pathname:{#{DOC_ID}}", "/references.bib")
  39. @r.set("ProjectHistoryId:{#{DOC_ID}}", "")
  40. @r.set("UnflushedTime:{#{DOC_ID}}", "")
  41. @r.set("lastUpdatedAt:{#{DOC_ID}}", "")
  42. @r.set("lastUpdatedBy:{#{DOC_ID}}", "")
  43. end
  44. def mset
  45. @r.mset(
  46. "doclines:{#{DOC_ID}}", "[\"@book{adams1995hitchhiker,\",\" title={The Hitchhiker's Guide to the Galaxy},\",\" author={Adams, D.},\",\" isbn={9781417642595},\",\" url={http://books.google.com/books?id=W-xMPgAACAAJ},\",\" year={1995},\",\" publisher={San Val}\",\"}\",\"\"]",
  47. "DocVersion:{#{DOC_ID}}", "0",
  48. "DocHash:{#{DOC_ID}}", "0075bb0629c6c13d0d68918443648bbfe7d98869",
  49. "ProjectId:{#{DOC_ID}}", "606072b20bb4d3109fb5b11e",
  50. "Ranges:{#{DOC_ID}}", "",
  51. "Pathname:{#{DOC_ID}}", "/references.bib",
  52. "ProjectHistoryId:{#{DOC_ID}}", "",
  53. "UnflushedTime:{#{DOC_ID}}", "",
  54. "lastUpdatedAt:{#{DOC_ID}}", "",
  55. "lastUpdatedBy:{#{DOC_ID}}", "",
  56. )
  57. end
  58. def benchmark_multi_get(benchmark, i)
  59. benchmark.report("#{i}: multi get") do
  60. N.times do
  61. @r.multi do
  62. get
  63. end
  64. end
  65. end
  66. end
  67. def benchmark_mget(benchmark, i)
  68. benchmark.report("#{i}: mget") do
  69. N.times do
  70. mget
  71. end
  72. end
  73. end
  74. def benchmark_multi_set(benchmark, i)
  75. benchmark.report("#{i}: multi set") do
  76. N.times do
  77. @r.multi do
  78. set
  79. end
  80. end
  81. end
  82. end
  83. def benchmark_mset(benchmark, i)
  84. benchmark.report("#{i}: mset") do
  85. N.times do
  86. mset
  87. end
  88. end
  89. end
  90. # init
  91. set
  92. Benchmark.bmbm do |benchmark|
  93. 3.times do |i|
  94. benchmark_multi_get(benchmark, i)
  95. benchmark_mget(benchmark, i)
  96. benchmark_multi_set(benchmark, i)
  97. benchmark_mset(benchmark, i)
  98. end
  99. end
  100. =begin
  101. # Results
  102. I could not max out the redis-server process with this benchmark.
  103. The ruby process hit 100% of a modern i7 CPU thread and the redis-server process
  104. barely hit 50% of a CPU thread.
  105. Based on the timings below, mget is about 3 times faster and mset about 4 times
  106. faster than multiple get/set commands in a multi.
  107. =end
  108. =begin
  109. $ redis-server --version
  110. Redis server v=5.0.7 sha=00000000:0 malloc=jemalloc-5.2.1 bits=64 build=636cde3b5c7a3923
  111. $ ruby multi_vs_mget_mset.rb 100000
  112. Rehearsal ------------------------------------------------
  113. 0: multi get 12.132423 4.246689 16.379112 ( 16.420069)
  114. 0: mget 4.499457 0.947556 5.447013 ( 6.274883)
  115. 0: multi set 12.685936 4.495241 17.181177 ( 17.225984)
  116. 0: mset 2.543401 0.913448 3.456849 ( 4.554799)
  117. 1: multi get 13.397207 4.581881 17.979088 ( 18.027755)
  118. 1: mget 4.551287 1.160531 5.711818 ( 6.579168)
  119. 1: multi set 13.018957 4.927175 17.946132 ( 17.987502)
  120. 1: mset 2.561096 1.048416 3.609512 ( 4.780087)
  121. 2: multi get 13.224422 5.014475 18.238897 ( 18.284152)
  122. 2: mget 4.664434 1.051083 5.715517 ( 6.592088)
  123. 2: multi set 12.972284 4.600422 17.572706 ( 17.613185)
  124. 2: mset 2.621344 0.984123 3.605467 ( 4.766855)
  125. ------------------------------------- total: 132.843288sec
  126. user system total real
  127. 0: multi get 13.341552 4.900892 18.242444 ( 18.289912)
  128. 0: mget 5.056534 0.960954 6.017488 ( 6.971189)
  129. 0: multi set 12.989880 4.823793 17.813673 ( 17.858393)
  130. 0: mset 2.543434 1.025352 3.568786 ( 4.723040)
  131. 1: multi get 13.059379 4.674345 17.733724 ( 17.777859)
  132. 1: mget 4.698754 0.915637 5.614391 ( 6.489614)
  133. 1: multi set 12.608293 4.729163 17.337456 ( 17.372993)
  134. 1: mset 2.645290 0.940584 3.585874 ( 4.744134)
  135. 2: multi get 13.678224 4.732373 18.410597 ( 18.457525)
  136. 2: mget 4.716749 1.072064 5.788813 ( 6.697683)
  137. 2: multi set 13.058710 4.889801 17.948511 ( 17.988742)
  138. 2: mset 2.311854 0.989166 3.301020 ( 4.346467)
  139. =end
  140. =begin
  141. # multi get/set run at about O(65'000) operations per second
  142. $ redis-cli info | grep 'instantaneous_ops_per_sec'
  143. instantaneous_ops_per_sec:65557
  144. # mget runs at about O(15'000) operations per second
  145. $ redis-cli info | grep 'instantaneous_ops_per_sec'
  146. instantaneous_ops_per_sec:14580
  147. # mset runs at about O(20'000) operations per second
  148. $ redis-cli info | grep 'instantaneous_ops_per_sec'
  149. instantaneous_ops_per_sec:20792
  150. These numbers are pretty reasonable:
  151. multi: 100'000 * 12 ops / 18s = 66'666 ops/s
  152. mget : 100'000 * 1 ops / 7s = 14'285 ops/s
  153. mset : 100'000 * 1 ops / 5s = 20'000 ops/s
  154. Bonus: Running three benchmarks in parallel on different keys.
  155. multi get: O(125'000) ops/s and 80% CPU load of redis-server
  156. multi set: O(130'000) ops/s and 90% CPU load of redis-server
  157. mget : O( 30'000) ops/s and 70% CPU load of redis-server
  158. mset : O( 40'000) ops/s and 90% CPU load of redis-server
  159. =end