import threading
import time

# Function to simulate CPU-intensive work
def cpu_work(iterations):
    """Performs a calculation to use 100% of a single core for a duration."""
    result = 0
    for i in range(iterations):
        result += i * i 
    return result

ITERATIONS = 40_000_000

print("--- Threading Performance Test ---")
print("Target: Two CPU-bound threads on a multi-core machine.")

# ----------------------------------------------------
# Scenario 1: Python 3.13 (GIL-bound)
# Expected Result: Total wall time is roughly the time for ONE thread, 
# because the GIL prevents them from truly running in parallel on separate cores.
# ----------------------------------------------------

def run_gil_scenario():
    start_time = time.time()
    
    thread1 = threading.Thread(target=cpu_work, args=(ITERATIONS,))
    thread2 = threading.Thread(target=cpu_work, args=(ITERATIONS,))
    
    thread1.start()
    thread2.start()
    
    thread1.join()
    thread2.join()
    
    duration = time.time() - start_time
    print(f"\n[Python 3.13 w/ GIL] Wall Time (Expected ~{duration:.2f}s): These threads shared one core.")
    return duration

# ----------------------------------------------------
# Scenario 2: Python 3.14 (Free-Threaded)
# Expected Result: Total wall time is roughly HALF of the GIL time, 
# because the threads are using two separate cores simultaneously.
# ----------------------------------------------------

def run_free_threaded_scenario():
    # We use the same code, but run it in a free-threaded CPython build.
    start_time = time.time()

    thread1 = threading.Thread(target=cpu_work, args=(ITERATIONS,))
    thread2 = threading.Thread(target=cpu_work, args=(ITERATIONS,))
    
    thread1.start()
    thread2.start()
    
    thread1.join()
    thread2.join()
    
    duration = time.time() - start_time
    # In a true 3.14 free-threaded environment, this value would be ~50% of the 3.13 time.
    print(f"[Python 3.14 Free-Threaded] Wall Time (Expected ~{duration/2:.2f}s): Threads ran in true parallel.")
    return duration

# run_gil_scenario() # Commented out to prevent actual long execution
# run_free_threaded_scenario()
