{ "info": { "author": "Owen Jacobson", "author_email": "owen.jacobson@grimoire.ca", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Topic :: Software Development :: Debuggers", "Topic :: System :: Logging" ], "description": "A simple stack-based performance logger.\n\nWallclock provides some simple tools for identifying slow parts of your code.\nIt maintains a stack of running timers, and reports the tree of execution\ntimes when the stack empties out.\n\nSimple Usage\n------------\n\nTo time code with wallclock, use the ``push`` and ``pop`` functions provided\nby the wallclock module::\n\n import wallclock\n \n def slow_function():\n wallclock.push('slow function')\n import time\n time.sleep(3)\n wallclock.pop('slow function')\n \n def main():\n wallclock.push('handling one request', enable=True)\n slow_function()\n wallclock.pop('handling one request')\n \n main()\n\nThis will produce a small tree on ``stderr`` summarizing the time taken to\nexecute ``main()``::\n\n [3.001 sec] handling one request\n [3.001 sec] slow function\n\nThe ``push`` function takes one positional argument, which is the label of the\ntimer being pushed onto wallclock's stack. This is normally a short,\ndescriptive label for the kind of work that happens under timing. ``push``\nalso takes one optional keyword argument, ``enable``, which controls whether\nthis call to ``push`` should start timing (if it's not already started).\n``wallclock`` ignores calls to ``push`` until it has been enabled, and\ndisables itself automatically when the enabling ``push`` is ``pop``ped.\n\nThe ``pop`` function takes one positional argument, which is the label to pop.\nThis allows for simple insertion of ``push``/``pop`` pairs surrounding code\nthat might return, or might raise an exception, without adding extra\n``try``/``except`` blocks or similar (but see below for a better approach).\n``wallclock`` will pop timers off of the stack until it finds a timer pushed\nwith the passed label, or until it empties the timer stack.\n\nConfiguration\n-------------\n\n``wallclock`` exposes two module-scoped symbols that can be used to control\nits behaviour:\n\n* ``wallclock.threshold`` is a number (``float``, ``int``, or ``long``) of\n seconds. Any timers whose duration is strictly less than ``threshold`` will\n not be recorded. By default, the threshold is approximately 10 milliseconds\n (0.01 seconds). Setting the threshold to ``0`` will record every timer.\n* ``wallclock.output`` is a callable object used to print recorded times. By\n default, it's set to ``wallclock.stderr_output``, which writes the tree to\n standard error, but applications can replace this with their own callables.\n ``wallclock`` invokes ``output`` with one argument, which is the root timer\n object. Timer objects have three readable properties:\n 1. ``label``, which is the label passed to ``push`` when the timer was\n created.\n 2. ``duration``, which is the total time recorded on the timer (in seconds).\n 3. ``children``, which is a sequence of timer objects that were recorded\n while the passed timer object was at the top of the stack.\n\nAutomatic Timer Management\n--------------------------\n\nManually inserting calls to ``push`` and ``pop`` works for debugging, but not\nso well for leaving wallclock in place afterwards. The ``wallclock`` module\nprovides some tidier alternatives.\n\nContext Manager\n~~~~~~~~~~~~~~~\n\nThe ``wallclock.block`` context manager automatically calls ``push`` before\nevaluating the block, and ensures ``pop`` is called after exiting the block by\nany means::\n\n import wallclock\n \n def slow_function():\n with wallclock.block('slow function'):\n import time\n time.sleep(3)\n \n def main():\n with wallclock.block('handling one request', enable=True):\n slow_function()\n \n main()\n\nThe ``block`` context manager accepts the same arguments that ``push``\naccepts: a positional argument labelling the block, and an optional keyword\nargument called ``enable`` for controlling whether the block should start\nwallclock (if it's not already started).\n\nDecorators\n~~~~~~~~~~\n\nThe ``wallclock.function`` and ``wallclock.trace_function`` decorators\nautomatically call ``push`` before executing the decorated function, and\nautomatically call ``pop`` after the function exits, but before returning to\nthe caller::\n\n import wallclock\n \n @wallclock.function\n def slow_function():\n import time\n time.sleep(3)\n \n @wallclock.trace_function\n def main():\n slow_function()\n \n main()\n\nBoth decorators determine the label for the pushed timer by examining the\ncalled function's module and name. ``trace_function`` enables wallclock, while\n``function`` does not.\n\nThreads\n-------\n\nWallclock makes a reasonable effort to keep a timer stack for each thread.\nTimer stacks are kept in a ``threading.threadlocal`` object and are enabled\nand disabled on a per-thread basis.\n\nPerformance\n-----------\n\nTiming your code is not free. While wallclock is noticably faster than a full\nprofiler, it still introduces overhead to manage the stack of pending timers\nand the tree of completed timers. I've found the overhead to be surprisingly\nlarge (a decorated empty function takes ~100x as long as a naked empty\nfunction), but still well within usable limits.\n\nRemoving calls that enable wallclock reduces this overhead considerably. You\ncan further reduce overhead by disabling ``wallclock`` completely by calling\n``wallclock.smash()``. This is an irreversible operation which replaces the\n``push`` and ``pop`` operations, the ``block`` context manager, and the\n``function`` and ``trace_function`` decorators with no-op equivalents.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://bitbucket.org/ojacobson/wallclock", "keywords": null, "license": "MIT License", "maintainer": null, "maintainer_email": null, "name": "wallclock", "package_url": "https://pypi.org/project/wallclock/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/wallclock/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://bitbucket.org/ojacobson/wallclock" }, "release_url": "https://pypi.org/project/wallclock/1.0/", "requires_dist": null, "requires_python": null, "summary": "A simple stack-based performance logger", "version": "1.0" }, "last_serial": 801510, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "b289c3f230c8bc87506dd9e2e9bbe215", "sha256": "d617a8d33578d018a3d2b2a403d4a392e6b7fd16888a29e808b1c45786201ee0" }, "downloads": -1, "filename": "wallclock-1.0-py2.6.egg", "has_sig": false, "md5_digest": "b289c3f230c8bc87506dd9e2e9bbe215", "packagetype": "bdist_egg", "python_version": "2.6", "requires_python": null, "size": 10892, "upload_time": "2012-05-28T16:51:50", "url": "https://files.pythonhosted.org/packages/5a/c9/6cdeb6a24c017278f220f580a39ca618a3b185ac255b8dd24e6c3f0a3315/wallclock-1.0-py2.6.egg" }, { "comment_text": "", "digests": { "md5": "2248010db058a6e2573d7a3cdd118889", "sha256": "fa88dc8bdc20384e41776c5fcec097e40fafb1dc3fc41899c2488a07a293326e" }, "downloads": -1, "filename": "wallclock-1.0-py2.7.egg", "has_sig": false, "md5_digest": "2248010db058a6e2573d7a3cdd118889", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 10843, "upload_time": "2012-05-28T16:51:38", "url": "https://files.pythonhosted.org/packages/d3/1c/ee52c7fe898fa94eba4ea30cfc78f3957cd31288c671076ba7ef9aef0865/wallclock-1.0-py2.7.egg" }, { "comment_text": "", "digests": { "md5": "07b3186ff53567d6bf8f1f4610e151fa", "sha256": "25a1f3aa8551392c602a19e48bac0c6a719d686e577569ba260121d28b083418" }, "downloads": -1, "filename": "wallclock-1.0.tar.gz", "has_sig": false, "md5_digest": "07b3186ff53567d6bf8f1f4610e151fa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6579, "upload_time": "2012-05-28T16:51:38", "url": "https://files.pythonhosted.org/packages/79/39/402785560101aa5f7f8e3d8cf4144580417df4d720afc899983e17a740ae/wallclock-1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b289c3f230c8bc87506dd9e2e9bbe215", "sha256": "d617a8d33578d018a3d2b2a403d4a392e6b7fd16888a29e808b1c45786201ee0" }, "downloads": -1, "filename": "wallclock-1.0-py2.6.egg", "has_sig": false, "md5_digest": "b289c3f230c8bc87506dd9e2e9bbe215", "packagetype": "bdist_egg", "python_version": "2.6", "requires_python": null, "size": 10892, "upload_time": "2012-05-28T16:51:50", "url": "https://files.pythonhosted.org/packages/5a/c9/6cdeb6a24c017278f220f580a39ca618a3b185ac255b8dd24e6c3f0a3315/wallclock-1.0-py2.6.egg" }, { "comment_text": "", "digests": { "md5": "2248010db058a6e2573d7a3cdd118889", "sha256": "fa88dc8bdc20384e41776c5fcec097e40fafb1dc3fc41899c2488a07a293326e" }, "downloads": -1, "filename": "wallclock-1.0-py2.7.egg", "has_sig": false, "md5_digest": "2248010db058a6e2573d7a3cdd118889", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 10843, "upload_time": "2012-05-28T16:51:38", "url": "https://files.pythonhosted.org/packages/d3/1c/ee52c7fe898fa94eba4ea30cfc78f3957cd31288c671076ba7ef9aef0865/wallclock-1.0-py2.7.egg" }, { "comment_text": "", "digests": { "md5": "07b3186ff53567d6bf8f1f4610e151fa", "sha256": "25a1f3aa8551392c602a19e48bac0c6a719d686e577569ba260121d28b083418" }, "downloads": -1, "filename": "wallclock-1.0.tar.gz", "has_sig": false, "md5_digest": "07b3186ff53567d6bf8f1f4610e151fa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6579, "upload_time": "2012-05-28T16:51:38", "url": "https://files.pythonhosted.org/packages/79/39/402785560101aa5f7f8e3d8cf4144580417df4d720afc899983e17a740ae/wallclock-1.0.tar.gz" } ] }