Commit 85faaafb by John Eskew

Update README. Make thread-safe. Use file-relative path to schema.

parent e4d9750b
Python module which puts timing around Python code blocks. Python module which times Python code blocks.
Features Features
-------- --------
* Nesting of timers - higher level timers continue to tick during lower-level timers starting/stopping. * Nesting of timers - higher level timers continue to tick during lower-level timers starting/stopping.
* Timing storage in a SQLite DB. * Timing storage in a SQLite DB.
Usage
-----
```
from code_block_timer import CodeBlockTimer
for i in xrange(0, 2):
with CodeBlockTimer("all blocks"):
performSetUp()
with CodeBlockTimer("block1"):
perform_lengthy_task()
with CodeBlockTimer("block2"):
perform_another_lengthy_task()
```
In the SQLite DB, you'll now see six rows, similar to these:
```
1|1|all blocks:block1|201.16|2014-10-12 12:26:01
2|1|all blocks:block2|516.492|2014-10-12 12:26:01
3|1|all blocks|916.54|2014-10-12 12:26:01
4|2|all blocks:block1|199.16|2014-10-12 12:26:04
5|2|all blocks:block2|505.142|2014-10-12 12:26:04
6|2|all blocks|903.212|2014-10-12 12:26:04
```
import threading
from timeit import default_timer from timeit import default_timer
from .storage import TimingDataStorage from .storage import TimingDataStorage
class Globals(object): class Globals(threading.local):
pass # Current module-level nest stack.
# As CodeBlockTimer objects are __enter__ed, their descriptions are pushed
# onto this stack. The stack length indicates the current nesting level.
nest_stack = []
_m = Globals() # Current run_id.
# Set from data storage when stack size increases from 0.
# While nest stack is populated, remains at a constant value.
# Identifies all the times from the same run.
run_id = None
# Current module-level nest stack.
# As CodeBlockTimer objects are __enter__ed, their descriptions are pushed
# onto this stack. The stack length indicates the current nesting level.
_m.nest_stack = []
# Current run_id. _m = Globals()
# Set from data storage when stack size increases from 0.
# While nest stack is populated, remains at a constant value.
# Identifies all the times from the same run.
_m.run_id = None
class CodeBlockTimer(object): class CodeBlockTimer(object):
...@@ -28,7 +28,6 @@ class CodeBlockTimer(object): ...@@ -28,7 +28,6 @@ class CodeBlockTimer(object):
self.data_store = TimingDataStorage(**kwargs) self.data_store = TimingDataStorage(**kwargs)
def __enter__(self): def __enter__(self):
global _m
if len(_m.nest_stack) == 0: if len(_m.nest_stack) == 0:
_m.run_id = self.data_store.run_id() _m.run_id = self.data_store.run_id()
_m.nest_stack.append(self.block_desc) _m.nest_stack.append(self.block_desc)
...@@ -36,8 +35,6 @@ class CodeBlockTimer(object): ...@@ -36,8 +35,6 @@ class CodeBlockTimer(object):
return self return self
def __exit__(self, *args): def __exit__(self, *args):
global _m
# Compute elapsed times. # Compute elapsed times.
end = self.timer() end = self.timer()
self.elapsed_secs = end - self.start self.elapsed_secs = end - self.start
......
import sqlite3
import os import os
import sqlite3
from path import path
# Assumes that the DB exists and the schema in schema.sql exists in it. # Assumes that the DB exists and the schema in schema.sql exists in it.
MODULE_DIR = path(__file__).dirname()
class TimingDataStorage(object): class TimingDataStorage(object):
SCHEMA_NAME = 'schema.sql' SCHEMA_NAME = 'schema.sql'
SCHEMA_PATH = MODULE_DIR / self.SCHEMA_NAME
DEFAULT_DB_NAME = 'block_times.db' DEFAULT_DB_NAME = 'block_times.db'
def __init__(self, **kwargs): def __init__(self, **kwargs):
...@@ -23,8 +27,7 @@ class TimingDataStorage(object): ...@@ -23,8 +27,7 @@ class TimingDataStorage(object):
# Create the sqlite DB file. # Create the sqlite DB file.
with open(db_name, "w") as f: with open(db_name, "w") as f:
conn = sqlite3.connect(db_name) conn = sqlite3.connect(db_name)
schema_filepath = os.path.join(os.path.dirname(__file__), self.SCHEMA_NAME) with open(self.SCHEMA_PATH, "r") as schema_file:
with open(schema_filepath, "r") as schema_file:
schema = schema_file.read() schema = schema_file.read()
cur = conn.cursor() cur = conn.cursor()
conn.executescript(schema) conn.executescript(schema)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment