ZetCode

Python time.thread_time Function

Last modified April 11, 2025

This comprehensive guide explores Python's time.thread_time function, which returns the current thread's CPU time. We'll cover thread-specific timing, performance measurement, and practical examples.

Basic Definitions

The time.thread_time function returns the current thread's CPU time as a float in seconds. It measures time spent executing in the current thread.

Key characteristics: thread-specific CPU time, excludes sleep time, useful for profiling. The reference point is undefined, so only differences are meaningful.

Basic Thread Time Measurement

This example shows basic usage of thread_time to measure CPU time consumed by the current thread during a computation.

basic_thread_time.py
import time

def compute():
    sum(range(10**6))  # CPU-intensive work

start = time.thread_time()
compute()
end = time.thread_time()

print(f"CPU time used: {end - start:.6f} seconds")

This measures only the CPU time spent in the current thread. Sleep time or other threads' work won't affect the measurement.

The precision depends on the platform but is typically nanosecond-level. Only time differences should be compared.

Comparing Thread Time vs Process Time

This example compares thread_time with process_time to show thread-specific vs process-wide CPU time measurement.

thread_vs_process.py
import time
import threading

def worker():
    start_thread = time.thread_time()
    start_process = time.process_time()
    
    sum(range(10**7))  # CPU work
    
    end_thread = time.thread_time()
    end_process = time.process_time()
    
    print(f"Thread CPU: {end_thread - start_thread:.3f}s")
    print(f"Process CPU: {end_process - start_process:.3f}s")

# Create and start two threads
t1 = threading.Thread(target=worker)
t2 = threading.Thread(target=worker)
t1.start()
t2.start()
t1.join()
t2.join()

thread_time measures only the calling thread's CPU time, while process_time includes all threads in the process.

This distinction is crucial when profiling multi-threaded applications.

Measuring I/O vs CPU Bound Operations

This example demonstrates how thread_time distinguishes between CPU-bound and I/O-bound operations in a thread.

io_vs_cpu.py
import time

def mixed_work():
    # CPU-bound work
    start_cpu = time.thread_time()
    sum(range(10**6))
    end_cpu = time.thread_time()
    
    # I/O-bound work (sleep simulates waiting)
    start_io = time.thread_time()
    time.sleep(1)
    end_io = time.thread_time()
    
    print(f"CPU work time: {end_cpu - start_cpu:.6f}s")
    print(f"I/O wait time: {end_io - start_io:.6f}s")

mixed_work()

Sleep time doesn't count toward thread CPU time, showing how thread_time only measures actual CPU usage.

This helps identify whether a thread is CPU-bound or waiting on I/O operations.

Profiling Function Execution

This example creates a decorator that profiles functions using thread_time to measure their CPU consumption.

profiler.py
import time

def profile(func):
    def wrapper(*args, **kwargs):
        start = time.thread_time()
        result = func(*args, **kwargs)
        end = time.thread_time()
        print(f"{func.__name__} used {end - start:.6f}s CPU time")
        return result
    return wrapper

@profile
def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n - 1)

@profile
def sleep_and_compute():
    time.sleep(0.5)
    sum(range(10**6))

factorial(10)
sleep_and_compute()

The decorator measures only the CPU time used by the function, excluding any time spent waiting or in other threads.

This is particularly useful for identifying CPU-intensive functions in multi-threaded applications.

Comparing Thread Performance

This example uses thread_time to compare the CPU consumption of different thread implementations of the same task.

thread_comparison.py
import time
import threading

def worker_optimized():
    start = time.thread_time()
    # Efficient computation
    sum(i*i for i in range(10**6))
    end = time.thread_time()
    print(f"Optimized: {end - start:.6f}s")

def worker_unoptimized():
    start = time.thread_time()
    # Less efficient computation
    total = 0
    for i in range(10**6):
        total += i*i
    end = time.thread_time()
    print(f"Unoptimized: {end - start:.6f}s")

t1 = threading.Thread(target=worker_optimized)
t2 = threading.Thread(target=worker_unoptimized)
t1.start()
t2.start()
t1.join()
t2.join()

By measuring each thread's CPU time separately, we can compare the efficiency of different implementations running concurrently.

This approach helps identify performance optimizations in multi-threaded code.

Monitoring Thread CPU Usage Over Time

This example shows how to monitor a thread's CPU usage over time using thread_time with periodic sampling.

monitoring.py
import time
import threading

def worker():
    last_time = time.thread_time()
    for i in range(5):
        # Do some work
        sum(range(10**6))
        
        current_time = time.thread_time()
        cpu_used = current_time - last_time
        print(f"Interval {i}: {cpu_used:.3f}s CPU time")
        last_time = current_time
        
        # Simulate mixed workload
        time.sleep(0.2)

thread = threading.Thread(target=worker)
thread.start()
thread.join()

By taking periodic measurements, we can track how CPU usage varies during a thread's execution.

This technique is useful for identifying phases of high CPU usage in long-running threads.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.