redis-server 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. data/LICENSE +38 -0
  2. data/README.md +33 -0
  3. data/bin/redis +114 -0
  4. data/redis/Makefile +5 -0
  5. data/redis/extconf.rb +3 -0
  6. data/redis/redis-2.2.11/00-RELEASENOTES +199 -0
  7. data/redis/redis-2.2.11/BUGS +1 -0
  8. data/redis/redis-2.2.11/CONTRIBUTING +13 -0
  9. data/redis/redis-2.2.11/COPYING +10 -0
  10. data/redis/redis-2.2.11/Changelog +1032 -0
  11. data/redis/redis-2.2.11/INSTALL +30 -0
  12. data/redis/redis-2.2.11/Makefile +22 -0
  13. data/redis/redis-2.2.11/README +83 -0
  14. data/redis/redis-2.2.11/TODO +4 -0
  15. data/redis/redis-2.2.11/client-libraries/README +11 -0
  16. data/redis/redis-2.2.11/deps/hiredis/COPYING +10 -0
  17. data/redis/redis-2.2.11/deps/hiredis/Makefile +115 -0
  18. data/redis/redis-2.2.11/deps/hiredis/README.md +311 -0
  19. data/redis/redis-2.2.11/deps/hiredis/TODO +2 -0
  20. data/redis/redis-2.2.11/deps/hiredis/adapters/ae.h +95 -0
  21. data/redis/redis-2.2.11/deps/hiredis/adapters/libev.h +113 -0
  22. data/redis/redis-2.2.11/deps/hiredis/adapters/libevent.h +76 -0
  23. data/redis/redis-2.2.11/deps/hiredis/async.c +321 -0
  24. data/redis/redis-2.2.11/deps/hiredis/async.h +112 -0
  25. data/redis/redis-2.2.11/deps/hiredis/example-ae.c +53 -0
  26. data/redis/redis-2.2.11/deps/hiredis/example-libev.c +47 -0
  27. data/redis/redis-2.2.11/deps/hiredis/example-libevent.c +48 -0
  28. data/redis/redis-2.2.11/deps/hiredis/example.c +67 -0
  29. data/redis/redis-2.2.11/deps/hiredis/fmacros.h +15 -0
  30. data/redis/redis-2.2.11/deps/hiredis/hiredis.c +1058 -0
  31. data/redis/redis-2.2.11/deps/hiredis/hiredis.h +170 -0
  32. data/redis/redis-2.2.11/deps/hiredis/net.c +170 -0
  33. data/redis/redis-2.2.11/deps/hiredis/net.h +43 -0
  34. data/redis/redis-2.2.11/deps/hiredis/sds.c +479 -0
  35. data/redis/redis-2.2.11/deps/hiredis/sds.h +77 -0
  36. data/redis/redis-2.2.11/deps/hiredis/test.c +479 -0
  37. data/redis/redis-2.2.11/deps/hiredis/util.h +40 -0
  38. data/redis/redis-2.2.11/deps/linenoise/Makefile +10 -0
  39. data/redis/redis-2.2.11/deps/linenoise/README.markdown +45 -0
  40. data/redis/redis-2.2.11/deps/linenoise/example.c +27 -0
  41. data/redis/redis-2.2.11/deps/linenoise/linenoise.c +609 -0
  42. data/redis/redis-2.2.11/deps/linenoise/linenoise.h +55 -0
  43. data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER +214 -0
  44. data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER-2 +343 -0
  45. data/redis/redis-2.2.11/doc/AppendCommand.html +48 -0
  46. data/redis/redis-2.2.11/doc/AppendOnlyFileHowto.html +41 -0
  47. data/redis/redis-2.2.11/doc/AuthCommand.html +39 -0
  48. data/redis/redis-2.2.11/doc/Benchmarks.html +129 -0
  49. data/redis/redis-2.2.11/doc/BgrewriteaofCommand.html +41 -0
  50. data/redis/redis-2.2.11/doc/BgsaveCommand.html +39 -0
  51. data/redis/redis-2.2.11/doc/BlpopCommand.html +51 -0
  52. data/redis/redis-2.2.11/doc/BrpoplpushCommand.html +39 -0
  53. data/redis/redis-2.2.11/doc/CommandReference.html +47 -0
  54. data/redis/redis-2.2.11/doc/Comparisons.html +42 -0
  55. data/redis/redis-2.2.11/doc/ConfigCommand.html +76 -0
  56. data/redis/redis-2.2.11/doc/Configuration.html +38 -0
  57. data/redis/redis-2.2.11/doc/ConnectionHandlingSidebar.html +36 -0
  58. data/redis/redis-2.2.11/doc/ControlCommandsSidebar.html +36 -0
  59. data/redis/redis-2.2.11/doc/Credits.html +38 -0
  60. data/redis/redis-2.2.11/doc/DbsizeCommand.html +38 -0
  61. data/redis/redis-2.2.11/doc/DelCommand.html +41 -0
  62. data/redis/redis-2.2.11/doc/DesignPatterns.html +37 -0
  63. data/redis/redis-2.2.11/doc/EventLibray.html +44 -0
  64. data/redis/redis-2.2.11/doc/ExistsCommand.html +42 -0
  65. data/redis/redis-2.2.11/doc/ExpireCommand.html +96 -0
  66. data/redis/redis-2.2.11/doc/FAQ.html +70 -0
  67. data/redis/redis-2.2.11/doc/Features.html +38 -0
  68. data/redis/redis-2.2.11/doc/FlushallCommand.html +39 -0
  69. data/redis/redis-2.2.11/doc/FlushdbCommand.html +39 -0
  70. data/redis/redis-2.2.11/doc/FromSqlToDataStructures.html +37 -0
  71. data/redis/redis-2.2.11/doc/GenericCommandsSidebar.html +36 -0
  72. data/redis/redis-2.2.11/doc/GetCommand.html +39 -0
  73. data/redis/redis-2.2.11/doc/GetbitCommand.html +39 -0
  74. data/redis/redis-2.2.11/doc/GetsetCommand.html +38 -0
  75. data/redis/redis-2.2.11/doc/HackingStrings.html +83 -0
  76. data/redis/redis-2.2.11/doc/HashCommandsSidebar.html +36 -0
  77. data/redis/redis-2.2.11/doc/Hashes.html +37 -0
  78. data/redis/redis-2.2.11/doc/HdelCommand.html +39 -0
  79. data/redis/redis-2.2.11/doc/HexistsCommand.html +39 -0
  80. data/redis/redis-2.2.11/doc/HgetCommand.html +39 -0
  81. data/redis/redis-2.2.11/doc/HgetallCommand.html +40 -0
  82. data/redis/redis-2.2.11/doc/HincrbyCommand.html +45 -0
  83. data/redis/redis-2.2.11/doc/HlenCommand.html +38 -0
  84. data/redis/redis-2.2.11/doc/HmgetCommand.html +40 -0
  85. data/redis/redis-2.2.11/doc/HmsetCommand.html +40 -0
  86. data/redis/redis-2.2.11/doc/HsetCommand.html +40 -0
  87. data/redis/redis-2.2.11/doc/HsetnxCommand.html +41 -0
  88. data/redis/redis-2.2.11/doc/IncrCommand.html +43 -0
  89. data/redis/redis-2.2.11/doc/InfoCommand.html +48 -0
  90. data/redis/redis-2.2.11/doc/IntroductionToRedisDataTypes.html +152 -0
  91. data/redis/redis-2.2.11/doc/KeysCommand.html +43 -0
  92. data/redis/redis-2.2.11/doc/LastsaveCommand.html +39 -0
  93. data/redis/redis-2.2.11/doc/LindexCommand.html +40 -0
  94. data/redis/redis-2.2.11/doc/ListCommandsSidebar.html +36 -0
  95. data/redis/redis-2.2.11/doc/Lists.html +42 -0
  96. data/redis/redis-2.2.11/doc/LlenCommand.html +41 -0
  97. data/redis/redis-2.2.11/doc/LpopCommand.html +41 -0
  98. data/redis/redis-2.2.11/doc/LrangeCommand.html +47 -0
  99. data/redis/redis-2.2.11/doc/LremCommand.html +41 -0
  100. data/redis/redis-2.2.11/doc/LsetCommand.html +38 -0
  101. data/redis/redis-2.2.11/doc/LtrimCommand.html +47 -0
  102. data/redis/redis-2.2.11/doc/MgetCommand.html +52 -0
  103. data/redis/redis-2.2.11/doc/MonitorCommand.html +63 -0
  104. data/redis/redis-2.2.11/doc/MoveCommand.html +42 -0
  105. data/redis/redis-2.2.11/doc/MsetCommand.html +44 -0
  106. data/redis/redis-2.2.11/doc/MultiExecCommand.html +166 -0
  107. data/redis/redis-2.2.11/doc/NonexistentCommands.html +51 -0
  108. data/redis/redis-2.2.11/doc/ObjectHashMappers.html +39 -0
  109. data/redis/redis-2.2.11/doc/Pipelining.html +36 -0
  110. data/redis/redis-2.2.11/doc/ProgrammingExamples.html +38 -0
  111. data/redis/redis-2.2.11/doc/ProtocolSpecification.html +137 -0
  112. data/redis/redis-2.2.11/doc/PublishSubscribe.html +115 -0
  113. data/redis/redis-2.2.11/doc/QuickStart.html +68 -0
  114. data/redis/redis-2.2.11/doc/QuitCommand.html +38 -0
  115. data/redis/redis-2.2.11/doc/README.html +119 -0
  116. data/redis/redis-2.2.11/doc/RandomkeyCommand.html +39 -0
  117. data/redis/redis-2.2.11/doc/Redis0100ChangeLog.html +67 -0
  118. data/redis/redis-2.2.11/doc/Redis0900ChangeLog.html +56 -0
  119. data/redis/redis-2.2.11/doc/RedisBigData.html +61 -0
  120. data/redis/redis-2.2.11/doc/RedisCLI.html +37 -0
  121. data/redis/redis-2.2.11/doc/RedisEventLibrary.html +70 -0
  122. data/redis/redis-2.2.11/doc/RedisGuides.html +37 -0
  123. data/redis/redis-2.2.11/doc/RedisInternals.html +38 -0
  124. data/redis/redis-2.2.11/doc/RedisPipelining.html +93 -0
  125. data/redis/redis-2.2.11/doc/RedisStatus.html +56 -0
  126. data/redis/redis-2.2.11/doc/Redis_1_2_0_Changelog.html +40 -0
  127. data/redis/redis-2.2.11/doc/Redis_2_0_0_Changelog.html +62 -0
  128. data/redis/redis-2.2.11/doc/Redis_2_0_Whats_new.html +59 -0
  129. data/redis/redis-2.2.11/doc/RenameCommand.html +39 -0
  130. data/redis/redis-2.2.11/doc/RenamenxCommand.html +42 -0
  131. data/redis/redis-2.2.11/doc/ReplicationHowto.html +43 -0
  132. data/redis/redis-2.2.11/doc/ReplyTypes.html +42 -0
  133. data/redis/redis-2.2.11/doc/RoadMap.html +38 -0
  134. data/redis/redis-2.2.11/doc/RpoplpushCommand.html +44 -0
  135. data/redis/redis-2.2.11/doc/RpushCommand.html +40 -0
  136. data/redis/redis-2.2.11/doc/SaddCommand.html +41 -0
  137. data/redis/redis-2.2.11/doc/SaveCommand.html +39 -0
  138. data/redis/redis-2.2.11/doc/ScardCommand.html +41 -0
  139. data/redis/redis-2.2.11/doc/SdiffCommand.html +45 -0
  140. data/redis/redis-2.2.11/doc/SdiffstoreCommand.html +38 -0
  141. data/redis/redis-2.2.11/doc/SelectCommand.html +39 -0
  142. data/redis/redis-2.2.11/doc/SetCommand.html +39 -0
  143. data/redis/redis-2.2.11/doc/SetCommandsSidebar.html +36 -0
  144. data/redis/redis-2.2.11/doc/SetbitCommand.html +45 -0
  145. data/redis/redis-2.2.11/doc/SetexCommand.html +42 -0
  146. data/redis/redis-2.2.11/doc/SetnxCommand.html +51 -0
  147. data/redis/redis-2.2.11/doc/SetrangeCommand.html +58 -0
  148. data/redis/redis-2.2.11/doc/Sets.html +36 -0
  149. data/redis/redis-2.2.11/doc/ShutdownCommand.html +39 -0
  150. data/redis/redis-2.2.11/doc/SideBar.html +36 -0
  151. data/redis/redis-2.2.11/doc/SinterCommand.html +40 -0
  152. data/redis/redis-2.2.11/doc/SinterstoreCommand.html +39 -0
  153. data/redis/redis-2.2.11/doc/SismemberCommand.html +42 -0
  154. data/redis/redis-2.2.11/doc/SlaveofCommand.html +41 -0
  155. data/redis/redis-2.2.11/doc/SmembersCommand.html +38 -0
  156. data/redis/redis-2.2.11/doc/SmoveCommand.html +44 -0
  157. data/redis/redis-2.2.11/doc/SortCommand.html +75 -0
  158. data/redis/redis-2.2.11/doc/SortedSetCommandsSidebar.html +36 -0
  159. data/redis/redis-2.2.11/doc/SortedSets.html +36 -0
  160. data/redis/redis-2.2.11/doc/Speed.html +38 -0
  161. data/redis/redis-2.2.11/doc/SponsorshipHistory.html +38 -0
  162. data/redis/redis-2.2.11/doc/SpopCommand.html +40 -0
  163. data/redis/redis-2.2.11/doc/SrandmemberCommand.html +40 -0
  164. data/redis/redis-2.2.11/doc/SremCommand.html +42 -0
  165. data/redis/redis-2.2.11/doc/StringCommandsSidebar.html +36 -0
  166. data/redis/redis-2.2.11/doc/Strings.html +37 -0
  167. data/redis/redis-2.2.11/doc/StrlenCommand.html +39 -0
  168. data/redis/redis-2.2.11/doc/SubstrCommand.html +52 -0
  169. data/redis/redis-2.2.11/doc/SunionCommand.html +40 -0
  170. data/redis/redis-2.2.11/doc/SunionstoreCommand.html +38 -0
  171. data/redis/redis-2.2.11/doc/SupportedLanguages.html +60 -0
  172. data/redis/redis-2.2.11/doc/SupportedPlatforms.html +37 -0
  173. data/redis/redis-2.2.11/doc/TemplateCommand.html +38 -0
  174. data/redis/redis-2.2.11/doc/TtlCommand.html +38 -0
  175. data/redis/redis-2.2.11/doc/TwitterAlikeExample.html +250 -0
  176. data/redis/redis-2.2.11/doc/TypeCommand.html +46 -0
  177. data/redis/redis-2.2.11/doc/UnstableSource.html +39 -0
  178. data/redis/redis-2.2.11/doc/VirtualMemorySpecification.html +156 -0
  179. data/redis/redis-2.2.11/doc/VirtualMemoryUserGuide.html +66 -0
  180. data/redis/redis-2.2.11/doc/ZaddCommand.html +43 -0
  181. data/redis/redis-2.2.11/doc/ZcardCommand.html +41 -0
  182. data/redis/redis-2.2.11/doc/ZincrbyCommand.html +42 -0
  183. data/redis/redis-2.2.11/doc/ZrangeCommand.html +42 -0
  184. data/redis/redis-2.2.11/doc/ZrangebyscoreCommand.html +77 -0
  185. data/redis/redis-2.2.11/doc/ZrankCommand.html +43 -0
  186. data/redis/redis-2.2.11/doc/ZremCommand.html +42 -0
  187. data/redis/redis-2.2.11/doc/ZremrangebyrankCommand.html +39 -0
  188. data/redis/redis-2.2.11/doc/ZremrangebyscoreCommand.html +39 -0
  189. data/redis/redis-2.2.11/doc/ZscoreCommand.html +41 -0
  190. data/redis/redis-2.2.11/doc/ZunionCommand.html +42 -0
  191. data/redis/redis-2.2.11/doc/ZunionstoreCommand.html +43 -0
  192. data/redis/redis-2.2.11/doc/index.html +43 -0
  193. data/redis/redis-2.2.11/doc/redis.png +0 -0
  194. data/redis/redis-2.2.11/doc/style.css +25 -0
  195. data/redis/redis-2.2.11/redis.conf +417 -0
  196. data/redis/redis-2.2.11/src/Makefile +177 -0
  197. data/redis/redis-2.2.11/src/adlist.c +325 -0
  198. data/redis/redis-2.2.11/src/adlist.h +92 -0
  199. data/redis/redis-2.2.11/src/ae.c +390 -0
  200. data/redis/redis-2.2.11/src/ae.h +117 -0
  201. data/redis/redis-2.2.11/src/ae_epoll.c +91 -0
  202. data/redis/redis-2.2.11/src/ae_kqueue.c +93 -0
  203. data/redis/redis-2.2.11/src/ae_select.c +72 -0
  204. data/redis/redis-2.2.11/src/anet.c +347 -0
  205. data/redis/redis-2.2.11/src/anet.h +57 -0
  206. data/redis/redis-2.2.11/src/aof.c +675 -0
  207. data/redis/redis-2.2.11/src/config.c +627 -0
  208. data/redis/redis-2.2.11/src/config.h +64 -0
  209. data/redis/redis-2.2.11/src/db.c +543 -0
  210. data/redis/redis-2.2.11/src/debug.c +314 -0
  211. data/redis/redis-2.2.11/src/dict.c +721 -0
  212. data/redis/redis-2.2.11/src/dict.h +156 -0
  213. data/redis/redis-2.2.11/src/fmacros.h +15 -0
  214. data/redis/redis-2.2.11/src/help.h +638 -0
  215. data/redis/redis-2.2.11/src/intset.c +422 -0
  216. data/redis/redis-2.2.11/src/intset.h +19 -0
  217. data/redis/redis-2.2.11/src/lzf.h +100 -0
  218. data/redis/redis-2.2.11/src/lzfP.h +159 -0
  219. data/redis/redis-2.2.11/src/lzf_c.c +295 -0
  220. data/redis/redis-2.2.11/src/lzf_d.c +150 -0
  221. data/redis/redis-2.2.11/src/mkreleasehdr.sh +9 -0
  222. data/redis/redis-2.2.11/src/multi.c +268 -0
  223. data/redis/redis-2.2.11/src/networking.c +899 -0
  224. data/redis/redis-2.2.11/src/object.c +484 -0
  225. data/redis/redis-2.2.11/src/pqsort.c +197 -0
  226. data/redis/redis-2.2.11/src/pqsort.h +15 -0
  227. data/redis/redis-2.2.11/src/pubsub.c +267 -0
  228. data/redis/redis-2.2.11/src/rdb.c +1020 -0
  229. data/redis/redis-2.2.11/src/redis-benchmark.c +530 -0
  230. data/redis/redis-2.2.11/src/redis-check-aof.c +185 -0
  231. data/redis/redis-2.2.11/src/redis-check-dump.c +681 -0
  232. data/redis/redis-2.2.11/src/redis-cli.c +773 -0
  233. data/redis/redis-2.2.11/src/redis.c +1677 -0
  234. data/redis/redis-2.2.11/src/redis.h +1022 -0
  235. data/redis/redis-2.2.11/src/release.c +13 -0
  236. data/redis/redis-2.2.11/src/replication.c +557 -0
  237. data/redis/redis-2.2.11/src/sds.c +639 -0
  238. data/redis/redis-2.2.11/src/sds.h +78 -0
  239. data/redis/redis-2.2.11/src/sha1.c +276 -0
  240. data/redis/redis-2.2.11/src/sha1.h +17 -0
  241. data/redis/redis-2.2.11/src/solarisfixes.h +22 -0
  242. data/redis/redis-2.2.11/src/sort.c +389 -0
  243. data/redis/redis-2.2.11/src/syncio.c +154 -0
  244. data/redis/redis-2.2.11/src/t_hash.c +476 -0
  245. data/redis/redis-2.2.11/src/t_list.c +986 -0
  246. data/redis/redis-2.2.11/src/t_set.c +610 -0
  247. data/redis/redis-2.2.11/src/t_string.c +438 -0
  248. data/redis/redis-2.2.11/src/t_zset.c +1084 -0
  249. data/redis/redis-2.2.11/src/testhelp.h +54 -0
  250. data/redis/redis-2.2.11/src/util.c +243 -0
  251. data/redis/redis-2.2.11/src/valgrind.sup +5 -0
  252. data/redis/redis-2.2.11/src/version.h +1 -0
  253. data/redis/redis-2.2.11/src/vm.c +1149 -0
  254. data/redis/redis-2.2.11/src/ziplist.c +1323 -0
  255. data/redis/redis-2.2.11/src/ziplist.h +15 -0
  256. data/redis/redis-2.2.11/src/zipmap.c +455 -0
  257. data/redis/redis-2.2.11/src/zipmap.h +48 -0
  258. data/redis/redis-2.2.11/src/zmalloc.c +278 -0
  259. data/redis/redis-2.2.11/src/zmalloc.h +47 -0
  260. data/redis/redis-2.2.11/tests/assets/default.conf +308 -0
  261. data/redis/redis-2.2.11/tests/integration/aof.tcl +104 -0
  262. data/redis/redis-2.2.11/tests/integration/redis-cli.tcl +208 -0
  263. data/redis/redis-2.2.11/tests/integration/replication.tcl +98 -0
  264. data/redis/redis-2.2.11/tests/support/redis.tcl +241 -0
  265. data/redis/redis-2.2.11/tests/support/server.tcl +294 -0
  266. data/redis/redis-2.2.11/tests/support/test.tcl +190 -0
  267. data/redis/redis-2.2.11/tests/support/tmpfile.tcl +15 -0
  268. data/redis/redis-2.2.11/tests/support/util.tcl +296 -0
  269. data/redis/redis-2.2.11/tests/test_helper.tcl +221 -0
  270. data/redis/redis-2.2.11/tests/unit/auth.tcl +15 -0
  271. data/redis/redis-2.2.11/tests/unit/basic.tcl +616 -0
  272. data/redis/redis-2.2.11/tests/unit/cas.tcl +135 -0
  273. data/redis/redis-2.2.11/tests/unit/expire.tcl +74 -0
  274. data/redis/redis-2.2.11/tests/unit/other.tcl +240 -0
  275. data/redis/redis-2.2.11/tests/unit/printver.tcl +6 -0
  276. data/redis/redis-2.2.11/tests/unit/protocol.tcl +62 -0
  277. data/redis/redis-2.2.11/tests/unit/pubsub.tcl +195 -0
  278. data/redis/redis-2.2.11/tests/unit/quit.tcl +40 -0
  279. data/redis/redis-2.2.11/tests/unit/sort.tcl +189 -0
  280. data/redis/redis-2.2.11/tests/unit/type/hash.tcl +300 -0
  281. data/redis/redis-2.2.11/tests/unit/type/list.tcl +819 -0
  282. data/redis/redis-2.2.11/tests/unit/type/set.tcl +334 -0
  283. data/redis/redis-2.2.11/tests/unit/type/zset.tcl +587 -0
  284. data/redis/redis-2.2.11/utils/build-static-symbols.tcl +22 -0
  285. data/redis/redis-2.2.11/utils/generate-command-help.rb +112 -0
  286. data/redis/redis-2.2.11/utils/mktarball.sh +13 -0
  287. data/redis/redis-2.2.11/utils/redis-copy.rb +78 -0
  288. data/redis/redis-2.2.11/utils/redis-sha1.rb +52 -0
  289. data/redis/redis-2.2.11/utils/redis_init_script +42 -0
  290. metadata +362 -0
@@ -0,0 +1,530 @@
1
+ /* Redis benchmark utility.
2
+ *
3
+ * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright notice,
10
+ * this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of Redis nor the names of its contributors may be used
15
+ * to endorse or promote products derived from this software without
16
+ * specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ * POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #include "fmacros.h"
32
+
33
+ #include <stdio.h>
34
+ #include <string.h>
35
+ #include <stdlib.h>
36
+ #include <unistd.h>
37
+ #include <errno.h>
38
+ #include <sys/time.h>
39
+ #include <signal.h>
40
+ #include <assert.h>
41
+
42
+ #include "ae.h"
43
+ #include "hiredis.h"
44
+ #include "sds.h"
45
+ #include "adlist.h"
46
+ #include "zmalloc.h"
47
+
48
+ #define REDIS_NOTUSED(V) ((void) V)
49
+
50
+ static struct config {
51
+ int debug;
52
+ int numclients;
53
+ int requests;
54
+ int liveclients;
55
+ int donerequests;
56
+ int keysize;
57
+ int datasize;
58
+ int randomkeys;
59
+ int randomkeys_keyspacelen;
60
+ aeEventLoop *el;
61
+ char *hostip;
62
+ int hostport;
63
+ char *hostsocket;
64
+ int keepalive;
65
+ long long start;
66
+ long long totlatency;
67
+ long long *latency;
68
+ char *title;
69
+ list *clients;
70
+ int quiet;
71
+ int loop;
72
+ int idlemode;
73
+ } config;
74
+
75
+ typedef struct _client {
76
+ redisContext *context;
77
+ sds obuf;
78
+ char *randptr[10]; /* needed for MSET against 10 keys */
79
+ size_t randlen;
80
+ unsigned int written; /* bytes of 'obuf' already written */
81
+ long long start; /* start time of a request */
82
+ long long latency; /* request latency */
83
+ } *client;
84
+
85
+ /* Prototypes */
86
+ static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask);
87
+ static void createMissingClients(client c);
88
+
89
+ /* Implementation */
90
+ static long long ustime(void) {
91
+ struct timeval tv;
92
+ long long ust;
93
+
94
+ gettimeofday(&tv, NULL);
95
+ ust = ((long)tv.tv_sec)*1000000;
96
+ ust += tv.tv_usec;
97
+ return ust;
98
+ }
99
+
100
+ static long long mstime(void) {
101
+ struct timeval tv;
102
+ long long mst;
103
+
104
+ gettimeofday(&tv, NULL);
105
+ mst = ((long)tv.tv_sec)*1000;
106
+ mst += tv.tv_usec/1000;
107
+ return mst;
108
+ }
109
+
110
+ static void freeClient(client c) {
111
+ listNode *ln;
112
+ aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);
113
+ aeDeleteFileEvent(config.el,c->context->fd,AE_READABLE);
114
+ redisFree(c->context);
115
+ sdsfree(c->obuf);
116
+ zfree(c);
117
+ config.liveclients--;
118
+ ln = listSearchKey(config.clients,c);
119
+ assert(ln != NULL);
120
+ listDelNode(config.clients,ln);
121
+ }
122
+
123
+ static void freeAllClients(void) {
124
+ listNode *ln = config.clients->head, *next;
125
+
126
+ while(ln) {
127
+ next = ln->next;
128
+ freeClient(ln->value);
129
+ ln = next;
130
+ }
131
+ }
132
+
133
+ static void resetClient(client c) {
134
+ aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);
135
+ aeDeleteFileEvent(config.el,c->context->fd,AE_READABLE);
136
+ aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c);
137
+ c->written = 0;
138
+ }
139
+
140
+ static void randomizeClientKey(client c) {
141
+ char buf[32];
142
+ size_t i, r;
143
+
144
+ for (i = 0; i < c->randlen; i++) {
145
+ r = random() % config.randomkeys_keyspacelen;
146
+ snprintf(buf,sizeof(buf),"%012zu",r);
147
+ memcpy(c->randptr[i],buf,12);
148
+ }
149
+ }
150
+
151
+ static void clientDone(client c) {
152
+ if (config.donerequests == config.requests) {
153
+ freeClient(c);
154
+ aeStop(config.el);
155
+ return;
156
+ }
157
+ if (config.keepalive) {
158
+ resetClient(c);
159
+ } else {
160
+ config.liveclients--;
161
+ createMissingClients(c);
162
+ config.liveclients++;
163
+ freeClient(c);
164
+ }
165
+ }
166
+
167
+ static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
168
+ client c = privdata;
169
+ void *reply = NULL;
170
+ REDIS_NOTUSED(el);
171
+ REDIS_NOTUSED(fd);
172
+ REDIS_NOTUSED(mask);
173
+
174
+ /* Calculate latency only for the first read event. This means that the
175
+ * server already sent the reply and we need to parse it. Parsing overhead
176
+ * is not part of the latency, so calculate it only once, here. */
177
+ if (c->latency < 0) c->latency = ustime()-(c->start);
178
+
179
+ if (redisBufferRead(c->context) != REDIS_OK) {
180
+ fprintf(stderr,"Error: %s\n",c->context->errstr);
181
+ exit(1);
182
+ } else {
183
+ if (redisGetReply(c->context,&reply) != REDIS_OK) {
184
+ fprintf(stderr,"Error: %s\n",c->context->errstr);
185
+ exit(1);
186
+ }
187
+ if (reply != NULL) {
188
+ if (reply == (void*)REDIS_REPLY_ERROR) {
189
+ fprintf(stderr,"Unexpected error reply, exiting...\n");
190
+ exit(1);
191
+ }
192
+
193
+ if (config.donerequests < config.requests)
194
+ config.latency[config.donerequests++] = c->latency;
195
+ clientDone(c);
196
+ }
197
+ }
198
+ }
199
+
200
+ static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
201
+ client c = privdata;
202
+ REDIS_NOTUSED(el);
203
+ REDIS_NOTUSED(fd);
204
+ REDIS_NOTUSED(mask);
205
+
206
+ /* When nothing was written yet, randomize keys and set start time. */
207
+ if (c->written == 0) {
208
+ if (config.randomkeys) randomizeClientKey(c);
209
+ c->start = ustime();
210
+ c->latency = -1;
211
+ }
212
+
213
+ if (sdslen(c->obuf) > c->written) {
214
+ void *ptr = c->obuf+c->written;
215
+ int nwritten = write(c->context->fd,ptr,sdslen(c->obuf)-c->written);
216
+ if (nwritten == -1) {
217
+ if (errno != EPIPE)
218
+ fprintf(stderr, "Writing to socket: %s\n", strerror(errno));
219
+ freeClient(c);
220
+ return;
221
+ }
222
+ c->written += nwritten;
223
+ if (sdslen(c->obuf) == c->written) {
224
+ aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);
225
+ aeCreateFileEvent(config.el,c->context->fd,AE_READABLE,readHandler,c);
226
+ }
227
+ }
228
+ }
229
+
230
+ static client createClient(char *cmd, int len) {
231
+ client c = zmalloc(sizeof(struct _client));
232
+ if (config.hostsocket == NULL) {
233
+ c->context = redisConnectNonBlock(config.hostip,config.hostport);
234
+ } else {
235
+ c->context = redisConnectUnixNonBlock(config.hostsocket);
236
+ }
237
+ if (c->context->err) {
238
+ fprintf(stderr,"Could not connect to Redis at ");
239
+ if (config.hostsocket == NULL)
240
+ fprintf(stderr,"%s:%d: %s\n",config.hostip,config.hostport,c->context->errstr);
241
+ else
242
+ fprintf(stderr,"%s: %s\n",config.hostsocket,c->context->errstr);
243
+ exit(1);
244
+ }
245
+ c->obuf = sdsnewlen(cmd,len);
246
+ c->randlen = 0;
247
+ c->written = 0;
248
+
249
+ /* Find substrings in the output buffer that need to be randomized. */
250
+ if (config.randomkeys) {
251
+ char *p = c->obuf, *newline;
252
+ while ((p = strstr(p,":rand:")) != NULL) {
253
+ newline = strstr(p,"\r\n");
254
+ assert(newline-(p+6) == 12); /* 12 chars for randomness */
255
+ assert(c->randlen < (signed)(sizeof(c->randptr)/sizeof(char*)));
256
+ c->randptr[c->randlen++] = p+6;
257
+ p = newline+2;
258
+ }
259
+ }
260
+
261
+ redisSetReplyObjectFunctions(c->context,NULL);
262
+ aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c);
263
+ listAddNodeTail(config.clients,c);
264
+ config.liveclients++;
265
+ return c;
266
+ }
267
+
268
+ static void createMissingClients(client c) {
269
+ int n = 0;
270
+
271
+ while(config.liveclients < config.numclients) {
272
+ createClient(c->obuf,sdslen(c->obuf));
273
+
274
+ /* Listen backlog is quite limited on most systems */
275
+ if (++n > 64) {
276
+ usleep(50000);
277
+ n = 0;
278
+ }
279
+ }
280
+ }
281
+
282
+ static int compareLatency(const void *a, const void *b) {
283
+ return (*(long long*)a)-(*(long long*)b);
284
+ }
285
+
286
+ static void showLatencyReport(void) {
287
+ int i, curlat = 0;
288
+ float perc, reqpersec;
289
+
290
+ reqpersec = (float)config.donerequests/((float)config.totlatency/1000);
291
+ if (!config.quiet) {
292
+ printf("====== %s ======\n", config.title);
293
+ printf(" %d requests completed in %.2f seconds\n", config.donerequests,
294
+ (float)config.totlatency/1000);
295
+ printf(" %d parallel clients\n", config.numclients);
296
+ printf(" %d bytes payload\n", config.datasize);
297
+ printf(" keep alive: %d\n", config.keepalive);
298
+ printf("\n");
299
+
300
+ qsort(config.latency,config.requests,sizeof(long long),compareLatency);
301
+ for (i = 0; i < config.requests; i++) {
302
+ if (config.latency[i]/1000 != curlat || i == (config.requests-1)) {
303
+ curlat = config.latency[i]/1000;
304
+ perc = ((float)(i+1)*100)/config.requests;
305
+ printf("%.2f%% <= %d milliseconds\n", perc, curlat);
306
+ }
307
+ }
308
+ printf("%.2f requests per second\n\n", reqpersec);
309
+ } else {
310
+ printf("%s: %.2f requests per second\n", config.title, reqpersec);
311
+ }
312
+ }
313
+
314
+ static void benchmark(char *title, char *cmd, int len) {
315
+ client c;
316
+
317
+ config.title = title;
318
+ config.donerequests = 0;
319
+
320
+ c = createClient(cmd,len);
321
+ createMissingClients(c);
322
+
323
+ config.start = mstime();
324
+ aeMain(config.el);
325
+ config.totlatency = mstime()-config.start;
326
+
327
+ showLatencyReport();
328
+ freeAllClients();
329
+ }
330
+
331
+ void parseOptions(int argc, char **argv) {
332
+ int i;
333
+
334
+ for (i = 1; i < argc; i++) {
335
+ int lastarg = i==argc-1;
336
+
337
+ if (!strcmp(argv[i],"-c") && !lastarg) {
338
+ config.numclients = atoi(argv[i+1]);
339
+ i++;
340
+ } else if (!strcmp(argv[i],"-n") && !lastarg) {
341
+ config.requests = atoi(argv[i+1]);
342
+ i++;
343
+ } else if (!strcmp(argv[i],"-k") && !lastarg) {
344
+ config.keepalive = atoi(argv[i+1]);
345
+ i++;
346
+ } else if (!strcmp(argv[i],"-h") && !lastarg) {
347
+ config.hostip = argv[i+1];
348
+ i++;
349
+ } else if (!strcmp(argv[i],"-p") && !lastarg) {
350
+ config.hostport = atoi(argv[i+1]);
351
+ i++;
352
+ } else if (!strcmp(argv[i],"-s") && !lastarg) {
353
+ config.hostsocket = argv[i+1];
354
+ i++;
355
+ } else if (!strcmp(argv[i],"-d") && !lastarg) {
356
+ config.datasize = atoi(argv[i+1]);
357
+ i++;
358
+ if (config.datasize < 1) config.datasize=1;
359
+ if (config.datasize > 1024*1024) config.datasize = 1024*1024;
360
+ } else if (!strcmp(argv[i],"-r") && !lastarg) {
361
+ config.randomkeys = 1;
362
+ config.randomkeys_keyspacelen = atoi(argv[i+1]);
363
+ if (config.randomkeys_keyspacelen < 0)
364
+ config.randomkeys_keyspacelen = 0;
365
+ i++;
366
+ } else if (!strcmp(argv[i],"-q")) {
367
+ config.quiet = 1;
368
+ } else if (!strcmp(argv[i],"-l")) {
369
+ config.loop = 1;
370
+ } else if (!strcmp(argv[i],"-D")) {
371
+ config.debug = 1;
372
+ } else if (!strcmp(argv[i],"-I")) {
373
+ config.idlemode = 1;
374
+ } else {
375
+ printf("Wrong option '%s' or option argument missing\n\n",argv[i]);
376
+ printf("Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]\n\n");
377
+ printf(" -h <hostname> Server hostname (default 127.0.0.1)\n");
378
+ printf(" -p <port> Server port (default 6379)\n");
379
+ printf(" -s <socket> Server socket (overrides host and port)\n");
380
+ printf(" -c <clients> Number of parallel connections (default 50)\n");
381
+ printf(" -n <requests> Total number of requests (default 10000)\n");
382
+ printf(" -d <size> Data size of SET/GET value in bytes (default 2)\n");
383
+ printf(" -k <boolean> 1=keep alive 0=reconnect (default 1)\n");
384
+ printf(" -r <keyspacelen> Use random keys for SET/GET/INCR, random values for SADD\n");
385
+ printf(" Using this option the benchmark will get/set keys\n");
386
+ printf(" in the form mykey_rand000000012456 instead of constant\n");
387
+ printf(" keys, the <keyspacelen> argument determines the max\n");
388
+ printf(" number of values for the random number. For instance\n");
389
+ printf(" if set to 10 only rand000000000000 - rand000000000009\n");
390
+ printf(" range will be allowed.\n");
391
+ printf(" -q Quiet. Just show query/sec values\n");
392
+ printf(" -l Loop. Run the tests forever\n");
393
+ printf(" -I Idle mode. Just open N idle connections and wait.\n");
394
+ printf(" -D Debug mode. more verbose.\n");
395
+ exit(1);
396
+ }
397
+ }
398
+ }
399
+
400
+ int showThroughput(struct aeEventLoop *eventLoop, long long id, void *clientData) {
401
+ REDIS_NOTUSED(eventLoop);
402
+ REDIS_NOTUSED(id);
403
+ REDIS_NOTUSED(clientData);
404
+
405
+ float dt = (float)(mstime()-config.start)/1000.0;
406
+ float rps = (float)config.donerequests/dt;
407
+ printf("%s: %.2f\r", config.title, rps);
408
+ fflush(stdout);
409
+ return 250; /* every 250ms */
410
+ }
411
+
412
+ int main(int argc, char **argv) {
413
+ int i;
414
+ client c;
415
+
416
+ signal(SIGHUP, SIG_IGN);
417
+ signal(SIGPIPE, SIG_IGN);
418
+
419
+ config.debug = 0;
420
+ config.numclients = 50;
421
+ config.requests = 10000;
422
+ config.liveclients = 0;
423
+ config.el = aeCreateEventLoop();
424
+ aeCreateTimeEvent(config.el,1,showThroughput,NULL,NULL);
425
+ config.keepalive = 1;
426
+ config.donerequests = 0;
427
+ config.datasize = 3;
428
+ config.randomkeys = 0;
429
+ config.randomkeys_keyspacelen = 0;
430
+ config.quiet = 0;
431
+ config.loop = 0;
432
+ config.idlemode = 0;
433
+ config.latency = NULL;
434
+ config.clients = listCreate();
435
+ config.hostip = "127.0.0.1";
436
+ config.hostport = 6379;
437
+ config.hostsocket = NULL;
438
+
439
+ parseOptions(argc,argv);
440
+ config.latency = zmalloc(sizeof(long long)*config.requests);
441
+
442
+ if (config.keepalive == 0) {
443
+ printf("WARNING: keepalive disabled, you probably need 'echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse' for Linux and 'sudo sysctl -w net.inet.tcp.msl=1000' for Mac OS X in order to use a lot of clients/requests\n");
444
+ }
445
+
446
+ if (config.idlemode) {
447
+ printf("Creating %d idle connections and waiting forever (Ctrl+C when done)\n", config.numclients);
448
+ c = createClient("",0); /* will never receive a reply */
449
+ createMissingClients(c);
450
+ aeMain(config.el);
451
+ /* and will wait for every */
452
+ }
453
+
454
+ do {
455
+ char *data, *cmd;
456
+ int len;
457
+
458
+ data = zmalloc(config.datasize+1);
459
+ memset(data,'x',config.datasize);
460
+ data[config.datasize] = '\0';
461
+
462
+ benchmark("PING (inline)","PING\r\n",6);
463
+
464
+ len = redisFormatCommand(&cmd,"PING");
465
+ benchmark("PING",cmd,len);
466
+ free(cmd);
467
+
468
+ const char *argv[21];
469
+ argv[0] = "MSET";
470
+ for (i = 1; i < 21; i += 2) {
471
+ argv[i] = "foo:rand:000000000000";
472
+ argv[i+1] = data;
473
+ }
474
+ len = redisFormatCommandArgv(&cmd,21,argv,NULL);
475
+ benchmark("MSET (10 keys)",cmd,len);
476
+ free(cmd);
477
+
478
+ len = redisFormatCommand(&cmd,"SET foo:rand:000000000000 %s",data);
479
+ benchmark("SET",cmd,len);
480
+ free(cmd);
481
+
482
+ len = redisFormatCommand(&cmd,"GET foo:rand:000000000000");
483
+ benchmark("GET",cmd,len);
484
+ free(cmd);
485
+
486
+ len = redisFormatCommand(&cmd,"INCR counter:rand:000000000000");
487
+ benchmark("INCR",cmd,len);
488
+ free(cmd);
489
+
490
+ len = redisFormatCommand(&cmd,"LPUSH mylist %s",data);
491
+ benchmark("LPUSH",cmd,len);
492
+ free(cmd);
493
+
494
+ len = redisFormatCommand(&cmd,"LPOP mylist");
495
+ benchmark("LPOP",cmd,len);
496
+ free(cmd);
497
+
498
+ len = redisFormatCommand(&cmd,"SADD myset counter:rand:000000000000");
499
+ benchmark("SADD",cmd,len);
500
+ free(cmd);
501
+
502
+ len = redisFormatCommand(&cmd,"SPOP myset");
503
+ benchmark("SPOP",cmd,len);
504
+ free(cmd);
505
+
506
+ len = redisFormatCommand(&cmd,"LPUSH mylist %s",data);
507
+ benchmark("LPUSH (again, in order to bench LRANGE)",cmd,len);
508
+ free(cmd);
509
+
510
+ len = redisFormatCommand(&cmd,"LRANGE mylist 0 99");
511
+ benchmark("LRANGE (first 100 elements)",cmd,len);
512
+ free(cmd);
513
+
514
+ len = redisFormatCommand(&cmd,"LRANGE mylist 0 299");
515
+ benchmark("LRANGE (first 300 elements)",cmd,len);
516
+ free(cmd);
517
+
518
+ len = redisFormatCommand(&cmd,"LRANGE mylist 0 449");
519
+ benchmark("LRANGE (first 450 elements)",cmd,len);
520
+ free(cmd);
521
+
522
+ len = redisFormatCommand(&cmd,"LRANGE mylist 0 599");
523
+ benchmark("LRANGE (first 600 elements)",cmd,len);
524
+ free(cmd);
525
+
526
+ printf("\n");
527
+ } while(config.loop);
528
+
529
+ return 0;
530
+ }