├── .gitmodules ├── README.md └── script.py /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "nstore"] 2 | path = nstore 3 | url = https://github.com/snalli/nstore 4 | branch = placement_new_on_psegments 5 | [submodule "mnemosyne-gcc"] 6 | path = mnemosyne-gcc 7 | url = https://github.com/snalli/mnemosyne-gcc 8 | branch = master 9 | [submodule "nvml"] 10 | path = nvml 11 | url = https://github.com/snalli/nvml 12 | branch = master 13 | [submodule "redis"] 14 | path = redis 15 | url = https://github.com/snalli/redis 16 | branch = 3.2-nvml 17 | [submodule "PMFS-new"] 18 | path = PMFS-new 19 | url = https://github.com/snalli/PMFS-new 20 | branch = master 21 | [submodule "kv-echo"] 22 | path = kv-echo 23 | url = https://github.com/snalli/echo 24 | branch = bailey 25 | [submodule "eliza"] 26 | path = eliza 27 | url = https://github.com/snalli/eliza 28 | branch = master 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WHISPER 1.0 2 | 3 | **WHISPER**, or **Wisconsin-HPL Suite for Persistence** is a comprehensive benchmark 4 | suite for emerging persistent memory technologies. For more details : 5 | 6 | **An Analysis of Persistent Memory Use with WHISPER**. *ASPLOS'17*. 7 | 8 | Sanketh Nalli, Swapnil Haria, Mike Swift, Mark Hill, Haris Volos, Kim Keeton. 9 | 10 | research.cs.wisc.edu/multifacet/whisper/ 11 | 12 | ## IMPORTANT 13 | We are currently testing WHISPER in various environments. 14 | PLEASE USE AT YOUR OWN RISK. 15 | Report issues and suggestions to Swapnil (swapnilh at cs dot wisc edu) or Sanketh (sankey 16 | at cs dot wisc dot edu). 17 | 18 | Eliza is a tool to process traces generated by WHISPER applications. 19 | You may use it or develop your own for your analysis. 20 | 21 | ## To download: 22 | ~~~ 23 | $ git clone --recursive https://github.com/swapnilh/whisper.git 24 | $ cd whisper 25 | ~~~ 26 | OR 27 | ~~~ 28 | $ git clone https://github.com/swapnilh/whisper.git 29 | $ cd whisper 30 | $ ./script.py -d 31 | ~~~ 32 | 33 | ## To build: 34 | ~~~ 35 | $ cd whisper 36 | $ ./script.py -b \ 37 | -w {ycsb,tpcc,echo,redis,ctree,hashmap,memcached,vacation,nfs,exim,sql,all} 38 | ~~~ 39 | 40 | ## To run (tracing is optional, but need to be root for it): 41 | ~~~ 42 | $ cd whisper 43 | $ ./script.py -r [-t] -z {small|med|large} \ 44 | -w {ycsb,tpcc,echo,redis,ctree,hashmap,memcached,vacation,nfs,exim,sql,all} 45 | ~~~ 46 | 47 | ## To clean: 48 | ~~~ 49 | $ cd whisper 50 | $ ./script.py -c \ 51 | -w {ycsb,tpcc,echo,redis,ctree,hashmap,memcached,vacation,nfs,exim,sql,all} 52 | ~~~ 53 | 54 | ## To update: 55 | ~~~ 56 | $ cd whisper 57 | $ ./script.py -u 58 | git submodule update --remote 59 | git submodule update status 60 | 61 | ~~~ 62 | 63 | ## For help: 64 | ~~~ 65 | $ cd whisper 66 | $ ./script.py -h 67 | 68 | usage: script.py [-h] [-d] [-b] [-r] 69 | [-w {ycsb,tpcc,echo,redis,ctree,hashmap,memcached,vacation,nfs,exim,sql,all}] 70 | [-z {small,med,large}] [-t] [-c] [-s] [-u] [-p] 71 | 72 | Buildi, Clean, Run, Update WHISPER 73 | 74 | optional arguments: 75 | -h, --help show this help message and exit 76 | -d Download workload 77 | -b Build workload 78 | -r Run workload 79 | -w {ycsb,tpcc,echo,redis,ctree,hashmap,memcached,vacation,nfs,exim,sql,all} 80 | Workload 81 | -z {small,med,large} Set workload size 82 | -t Enable tracing. Need to be root. 83 | -c Clean workload 84 | -s Clean workload and dependencies 85 | -u Update benchmark 86 | -p More help for a workload 87 | 88 | ~~~ 89 | 90 | ## For more help: 91 | ~~~ 92 | Example, 93 | $ ./script.py -w vacation -p 94 | 95 | Usage: ./build/bench/stamp-kozy/vacation/vacation [options] 96 | 97 | Options: (defaults) 98 | c Number of [c]lients (1) 99 | n [n]umber of user queries/transaction (10) 100 | q Percentage of relations [q]ueried (90) 101 | t Number of [t]ransactions (131072) 102 | r Number of [r]ows (5767168) 103 | u Percentage of [u]ser transactions (80) 104 | e Enable trac[e] collection (0) 105 | 106 | ~~~ 107 | 108 | ## FAQs : 109 | 110 | #### 1. For Nstore-{YCSB, TPCC} and Echo I get a runtime error that says "no free memory of size 128 available". 111 | #### What do I do ? 112 | 113 | Nstore and Echo create a file in /dev/shm (zfile for nstore and efile for echo} 114 | which act as persistent memory pools. So does every application in WHISPER. 115 | The default size is 1GB. When space is low, 116 | the above error is thrown. We will make this a run time parameter in the future. For now, simply increase it by altering the PSEGMENT_RESERVED_REGION_SIZE 117 | in Nstore and Echo. You may find this variable by using grep, cscope or any indexing tool for browsing source code. 118 | Its location varies with application. Delete the old pool, recompile and re-run. Suggested sizes are as shown. 119 | Please pay attention to the format of defining the size i.e. XXX * 1024 * 1024 * 1024. This is in bytes. 120 | 121 | ~~~ 122 | #define PSEGMENT_RESERVED_REGION_SIZE (2UL * 1024 * 1024 * 1024) // 2GB 123 | #define PSEGMENT_RESERVED_REGION_SIZE (4UL * 1024 * 1024 * 1024) // 4GB 124 | #define PSEGMENT_RESERVED_REGION_SIZE (8UL * 1024 * 1024 * 1024) // 8GB 125 | ~~~ 126 | 127 | You may also reduce the size as follows. 128 | 129 | ~~~ 130 | #define PSEGMENT_RESERVED_REGION_SIZE (512 * 1024 * 1024) // 512MB 131 | #define PSEGMENT_RESERVED_REGION_SIZE (256 * 1024 * 1024) // 256MB 132 | #define PSEGMENT_RESERVED_REGION_SIZE (128 * 1024 * 1024) // 128MB 133 | ~~~ 134 | -------------------------------------------------------------------------------- /script.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import sys 5 | import os 6 | import time 7 | 8 | DBG = 0 9 | 10 | __ycs = 'ycsb' 11 | __tpc = 'tpcc' 12 | __eco = 'echo' 13 | __red = 'redis' 14 | __ctr = 'ctree' 15 | __map = 'hashmap' 16 | __mem = 'memcached' 17 | __vac = 'vacation' 18 | __nfs = 'nfs' 19 | __exm = 'exim' 20 | __sql = 'sql' 21 | __all = 'all' 22 | __emt = 'empty' 23 | 24 | workload_l = [] 25 | workload_l.append(__ycs) 26 | workload_l.append(__tpc) 27 | workload_l.append(__eco) 28 | workload_l.append(__red) 29 | workload_l.append(__ctr) 30 | workload_l.append(__map) 31 | workload_l.append(__mem) 32 | workload_l.append(__vac) 33 | workload_l.append(__nfs) 34 | workload_l.append(__exm) 35 | workload_l.append(__sql) 36 | workload_l.append(__all) 37 | 38 | __home = os.getcwd() 39 | __nstr = 'nstore' 40 | __echo = 'kv-echo/echo/src' 41 | __nemo = 'mnemosyne-gcc/usermode' 42 | __nvml = 'nvml' 43 | __reds = 'redis' 44 | __pmfs = 'PMFS-new' 45 | 46 | dir_l = [] 47 | dir_l.append(__nstr) 48 | dir_l.append(__echo) 49 | dir_l.append(__nemo) 50 | dir_l.append(__nvml) 51 | dir_l.append(__reds) 52 | dir_l.append(__pmfs) 53 | 54 | __s = 'small' 55 | __m = 'med' 56 | __l = 'large' 57 | 58 | size_l = [] 59 | size_l.append(__s) 60 | size_l.append(__m) 61 | size_l.append(__l) 62 | 63 | parser = argparse.ArgumentParser(prog="script", description="Buildi, Clean, Run, Update WHISPER") 64 | parser.add_argument('-d', dest='downld', action='store_true', default=False, help="Download workload") 65 | parser.add_argument('-b', dest='build', action='store_true', default=False, help="Build workload") 66 | parser.add_argument('-r', dest='run' , action='store_true', default=False, help="Run workload") 67 | parser.add_argument('-w', dest='workload', default=__emt, help="Workload", choices=workload_l) 68 | parser.add_argument('-z', dest='size', default=__l, help="Set workload size", choices=size_l) 69 | parser.add_argument('-t', dest='trace', action='store_true', default=False, help="Enable tracing. Need to be root.") 70 | parser.add_argument('-c', dest='clean', action='store_true', default=False, help="Clean workload") 71 | parser.add_argument('-s', dest='scratch', action='store_true', default=False, help="Clean workload and dependencies") 72 | parser.add_argument('-u', dest='update', action='store_true', default=False, help="Update benchmark") 73 | parser.add_argument('-p', dest='mhelp', action='store_true', default=False, help="More help for a workload") 74 | 75 | 76 | try: 77 | args = parser.parse_args() 78 | except: 79 | sys.exit(0) 80 | 81 | def ex(): 82 | sys.exit(0) 83 | 84 | def dbg(s): 85 | 86 | if DBG == 1: 87 | print s 88 | 89 | def msg(s): 90 | 91 | print '\n' + '>>> ' + s + '\n' 92 | 93 | def cd(dirt): 94 | 95 | dbg(dirt) 96 | 97 | if dirt == __home: 98 | os.chdir(__home); 99 | else: 100 | 101 | path = __home + '/' + dirt 102 | dbg(path) 103 | 104 | try: 105 | os.chdir(path) 106 | except: 107 | print 'invalid directory ', path 108 | sys.exit(0) 109 | 110 | def sh(cmd): 111 | 112 | dbg(cmd) 113 | msg(cmd) 114 | try: 115 | os.system(cmd) 116 | except: 117 | print 'invalid cmd ', cmd 118 | sys.exit(0) 119 | 120 | def stat(f): 121 | 122 | dbg(os.getcwd() + '/' + f) 123 | try: 124 | os.stat(f) 125 | except: 126 | dbg('invalid file' + os.getcwd() + '/' + f) 127 | return 1 128 | 129 | return 0 130 | 131 | def build(sysargs): 132 | 133 | args = sysargs 134 | w = args.workload 135 | 136 | if w == __ycs: 137 | 138 | d = __nstr 139 | 140 | cd(d) 141 | 142 | if stat('Makefile') == 1: 143 | cmd = './bootstrap;./configure' 144 | sh(cmd) 145 | 146 | cmd = 'make' 147 | sh(cmd) 148 | 149 | cd(__home) 150 | 151 | elif w == __tpc: 152 | 153 | d = __nstr 154 | 155 | cd(d) 156 | 157 | if stat('Makefile') == 1: 158 | cmd = './bootstrap;./configure' 159 | sh(cmd) 160 | 161 | cmd = 'make' 162 | sh(cmd) 163 | 164 | cd(__home) 165 | 166 | elif w == __eco: 167 | 168 | d = __echo 169 | 170 | cd(d) 171 | 172 | if stat('malloc/gperftools-2.0/Makefile') == 1: 173 | cmd = './make-tcmalloc.sh' 174 | sh(cmd) 175 | 176 | cmd = 'make clean && make' 177 | sh(cmd) 178 | 179 | cd(__home) 180 | 181 | elif w == __red: 182 | d = __reds 183 | 184 | cd(d) 185 | 186 | cmd = './build.sh' 187 | sh(cmd) 188 | 189 | cd(__home) 190 | 191 | elif w == __ctr: 192 | d = __nvml 193 | 194 | cd(d) 195 | 196 | cmd = './build.sh' 197 | sh(cmd) 198 | 199 | cd(__home) 200 | 201 | elif w == __map: 202 | d = __nvml 203 | 204 | cd(d) 205 | 206 | cmd = './build.sh' 207 | sh(cmd) 208 | 209 | cd(__home) 210 | 211 | elif w == __mem: 212 | d = __nemo 213 | 214 | cd(d) 215 | 216 | cmd = 'scons --build-bench=memcached --config-ftrace' 217 | sh(cmd) 218 | 219 | cd(__home) 220 | 221 | elif w == __vac: 222 | d = __nemo 223 | 224 | cd(d) 225 | 226 | cmd = 'scons --build-bench=stamp-kozy --config-ftrace' 227 | sh(cmd) 228 | 229 | cd(__home) 230 | 231 | elif w == __nfs: 232 | d = __pmfs 233 | msg('please visit github.com/snalli/PMFS-new'); 234 | elif w == __exm: 235 | d = __pmfs 236 | msg('please visit github.com/snalli/PMFS-new'); 237 | elif w == __sql: 238 | d = __pmfs 239 | msg('please visit github.com/snalli/PMFS-new'); 240 | else: 241 | return 242 | 243 | def clean(sysargs): 244 | 245 | args = sysargs 246 | w = args.workload 247 | s = args.scratch 248 | 249 | if w == __ycs: 250 | 251 | d = __nstr 252 | 253 | cd(d) 254 | 255 | if s is True: 256 | cmd = './bootstrap;./configure' 257 | sh(cmd) 258 | 259 | cmd = 'make clean' 260 | sh(cmd) 261 | 262 | cd(__home) 263 | 264 | elif w == __tpc: 265 | 266 | d = __nstr 267 | 268 | cd(d) 269 | 270 | if s is True: 271 | cmd = './bootstrap;./configure' 272 | sh(cmd) 273 | 274 | cmd = 'make clean' 275 | sh(cmd) 276 | 277 | cd(__home) 278 | 279 | elif w == __eco: 280 | 281 | d = __echo 282 | 283 | cd(d) 284 | 285 | cmd = 'make clean' 286 | sh(cmd) 287 | 288 | cd(__home) 289 | 290 | elif w == __red: 291 | d = __reds 292 | 293 | cd(d) 294 | 295 | cmd = './clean.sh' 296 | sh(cmd) 297 | 298 | if s is True: 299 | cmd = 'make distclean' 300 | sh(cmd) 301 | 302 | cd(__home) 303 | 304 | elif w == __ctr: 305 | d = __nvml 306 | 307 | cd(d) 308 | 309 | cmd = './clean.sh' 310 | sh(cmd) 311 | 312 | if s is True: 313 | cmd = 'make distclean' 314 | sh(cmd) 315 | 316 | cd(__home) 317 | 318 | elif w == __map: 319 | d = __nvml 320 | 321 | cd(d) 322 | 323 | cmd = './clean.sh' 324 | sh(cmd) 325 | 326 | if s is True: 327 | cmd = 'make distclean' 328 | sh(cmd) 329 | 330 | cd(__home) 331 | 332 | elif w == __mem: 333 | d = __nemo 334 | 335 | cd(d) 336 | 337 | cmd = 'rm -fr build/memcached*/' 338 | sh(cmd) 339 | 340 | if s is True: 341 | cmd = 'rm -fr build/' 342 | sh(cmd) 343 | 344 | cd(__home) 345 | 346 | elif w == __vac: 347 | d = __nemo 348 | 349 | cd(d) 350 | 351 | cmd = 'rm -fr build/stamp*/' 352 | sh(cmd) 353 | 354 | if s is True: 355 | cmd = 'rm -fr build/' 356 | sh(cmd) 357 | 358 | cd(__home) 359 | 360 | elif w == __nfs: 361 | d = __pmfs 362 | msg('please visit github.com/snalli/PMFS-new'); 363 | elif w == __exm: 364 | d = __pmfs 365 | msg('please visit github.com/snalli/PMFS-new'); 366 | elif w == __sql: 367 | d = __pmfs 368 | msg('please visit github.com/snalli/PMFS-new'); 369 | else: 370 | return 371 | 372 | def more_help(sysargs): 373 | 374 | args = sysargs 375 | w = args.workload 376 | 377 | if w == __ycs: 378 | 379 | d = __nstr 380 | 381 | cd(d) 382 | cmd = './run.sh -h' 383 | sh(cmd) 384 | cd(__home) 385 | 386 | elif w == __tpc: 387 | 388 | d = __nstr 389 | 390 | cd(d) 391 | cmd = './run.sh -h' 392 | sh(cmd) 393 | cd(__home) 394 | 395 | elif w == __eco: 396 | 397 | d = __echo 398 | 399 | cd(d) 400 | cmd = './run.sh -h' 401 | sh(cmd) 402 | cd(__home) 403 | 404 | 405 | elif w == __red: 406 | d = __reds 407 | 408 | cd(d) 409 | cmd = './run-redis-server.sh -h' 410 | sh(cmd) 411 | cmd = './run-redis-cli.sh -h' 412 | sh(cmd) 413 | 414 | cd(__home) 415 | 416 | elif w == __ctr: 417 | d = __nvml 418 | 419 | cd(d) 420 | cmd = './run_ctree.sh -h' 421 | sh(cmd) 422 | cd(__home) 423 | 424 | elif w == __map: 425 | d = __nvml 426 | 427 | cd(d) 428 | cmd = './run_hashmap.sh -h' 429 | sh(cmd) 430 | cd(__home) 431 | 432 | elif w == __mem: 433 | d = __nemo 434 | 435 | cd(d) 436 | cmd = './run_memcache.sh -h' 437 | sh(cmd) 438 | cmd = './run_memslap.sh -h' 439 | sh(cmd) 440 | cd(__home) 441 | 442 | elif w == __vac: 443 | d = __nemo 444 | 445 | cd(d) 446 | cmd = './run_vacation.sh -h' 447 | sh(cmd) 448 | cd(__home) 449 | 450 | 451 | elif w == __nfs: 452 | d = __pmfs 453 | msg('please visit github.com/snalli/PMFS-new'); 454 | elif w == __exm: 455 | d = __pmfs 456 | msg('please visit github.com/snalli/PMFS-new'); 457 | elif w == __sql: 458 | d = __pmfs 459 | msg('please visit github.com/snalli/PMFS-new'); 460 | else: 461 | return 462 | 463 | def z2s(z): 464 | # convert size variable to string 465 | 466 | if z not in size_l: 467 | msg('please pass a valid workload size from ' + str(size_l)) 468 | ex() 469 | 470 | return ' --' + z 471 | 472 | def w2s(w): 473 | # convert workload variable to string 474 | 475 | if w not in workload_l: 476 | msg('please pass a valid workload from ' + str(workload_l)) 477 | ex() 478 | 479 | return ' --' + w 480 | 481 | def t2s(t): 482 | 483 | # convert trace variable to string 484 | 485 | if t is True: 486 | msg('For trace : $ cat /sys/kernel/debug/trace_pipe') 487 | return ' --trace' 488 | else: 489 | return '' 490 | 491 | def su(t): 492 | 493 | # convert privileges 494 | 495 | if t is True: 496 | msg('Need to be root for trace.') 497 | return 'sudo ' 498 | else: 499 | return '' 500 | 501 | def sleep(t): 502 | time.sleep(t) 503 | 504 | def run(sysargs): 505 | 506 | args = sysargs 507 | w = args.workload 508 | z = args.size 509 | t = args.trace 510 | 511 | if w == __ycs: 512 | 513 | d = __nstr 514 | 515 | cd(d) 516 | cmd = su(t) + './run.sh' + z2s(z) + w2s(w) + t2s(t) 517 | dbg(cmd) 518 | 519 | sh(cmd) 520 | cd(__home) 521 | 522 | elif w == __tpc: 523 | 524 | d = __nstr 525 | 526 | cd(d) 527 | cmd = su(t) + './run.sh' + z2s(z) + w2s(w) + t2s(t) 528 | dbg(cmd) 529 | 530 | sh(cmd) 531 | cd(__home) 532 | 533 | elif w == __eco: 534 | 535 | d = __echo 536 | 537 | cd(d) 538 | cmd = su(t) + './run.sh' + z2s(z) + t2s(t) 539 | dbg(cmd) 540 | 541 | sh(cmd) 542 | cd(__home) 543 | 544 | 545 | elif w == __red: 546 | d = __reds 547 | 548 | cd(d) 549 | 550 | 551 | cmd = su(t) + './run-redis-server.sh' + t2s(t) 552 | dbg(cmd) 553 | sh(cmd) 554 | 555 | sleep(2) 556 | msg('starting redis client') 557 | 558 | cmd = './run-redis-cli.sh' + z2s(z) 559 | dbg(cmd) 560 | sh(cmd) 561 | 562 | cmd = su(t) + "kill -s SIGKILL `pgrep redis`" 563 | sh(cmd) 564 | 565 | cd(__home) 566 | 567 | elif w == __ctr: 568 | d = __nvml 569 | 570 | cd(d) 571 | cmd = su(t) + './run_ctree.sh' + z2s(z) + t2s(t) 572 | 573 | sh(cmd) 574 | cd(__home) 575 | 576 | elif w == __map: 577 | d = __nvml 578 | 579 | cd(d) 580 | cmd = su(t) + './run_hashmap.sh' + z2s(z) + t2s(t) 581 | 582 | sh(cmd) 583 | cd(__home) 584 | 585 | elif w == __mem: 586 | d = __nemo 587 | 588 | cd(d) 589 | 590 | cmd = su(t) + './run_memcache.sh' + t2s(t) 591 | dbg(cmd) 592 | sh(cmd) 593 | 594 | sleep(2) 595 | msg('starting memslap client') 596 | 597 | cmd = './run_memslap.sh' + z2s(z) 598 | dbg(cmd) 599 | sh(cmd) 600 | 601 | cmd = su(t) + "kill -s SIGKILL `pgrep memcached`" 602 | sh(cmd) 603 | 604 | cd(__home) 605 | 606 | elif w == __vac: 607 | d = __nemo 608 | 609 | cd(d) 610 | cmd = su(t) + './run.sh' + z2s(z) + w2s(w) + t2s(t) 611 | sh(cmd) 612 | cd(__home) 613 | 614 | 615 | elif w == __nfs: 616 | d = __pmfs 617 | msg('please visit github.com/snalli/PMFS-new'); 618 | elif w == __exm: 619 | d = __pmfs 620 | msg('please visit github.com/snalli/PMFS-new'); 621 | elif w == __sql: 622 | d = __pmfs 623 | msg('please visit github.com/snalli/PMFS-new'); 624 | else: 625 | return 626 | 627 | 628 | if __name__ == '__main__': 629 | 630 | w = args.workload 631 | d = args.downld 632 | r = args.run 633 | c = args.clean 634 | b = args.build 635 | t = args.trace 636 | u = args.update 637 | p = args.mhelp 638 | 639 | if d is True: 640 | cmd='git submodule update --init' 641 | sh(cmd) 642 | 643 | if u is True: 644 | cmd='git pull' 645 | sh(cmd) 646 | cmd='git submodule update' 647 | sh(cmd) 648 | cmd='git submodule status' 649 | sh(cmd) 650 | ex() 651 | 652 | if p is True: 653 | more_help(args) 654 | 655 | if r is True: 656 | if w == __all: 657 | dbg("You can run only one workload at a time.") 658 | sys.exit(0); 659 | else: 660 | if c is True: 661 | clean(args) 662 | if b is True: 663 | build(args) 664 | 665 | run(args) 666 | 667 | if c is True: 668 | if w == __all: 669 | for w in workload_l: 670 | args.workload = w 671 | clean(args) 672 | else: 673 | clean(args) 674 | 675 | if b is True: 676 | if w == __all: 677 | for w in workload_l: 678 | args.workload = w 679 | build(args) 680 | else: 681 | build(args) 682 | 683 | 684 | 685 | --------------------------------------------------------------------------------