docs: def runs_per_second(generator, seconds=3):
      ''' 
  use this function as a profiler for both functions and generators
  to see how many iterations or cycles they can run per second 
  
  Example usage for timing simple operations/functions:
  
  ``` 
      print(runs_per_second(lambda:1+2))
      # 2074558
      print(runs_per_second(lambda:1-2))
      # 2048523
      print(runs_per_second(lambda:1/2))
      # 2075186
      print(runs_per_second(lambda:1*2))
      # 2101722
      print(runs_per_second(lambda:1**2))
      # 2104572
  ```
  
  Example usage for timing iteration speed of generators:
    
  ``` 
      def counter():
          c = 0
          while 1:
              yield c
              c+=1
  
      print(runs_per_second(counter()))
      # 1697328
      print(runs_per_second((i for i in range(2000))))
      # 1591301
  ``` 
  '''
      assert isinstance(seconds, int), 'runs_per_second needs seconds to be an int, not {}'.format(repr(seconds))
      assert seconds>0, 'runs_per_second needs seconds to be positive, not {}'.format(repr(seconds))
      # if generator is a function, turn it into a generator for testing
      if callable(generator) and not any(i in ('next', '__next__', '__iter__') for i in dir(generator)):
          try:
              # get the output of the function
              output = generator()
          except:
              # if the function crashes without any arguments
              raise Exception('runs_per_second needs a working function that accepts no arguments')
          else:
              # this usage of iter infinitely calls a function until the second argument is the output
              # so I set the second argument to something that isnt what output was.
              generator = iter(generator, (1 if output is None else None))
              del output
      c=0  # run counter, keep this one short for performance reasons
      entire_test_time_used = False
      start = ts()
      end = start+seconds
      for _ in generator:
          if ts()>end:
              entire_test_time_used = True
              break
          else:
              c += 1
      duration = (ts())-start  # the ( ) around ts ensures that it will be the first thing calculated
      return int(c/(seconds if entire_test_time_used else duration))