67 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			67 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Micro benchmark comparing match as "switch" with if-elif and dict access"""
 | |
| 
 | |
| from timeit import timeit
 | |
| 
 | |
| 
 | |
| def make_match(count: int) -> str:
 | |
|     code = f"for val in range({count}):\n    match val:\n"
 | |
|     for n in range(count):
 | |
|         m = n + 1
 | |
|         code += f"        case {n}:\n"
 | |
|         code += f"            res = {m}\n"
 | |
|     return code
 | |
| 
 | |
| 
 | |
| def make_elif(count: int) -> str:
 | |
|     code = f"for val in range({count}):\n"
 | |
|     for n in range(count):
 | |
|         m = n + 1
 | |
|         code += f"    {'' if n == 0 else 'el'}if val == {n}:\n"
 | |
|         code += f"        res = {m}\n"
 | |
|     return code
 | |
| 
 | |
| 
 | |
| def make_dict(count: int, mode: str) -> str:
 | |
|     if mode == "value":
 | |
|         code = "dct = {\n"
 | |
|         for n in range(count):
 | |
|             m = n + 1
 | |
|             code += f"    {n}: {m},\n"
 | |
|         code += "}\n"
 | |
|         code += f"for val in range({count}):\n    res = dct[val]"
 | |
|         return code
 | |
|     elif mode == "call":
 | |
|         code = ""
 | |
|         for n in range(count):
 | |
|             m = n + 1
 | |
|             code += f"def func{n}():\n    val = {m}\n\n"
 | |
|         code += "dct = {\n"
 | |
|         for n in range(count):
 | |
|             code += f"    {n}: func{n},\n"
 | |
|         code += "}\n"
 | |
|         code += f"for val in range({count}):\n    dct[val]()"
 | |
|         return code
 | |
|     return ""
 | |
| 
 | |
| 
 | |
| def timeit_best_of_5(stmt: str, setup: str = "pass") -> float:
 | |
|     """
 | |
|     Benchmark some code, returning the best of 5 runs.
 | |
|     :param stmt: Code to benchmark
 | |
|     :param setup: Optional code to set up environment
 | |
|     :return: Time taken in microseconds
 | |
|     """
 | |
|     return min(timeit(stmt, setup, number=10000, globals={}) for _ in range(5)) * 100
 | |
| 
 | |
| 
 | |
| def main() -> None:
 | |
|     for count in (3, 5, 8, 10, 20, 30):
 | |
|         print(f"value of {count:-2} with match: {timeit_best_of_5(make_match(count)) / count:.3f} us")
 | |
|         print(f"value of {count:-2} with elif:  {timeit_best_of_5(make_elif(count)) / count:.3f} us")
 | |
|         print(f"value of {count:-2} with dict:  {timeit_best_of_5(make_dict(count, 'value')) / count:.3f} us")
 | |
|         print(f"call  of {count:-2} with dict:  {timeit_best_of_5(make_dict(count, 'call')) / count:.3f} us")
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()
 | 
