LSST Applications  21.0.0+75b29a8a7f,21.0.0+e70536a077,21.0.0-1-ga51b5d4+62c747d40b,21.0.0-10-gbfb87ad6+3307648ee3,21.0.0-15-gedb9d5423+47cba9fc36,21.0.0-2-g103fe59+fdf0863a2a,21.0.0-2-g1367e85+d38a93257c,21.0.0-2-g45278ab+e70536a077,21.0.0-2-g5242d73+d38a93257c,21.0.0-2-g7f82c8f+e682ffb718,21.0.0-2-g8dde007+d179fbfa6a,21.0.0-2-g8f08a60+9402881886,21.0.0-2-ga326454+e682ffb718,21.0.0-2-ga63a54e+08647d4b1b,21.0.0-2-gde069b7+26c92b3210,21.0.0-2-gecfae73+0445ed2f95,21.0.0-2-gfc62afb+d38a93257c,21.0.0-27-gbbd0d29+ae871e0f33,21.0.0-28-g5fc5e037+feb0e9397b,21.0.0-3-g21c7a62+f4b9c0ff5c,21.0.0-3-g357aad2+57b0bddf0b,21.0.0-3-g4be5c26+d38a93257c,21.0.0-3-g65f322c+3f454acf5d,21.0.0-3-g7d9da8d+75b29a8a7f,21.0.0-3-gaa929c8+9e4ef6332c,21.0.0-3-ge02ed75+4b120a55c4,21.0.0-4-g3300ddd+e70536a077,21.0.0-4-g591bb35+4b120a55c4,21.0.0-4-gc004bbf+4911b9cd27,21.0.0-4-gccdca77+f94adcd104,21.0.0-4-ge8fba5a+2b3a696ff9,21.0.0-5-gb155db7+2c5429117a,21.0.0-5-gdf36809+637e4641ee,21.0.0-6-g00874e7+c9fd7f7160,21.0.0-6-g4e60332+4b120a55c4,21.0.0-7-gc8ca178+40eb9cf840,21.0.0-8-gfbe0b4b+9e4ef6332c,21.0.0-9-g2fd488a+d83b7cd606,w.2021.05
LSST Data Management Base Package
timer.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010, 2011 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 """Utilities for measuring execution time.
23 """
24 __all__ = ["logInfo", "timeMethod"]
25 
26 import functools
27 import resource
28 import time
29 import datetime
30 
31 from lsst.log import Log, log
32 
33 
34 def logPairs(obj, pairs, logLevel=Log.DEBUG):
35  """Log ``(name, value)`` pairs to ``obj.metadata`` and ``obj.log``
36 
37  Parameters
38  ----------
39  obj : `lsst.pipe.base.Task`-type
40  A `~lsst.pipe.base.Task` or any other object with these two attributes:
41 
42  - ``metadata`` an instance of `lsst.daf.base.PropertyList`` (or other
43  object with ``add(name, value)`` method).
44  - ``log`` an instance of `lsst.log.Log`.
45 
46  pairs : sequence
47  A sequence of ``(name, value)`` pairs, with value typically numeric.
48  logLevel : optional
49  Log level (an `lsst.log` level constant, such as `lsst.log.Log.DEBUG`).
50  """
51  strList = []
52  for name, value in pairs:
53  try:
54  # Use LongLong explicitly here in case an early value in the
55  # sequence is int-sized
56  obj.metadata.addLongLong(name, value)
57  except TypeError:
58  obj.metadata.add(name, value)
59  strList.append(f"{name}={value}")
60  log("timer." + obj.log.getName(), logLevel, "; ".join(strList))
61 
62 
63 def logInfo(obj, prefix, logLevel=Log.DEBUG):
64  """Log timer information to ``obj.metadata`` and ``obj.log``.
65 
66  Parameters
67  ----------
68  obj : `lsst.pipe.base.Task`-type
69  A `~lsst.pipe.base.Task` or any other object with these two attributes:
70 
71  - ``metadata`` an instance of `lsst.daf.base.PropertyList`` (or other
72  object with ``add(name, value)`` method).
73  - ``log`` an instance of `lsst.log.Log`.
74 
75  prefix
76  Name prefix, the resulting entries are ``CpuTime``, etc.. For example
77  timeMethod uses ``prefix = Start`` when the method begins and
78  ``prefix = End`` when the method ends.
79  logLevel : optional
80  Log level (an `lsst.log` level constant, such as `lsst.log.Log.DEBUG`).
81 
82  Notes
83  -----
84  Logged items include:
85 
86  - ``Utc``: UTC date in ISO format (only in metadata since log entries have
87  timestamps).
88  - ``CpuTime``: System + User CPU time (seconds). This should only be used
89  in differential measurements; the time reference point is undefined.
90  - ``MaxRss``: maximum resident set size.
91 
92  All logged resource information is only for the current process; child
93  processes are excluded.
94  """
95  cpuTime = time.process_time()
96  utcStr = datetime.datetime.utcnow().isoformat()
97  res = resource.getrusage(resource.RUSAGE_SELF)
98  obj.metadata.add(name=prefix + "Utc", value=utcStr) # log messages already have timestamps
99  logPairs(obj=obj,
100  pairs=[
101  (prefix + "CpuTime", cpuTime),
102  (prefix + "UserTime", res.ru_utime),
103  (prefix + "SystemTime", res.ru_stime),
104  (prefix + "MaxResidentSetSize", int(res.ru_maxrss)),
105  (prefix + "MinorPageFaults", int(res.ru_minflt)),
106  (prefix + "MajorPageFaults", int(res.ru_majflt)),
107  (prefix + "BlockInputs", int(res.ru_inblock)),
108  (prefix + "BlockOutputs", int(res.ru_oublock)),
109  (prefix + "VoluntaryContextSwitches", int(res.ru_nvcsw)),
110  (prefix + "InvoluntaryContextSwitches", int(res.ru_nivcsw)),
111  ],
112  logLevel=logLevel,
113  )
114 
115 
116 def timeMethod(func):
117  """Decorator to measure duration of a task method.
118 
119  Parameters
120  ----------
121  func
122  The method to wrap.
123 
124  Notes
125  -----
126  Writes various measures of time and possibly memory usage to the task's
127  metadata; all items are prefixed with the function name.
128 
129  .. warning::
130 
131  This decorator only works with instance methods of Task, or any class
132  with these attributes:
133 
134  - ``metadata``: an instance of `lsst.daf.base.PropertyList` (or other
135  object with ``add(name, value)`` method).
136  - ``log``: an instance of `lsst.log.Log`.
137 
138  Examples
139  --------
140  To use:
141 
142  .. code-block:: python
143 
144  import lsst.pipe.base as pipeBase
145  class FooTask(pipeBase.Task):
146  pass
147 
148  @pipeBase.timeMethod
149  def run(self, ...): # or any other instance method you want to time
150  pass
151  """
152 
153  @functools.wraps(func)
154  def wrapper(self, *args, **keyArgs):
155  logInfo(obj=self, prefix=func.__name__ + "Start")
156  try:
157  res = func(self, *args, **keyArgs)
158  finally:
159  logInfo(obj=self, prefix=func.__name__ + "End")
160  return res
161  return wrapper
Definition: Log.h:706
def logPairs(obj, pairs, logLevel=Log.DEBUG)
Definition: timer.py:34
def logInfo(obj, prefix, logLevel=Log.DEBUG)
Definition: timer.py:63
def timeMethod(func)
Definition: timer.py:116