timing.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # encoding: utf-8
  2. """
  3. Utilities for timing code execution.
  4. """
  5. #-----------------------------------------------------------------------------
  6. # Copyright (C) 2008-2011 The IPython Development Team
  7. #
  8. # Distributed under the terms of the BSD License. The full license is in
  9. # the file COPYING, distributed as part of this software.
  10. #-----------------------------------------------------------------------------
  11. #-----------------------------------------------------------------------------
  12. # Imports
  13. #-----------------------------------------------------------------------------
  14. from __future__ import annotations
  15. import time
  16. from typing import Any, Callable
  17. #-----------------------------------------------------------------------------
  18. # Code
  19. #-----------------------------------------------------------------------------
  20. # If possible (Unix), use the resource module instead of time.clock()
  21. try:
  22. import resource
  23. except ModuleNotFoundError:
  24. resource = None # type: ignore [assignment]
  25. # Some implementations (like jyputerlite) don't have getrusage
  26. if resource is not None and hasattr(resource, "getrusage"):
  27. def clocku():
  28. """clocku() -> floating point number
  29. Return the *USER* CPU time in seconds since the start of the process.
  30. This is done via a call to resource.getrusage, so it avoids the
  31. wraparound problems in time.clock()."""
  32. return resource.getrusage(resource.RUSAGE_SELF)[0]
  33. def clocks():
  34. """clocks() -> floating point number
  35. Return the *SYSTEM* CPU time in seconds since the start of the process.
  36. This is done via a call to resource.getrusage, so it avoids the
  37. wraparound problems in time.clock()."""
  38. return resource.getrusage(resource.RUSAGE_SELF)[1]
  39. def clock():
  40. """clock() -> floating point number
  41. Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
  42. the process. This is done via a call to resource.getrusage, so it
  43. avoids the wraparound problems in time.clock()."""
  44. u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
  45. return u+s
  46. def clock2() -> tuple[float, float]:
  47. """clock2() -> (t_user,t_system)
  48. Similar to clock(), but return a tuple of user/system times."""
  49. return resource.getrusage(resource.RUSAGE_SELF)[:2]
  50. else:
  51. # There is no distinction of user/system time under windows, so we just use
  52. # time.process_time() for everything...
  53. clocku = clocks = clock = time.process_time
  54. def clock2() -> tuple[float, float]:
  55. """Under windows, system CPU time can't be measured.
  56. This just returns process_time() and zero."""
  57. return time.process_time(), 0.0
  58. def timings_out(
  59. reps: int,
  60. func: Callable[..., Any],
  61. *args: Any,
  62. **kw: Any,
  63. ) -> tuple[float, float, Any]:
  64. """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
  65. Execute a function reps times, return a tuple with the elapsed total
  66. CPU time in seconds, the time per call and the function's output.
  67. Under Unix, the return value is the sum of user+system time consumed by
  68. the process, computed via the resource module. This prevents problems
  69. related to the wraparound effect which the time.clock() function has.
  70. Under Windows the return value is in wall clock seconds. See the
  71. documentation for the time module for more details."""
  72. reps = int(reps)
  73. assert reps >=1, 'reps must be >= 1'
  74. if reps==1:
  75. start = clock()
  76. out = func(*args,**kw)
  77. tot_time = clock()-start
  78. else:
  79. rng = range(reps-1) # the last time is executed separately to store output
  80. start = clock()
  81. for dummy in rng: func(*args,**kw)
  82. out = func(*args,**kw) # one last time
  83. tot_time = clock()-start
  84. av_time = tot_time / reps
  85. return tot_time,av_time,out
  86. def timings(
  87. reps: int,
  88. func: Callable[..., Any],
  89. *args: Any,
  90. **kw: Any,
  91. ) -> tuple[float, float]:
  92. """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
  93. Execute a function reps times, return a tuple with the elapsed total CPU
  94. time in seconds and the time per call. These are just the first two values
  95. in timings_out()."""
  96. return timings_out(reps,func,*args,**kw)[0:2]
  97. def timing(func: Callable[..., Any], *args: Any, **kw: Any) -> float:
  98. """timing(func,*args,**kw) -> t_total
  99. Execute a function once, return the elapsed total CPU time in
  100. seconds. This is just the first value in timings_out()."""
  101. return timings_out(1,func,*args,**kw)[0]