How to use timing

timing provides simple and powerful timing utilities for measuring execution time, collecting statistics, and analyzing performance.

Statistical timer that collects timing measurements and provides comprehensive statistics (mean, median, stdev, percentiles). Has more statistics that timeit.

Decorator for timing function executions with automatic statistics collection.

Context manager for timing code blocks with automatic start/stop.

With timethis and TimeThis you have 100% coverage. Anything and everything can be timed with one line of code.

Includes:

Importing

from suitkaise import timing
from suitkaise.timing import Sktimer, TimeThis, timethis, time, sleep, elapsed, clear_global_timers

Simple Functions

time()

Get the current Unix timestamp.

from suitkaise import timing

start_time = timing.time()

Wraps time.time() so that you don't have to import both timing and time.

Returns

float: Current Unix timestamp.

sleep()

Sleep the current thread for a given number of seconds.

from suitkaise import timing

# sleep for 2 seconds
timing.sleep(2)

# returns current time after sleeping
end_time = timing.sleep(2)

Arguments

seconds: Number of seconds to sleep.

Returns

float: Current time after sleeping.

Async Support

Use .asynced() for async contexts.

# in an async function
end_time = await timing.sleep.asynced()(2)

Uses asyncio.sleep internally.

elapsed()

Get the elapsed time between two timestamps.

from suitkaise import timing

start_time = timing.time()
timing.sleep(2)
end_time = timing.time()

# with two times
elapsed = timing.elapsed(start_time, end_time)  # 2.0

# with one time (uses current time as end)
elapsed = timing.elapsed(start_time)

Arguments

time1: First timestamp.

time2: Second timestamp.

Returns

float: Absolute elapsed time in seconds.

Note: Order doesn't matter - always returns positive elapsed time.

Sktimer

timethis Decorator

Decorator that times function executions and records results in a Sktimer.

from suitkaise import timing

@timing.timethis()
def quick_function():
    # ...
    pass

quick_function()

# access the auto-created timer
print(f"Last time: {quick_function.timer.most_recent:.3f}s")

# calling multiple times builds statistics
for i in range(100):
    quick_function()

print(f"Mean: {quick_function.timer.mean:.3f}s")

Arguments

timer: Sktimer to accumulate timing data in.

threshold: Minimum elapsed time to record.

max_times: Keep only the most recent N measurements.

Auto-Created Timers

When no timer is provided, the decorator creates a global timer with a naming convention:

The timer is attached to the function as .timer:

@timing.timethis()
def my_function():
    pass

my_function()
print(my_function.timer.mean)

Shared Timer

Use a single timer across multiple functions:

perf_timer = timing.Sktimer()
perf_timer.set_max_times(1000)

@timing.timethis(perf_timer)
def multiply(a, b):
    return a * b

@timing.timethis(perf_timer)
def divide(a, b):
    return a / b

for a, b in zip(range(1000), range(1, 1001)):
    multiply(a, b)
    divide(a, b)

print(f"Combined mean: {perf_timer.mean:.6f}s")

Stacked Decorators

Use both a shared timer and a function-specific timer:

perf_timer = timing.Sktimer()
overall_timer = timing.Sktimer()

# 2 stacked decorators on the same function
@timing.timethis(perf_timer)
@timing.timethis()
def multiply(a, b):
    return a * b

# supports infinite stacking
@timing.timethis(overall_timer)
@timing.timethis(perf_timer)
@timing.timethis()
def divide(a, b):
    return a / b

# ... call functions ...

# combined stats
print(f"Combined mean: {perf_timer.mean:.6f}s")

# individual stats
print(f"Multiply mean: {multiply.timer.mean:.6f}s")
print(f"Divide mean: {divide.timer.mean:.6f}s")

TimeThis Context Manager

Context manager for timing code blocks with automatic timer management.

from suitkaise import timing

with timing.TimeThis() as timer:
    do_work()

print(f"Time taken: {timer.most_recent:.3f}s")

Constructor

Arguments

timer: Sktimer instance to use.

threshold: Minimum elapsed time to record.

One-Use Timer

For quick, one-off measurements:

with timing.TimeThis() as timer:
    compress_file_with_gzip("data.csv")

print(f"Compression took: {timer.most_recent:.3f}s")

Shared Timer

For accumulating statistics across multiple runs:

api_timer = timing.Sktimer()

with timing.TimeThis(api_timer):
    response = requests.get("https://api.example.com/users")

with timing.TimeThis(api_timer):
    response = requests.get("https://api.example.com/posts")

print(f"Average API time: {api_timer.mean:.3f}s")

Pause and Resume

with timing.TimeThis() as timer:
    results = database.query("SELECT * FROM users")
    
    timer.pause()
    user_wants_export = input("Export to CSV? (y/n): ")
    timer.resume()
    
    if user_wants_export.lower() == 'y':
        export_to_csv(results)

print(f"Database operation took: {timer.most_recent:.3f}s (excluding user input)")

Methods

pause(): Pause timing.

resume(): Resume timing.

lap(): Record a lap and continue timing.

clear_global_timers()

Clear all auto-created global timers used by the @timethis() decorator.

from suitkaise import timing

# ... many @timethis() decorated functions called ...

# clear data from auto-created timers to save resources
timing.clear_global_timers()

Useful for:

Thread Safety

All Sktimer operations are thread-safe.

import threading

timer = timing.Sktimer()

def worker():
    for _ in range(100):
        timer.start()
        do_work()
        timer.stop()

threads = [threading.Thread(target=worker) for _ in range(4)]
for t in threads:
    t.start()
for t in threads:
    t.join()

# 400 total measurements across all threads (4 threads * 100 iterations)
print(f"Total measurements: {timer.num_times}")
print(f"Mean: {timer.mean:.3f}s")