sched-ext / scx

sched_ext schedulers and tools
https://bit.ly/scx_slack
GNU General Public License v2.0
692 stars 48 forks source link

Too few runtime for I/O intensive user space program #324

Closed vax-r closed 3 weeks ago

vax-r commented 1 month ago

Description

I tried to use the following code snippet to generate a mixture workload of I/O-bound load and CPU-bound load , aiming to cause CPU load unbalance which can trigger task migration to happen.

import threading
import os
import time

def io_bound_task(file_path, size_mb):
    with open(file_path, 'wb') as f:
        f.write(os.urandom(size_mb * 1024 * 1024))

    with open(file_path, 'rb') as f:
        data = f.read()

    os.remove(file_path)

def generate_io_load(num_threads, size_mb):
    threads = []
    for i in range(num_threads):
        file_path = f'test_file_{i}.dat'
        t = threading.Thread(target=io_bound_task, args=(file_path, size_mb))
        t.start()
        threads.append(t)

    for t in threads:
        t.join()

def cpu_bound_task(duration):
    end_time = time.time() + duration
    while time.time() < end_time:
        result = 0
        for i in range(10000):
            result += i ** 2

def generate_cpu_load(num_threads, duration):
    threads = []
    for i in range(num_threads):
        t = threading.Thread(target=cpu_bound_task, args=(duration,))
        t.start()
        threads.append(t)

    for t in threads:
        t.join()

if __name__ == "__main__":
    io_threads = threading.Thread(target=generate_io_load, args=(1200, 100))
    cpu_threads = threading.Thread(target=generate_cpu_load, args=(12, 300))

    io_threads.start()
    cpu_threads.start()

    io_threads.join()
    cpu_threads.join()

After executing the code snippet, I use the following command to monitor the scheduling bahavior or EEVDF scheduler and scx_rusty.

$ sudo perf sched record -ag sleep 30
$ sudo perf sched latency > eevdf.txt
// switch to scx_rusty
$ sudo perf sched record -ag sleep 30
$ sudo perf sched latency > scx_rusty.txt

The result are in the attached files below, what is weird is that the python program gets 58276.834 ms under EEVDF scheduler but only 0.000 ms in scx_rusty ( the code executed fine under scx_rusty ), while the switches times seems to be reasonable for both scheduler.

The weird behavior doesn't only appear in scx_rusty but nearly all scheduler under scx , including scx_simple , scx_rustland and so on. The python program all progress normally under each scheduler but perf sched shows 0 ms runtime for each of them.

Is it the issue of scx or the I should add more options when using perf sched ?

Expected behavior

the python program should get more than 0.000 ms runtime under scx_rusty