§Context switch cost

1
2
3
4
5
6
7
8
$ perf bench sched pipe -T
# Running 'sched/pipe' benchmark:
# Executed 1000000 pipe operations between two threads

Total time: 4.271 [sec]

4.271077 usecs/op
234132 ops/sec

Note: Using ubuntu, I have to use sudo to discover that the two threads are running on two different cores. Specifically:

1
$ sudo perf sched record -- perf bench sched pipe -T

However, the generated data file is ~ 1.3G, but I am only interested in sched_switch, so:

1
2
3
4
5
6
7
8
9
10
11
12
$ sudo perf record -e sched:sched_switch
...
$ sudo perf sched script
...
sched-pipe 16768 [000]
sched-pipe 16769 [001]
sched-pipe 16768 [000]
sched-pipe 16769 [001]
sched-pipe 16768 [000]
sched-pipe 16769 [001]
...

It’s clearly shown that those two threads are not scheduled on the same core.

1
2
3
4
5
6
7
8
$ taskset -c 0 perf bench sched pipe -T
# Running 'sched/pipe' benchmark:
# Executed 1000000 pipe operations between two threads

Total time: 2.494 [sec]

2.494871 usecs/op
400822 ops/sec

With thread pinning, the estimated upper bound (since this cost includes calling read/write for-loop, etc) of context switch cost on my box is ~ 1.2 microseconds.

§Scheduling latency

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-module(latency).
-mode(compile).

-compile(export_all).

busy(I) -> busy(I+1).

wait(1) -> ok;
wait(N) ->
Time = round(rand:uniform() * 1000),
Start = erlang:monotonic_time(),
timer:sleep(Time),
Diff = erlang:monotonic_time() - Start,
Jitter = erlang:convert_time_unit(Diff, native, microsecond) - Time * 1000,
io:format("~p~n", [Jitter]),
wait(N-1).

main(_) ->
[spawn(?MODULE, busy, [E]) || E <- lists:seq(0,3)],
wait(1000),
halt().

On my box, the jitter is mostly under 5ms.