← All reports

Python Report — HW3 Language Comparison

Language / runtime version

CPython 3.14.4 (confirmed via python3 --version inside WSL2 Ubuntu 26.04 "Resolute Raccoon"). No compilation step, no optimization flags — plain python3 quicksort.py invocation. No third-party packages used, standard library only (random, time, csv, os, sys).

Machine: AMD Ryzen 7 5800H (8 cores / 16 threads, ~3.2 GHz base), 32 GB RAM, Windows 11 Pro host, benchmark executed inside WSL2 Ubuntu.

Random pivot / RNG

Randomized pivot selection follows CLRS RANDOMIZED-PARTITION: at every partition call on subarray a[lo..hi], a pivot index is drawn uniformly at random from [lo, hi] via random.randint(lo, hi) (Python's random module, Mersenne Twister-based PRNG, seeded automatically from OS entropy at interpreter start — no explicit seed was set). That element is swapped into position hi, and a standard Lomuto partition then runs around it. The same random module (random.randrange(0, 1_000_000)) is used to generate the input arrays for each iteration; data generation is not timed.

External code used

No external code used — original implementation based on CLRS RANDOMIZED-QUICKSORT/RANDOMIZED-PARTITION pseudocode (Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms, Ch. 5).

Results

Run via:

wsl.exe -d Ubuntu -- bash -c "cd '/mnt/c/Users/granite/Documents/DSU/Algorithms 482/3/HW3/python' && python3 quicksort.py"

Loop stopped after 12 iterations because the measured time for n=2,048,000 (4.997s) exceeded the 4.0s cutoff (well before the 25-iteration or 200,000,000-element caps were reached — as anticipated in the assignment, Python's interpreter overhead means it stops far short of the memory-safety cap). Full results (also in ../results/python.csv):

n time_seconds
1,000 0.000795
2,000 0.001715
4,000 0.003579
8,000 0.008061
16,000 0.017060
32,000 0.033987
64,000 0.076598
128,000 0.172966
256,000 0.443615
512,000 1.083513
1,024,000 2.516872
2,048,000 4.996636

Total wall-clock time for the whole run (including Python interpreter start-up and all 12 data-generation + sort iterations): ~10.5s (real from time python3 quicksort.py).

Growth analysis

For expected O(n log n) behavior, doubling n should multiply the running time by roughly 2 * (log2(2n) / log2(n)), which shrinks slowly from about 2.2x (near n=1,000, where log2(n)≈10) toward 2.0x as n grows into the millions (log2(n)≈21 at n≈2,048,000). The observed per-doubling ratios in this run range from about 1.99x to 2.57x, centered close to the theoretical band, with the last doubling (1,024,000 → 2,048,000) coming in at 1.99x — almost exactly the asymptotic 2x floor — and a few middling doublings (256,000 → 512,000 at 2.44x; 512,000 → 1,024,000 at 2.32x) running slightly above the pure-asymptotic prediction. This is consistent with expected O(n log n) growth for randomized quicksort; the modest excess in the mid-range doublings is plausible timing noise from CPython's per-call interpreter overhead (attribute lookups, bytecode dispatch, and list indexing inside the recursive randomized_quicksort/randomized_partition calls dominate the constant factor far more than in a compiled language, which flattens some of the log-factor curvature at smaller n) and possibly minor GC/memory-allocator effects as the list size crosses cache boundaries. No anomalies such as RecursionError occurred — recursion depth for randomized quicksort stays at O(log n) in expectation (≈21 for the largest n reached here), far under Python's default recursion limit, so sys.setrecursionlimit was never needed.