Threads in both

Four jobs that wait

Threads pay off when the work waits: a network response, a disk read, a sleep. Four jobs that each wait 0.2 seconds should finish in about 0.2 seconds when they run at the same time, in either language, because the waiting does not need the interpreter.

Ruby

threads = 4.times.map do Thread.new { sleep 0.2 } end threads.each(&:join) puts "4 threads, 0.2s of sleep each: done"

time ruby threads.rb

4 threads, 0.2s of sleep each: done real 0m0.315s user 0m0.081s sys 0m0.035s

Python

import threading import time def work(): time.sleep(0.2) threads = [threading.Thread(target=work) for _ in range(4)] for thread in threads: thread.start() for thread in threads: thread.join() print("4 threads, 0.2s of sleep each: done")

time python3 threads.py

4 threads, 0.2s of sleep each: done real 0m0.248s user 0m0.040s sys 0m0.010s

Both runs take about a quarter of a second: the four waits overlap. The total wall time is close to one wait, not four, which is the whole point of threads for I/O.

What differs

What to watch for

A thread that raises an exception can end silently unless the program joins it or sets abort_on_exception (Ruby) or reads thread.exc_info (Python). Join every thread you start, in both languages.

Do not reach for threads because they are there. A script that runs four commands one after another is often clearer than a pool, and a pool that writes to one file needs a lock in either language.

Next: The same task, measured

Article author: Arthur Isaev