class_docstr: A locust-like benchmark tool with asyncio.
  Features:
  * Very efficient, low CPU cost
  * Could be embedded into other asyncio apps, like jupyter notebook
  
  Paras:
  * request_producer: The test case producer, a function with return value
      (url: str, method: str, headers: dict, data: str)
  * request_interval: intervals in seconds between each requests of the same user,
    lazy value supported.
      for eg:
          - 1  # for constant 1 sec
          - lambda: random.random()  # for random wait time between 0 and 1
  * url_override: override the url provided by request_producer
  
  
  Example usage
  =========
  
  In a session of one minute, 100 users keep sending POST request with
  one seconds interval:
  
  ``` test.py
  def test_case_producer():
      return ('http://localhost:3000',
              "POST",
              {"Content-Type": "application/json"},
              '{"x": 1.0}')
  
  from bentoml.utils.benchmark import BenchmarkClient
  b = BenchmarkClient(test_case_producer, request_interval=1, timeout=10)
  b.start_session(session_time=60, total_user=100)
  ```
  
  run command:
  > python test.py
class_docstr_tok: ["A","locust-like","benchmark","tool","with","asyncio",".","Features",":","*","Very","efficient",",","low","CPU","cost","*","Could","be","embedded","into","other","asyncio","apps",",","like","jupyter","notebook","Paras",":","*","request_producer",":","The","test","case","producer",",","a","function","with","return","value","(","url",":","str",",","method",":","str",",","headers",":","dict",",","data",":","str",")","*","request_interval",":","intervals","in","seconds","between","each","requests","of","the","same","user",",","lazy","value","supported",".","for","eg",":","-","1","#","for","constant","1","sec","-","lambda",":","random.random","(",")","#","for","random","wait","time","between","0","and","1","*","url_override",":","override","the","url","provided","by","request_producer","Example","usage","=========","In","a","session","of","one","minute",",","100","users","keep","sending","POST","request","with","one","seconds","interval",":","``","`","test.py","def","test_case_producer","(",")",":","return","(","'http",":","\/\/localhost:3000","'",",","``","POST","''",",","{","``","Content-Type","''",":","``","application\/json","''","}",",","'","{","``","x","''",":","1.0","}","'",")","from","bentoml.utils.benchmark","import","BenchmarkClient","b","=","BenchmarkClient","(","test_case_producer",",","request_interval=1",",","timeout=10",")","b.start_session","(","session_time=60",",","total_user=100",")","``","`","run","command",":",">","python","test.py"]
code: def spawn(self):
      self.user_pool.append(
          asyncio.get_event_loop().create_task(self._start())
      )
  
imports: import asyncio
  import math
  import time
  from collections import defaultdict
  from tabulate import tabulate
label_desc: Use image node_id 2 for calling the BenchmarkClient obj's underlying member method code with example usage: obj.spawn() without return types