bitbake-hashclient 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #! /usr/bin/env python3
  2. #
  3. # Copyright (C) 2019 Garmin Ltd.
  4. #
  5. # SPDX-License-Identifier: GPL-2.0-only
  6. #
  7. import argparse
  8. import hashlib
  9. import logging
  10. import os
  11. import pprint
  12. import sys
  13. import threading
  14. import time
  15. import warnings
  16. warnings.simplefilter("default")
  17. try:
  18. import tqdm
  19. ProgressBar = tqdm.tqdm
  20. except ImportError:
  21. class ProgressBar(object):
  22. def __init__(self, *args, **kwargs):
  23. pass
  24. def __enter__(self):
  25. return self
  26. def __exit__(self, *args, **kwargs):
  27. pass
  28. def update(self):
  29. pass
  30. sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'lib'))
  31. import hashserv
  32. DEFAULT_ADDRESS = 'unix://./hashserve.sock'
  33. METHOD = 'stress.test.method'
  34. def main():
  35. def handle_stats(args, client):
  36. if args.reset:
  37. s = client.reset_stats()
  38. else:
  39. s = client.get_stats()
  40. pprint.pprint(s)
  41. return 0
  42. def handle_stress(args, client):
  43. def thread_main(pbar, lock):
  44. nonlocal found_hashes
  45. nonlocal missed_hashes
  46. nonlocal max_time
  47. client = hashserv.create_client(args.address)
  48. for i in range(args.requests):
  49. taskhash = hashlib.sha256()
  50. taskhash.update(args.taskhash_seed.encode('utf-8'))
  51. taskhash.update(str(i).encode('utf-8'))
  52. start_time = time.perf_counter()
  53. l = client.get_unihash(METHOD, taskhash.hexdigest())
  54. elapsed = time.perf_counter() - start_time
  55. with lock:
  56. if l:
  57. found_hashes += 1
  58. else:
  59. missed_hashes += 1
  60. max_time = max(elapsed, max_time)
  61. pbar.update()
  62. max_time = 0
  63. found_hashes = 0
  64. missed_hashes = 0
  65. lock = threading.Lock()
  66. total_requests = args.clients * args.requests
  67. start_time = time.perf_counter()
  68. with ProgressBar(total=total_requests) as pbar:
  69. threads = [threading.Thread(target=thread_main, args=(pbar, lock), daemon=False) for _ in range(args.clients)]
  70. for t in threads:
  71. t.start()
  72. for t in threads:
  73. t.join()
  74. elapsed = time.perf_counter() - start_time
  75. with lock:
  76. print("%d requests in %.1fs. %.1f requests per second" % (total_requests, elapsed, total_requests / elapsed))
  77. print("Average request time %.8fs" % (elapsed / total_requests))
  78. print("Max request time was %.8fs" % max_time)
  79. print("Found %d hashes, missed %d" % (found_hashes, missed_hashes))
  80. if args.report:
  81. with ProgressBar(total=args.requests) as pbar:
  82. for i in range(args.requests):
  83. taskhash = hashlib.sha256()
  84. taskhash.update(args.taskhash_seed.encode('utf-8'))
  85. taskhash.update(str(i).encode('utf-8'))
  86. outhash = hashlib.sha256()
  87. outhash.update(args.outhash_seed.encode('utf-8'))
  88. outhash.update(str(i).encode('utf-8'))
  89. client.report_unihash(taskhash.hexdigest(), METHOD, outhash.hexdigest(), taskhash.hexdigest())
  90. with lock:
  91. pbar.update()
  92. parser = argparse.ArgumentParser(description='Hash Equivalence Client')
  93. parser.add_argument('--address', default=DEFAULT_ADDRESS, help='Server address (default "%(default)s")')
  94. parser.add_argument('--log', default='WARNING', help='Set logging level')
  95. subparsers = parser.add_subparsers()
  96. stats_parser = subparsers.add_parser('stats', help='Show server stats')
  97. stats_parser.add_argument('--reset', action='store_true',
  98. help='Reset server stats')
  99. stats_parser.set_defaults(func=handle_stats)
  100. stress_parser = subparsers.add_parser('stress', help='Run stress test')
  101. stress_parser.add_argument('--clients', type=int, default=10,
  102. help='Number of simultaneous clients')
  103. stress_parser.add_argument('--requests', type=int, default=1000,
  104. help='Number of requests each client will perform')
  105. stress_parser.add_argument('--report', action='store_true',
  106. help='Report new hashes')
  107. stress_parser.add_argument('--taskhash-seed', default='',
  108. help='Include string in taskhash')
  109. stress_parser.add_argument('--outhash-seed', default='',
  110. help='Include string in outhash')
  111. stress_parser.set_defaults(func=handle_stress)
  112. args = parser.parse_args()
  113. logger = logging.getLogger('hashserv')
  114. level = getattr(logging, args.log.upper(), None)
  115. if not isinstance(level, int):
  116. raise ValueError('Invalid log level: %s' % args.log)
  117. logger.setLevel(level)
  118. console = logging.StreamHandler()
  119. console.setLevel(level)
  120. logger.addHandler(console)
  121. func = getattr(args, 'func', None)
  122. if func:
  123. client = hashserv.create_client(args.address)
  124. return func(args, client)
  125. return 0
  126. if __name__ == '__main__':
  127. try:
  128. ret = main()
  129. except Exception:
  130. ret = 1
  131. import traceback
  132. traceback.print_exc()
  133. sys.exit(ret)