บางทีสิ่งที่ช้ากว่าคือ futex ซึ่งเป็นส่วนประกอบของตัวแปรเงื่อนไข สิ่งนี้จะทำให้แสงสว่างบางส่วน:
strace -r ./test_latency 0 1 &> test_latency_strace & sleep 8 && killall test_latency
แล้ว
for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done
ซึ่งจะแสดงไมโครวินาทีที่ใช้สำหรับการเรียกระบบที่น่าสนใจโดยเรียงตามเวลา
บนเคอร์เนล 2.6.32
$ for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done
futex
1.000140 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000129 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000124 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000119 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000106 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000103 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000102 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
0.000125 futex(0x7f98ce4c0b88, FUTEX_WAKE_PRIVATE, 2147483647) = 0
0.000042 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
0.000038 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
0.000037 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
0.000030 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
0.000029 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 0
0.000028 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
0.000027 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
0.000018 futex(0x7fff82f0ec3c, FUTEX_WAKE_PRIVATE, 1) = 0
nanosleep
0.000027 nanosleep({1, 0}, {1, 0}) = 0
0.000019 nanosleep({1, 0}, {1, 0}) = 0
0.000019 nanosleep({1, 0}, {1, 0}) = 0
0.000018 nanosleep({1, 0}, {1, 0}) = 0
0.000018 nanosleep({1, 0}, {1, 0}) = 0
0.000018 nanosleep({1, 0}, {1, 0}) = 0
0.000018 nanosleep({1, 0}, 0x7fff82f0eb40) = ? ERESTART_RESTARTBLOCK (To be restarted)
0.000017 nanosleep({1, 0}, {1, 0}) = 0
rt_sig
0.000045 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000040 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000038 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000034 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000033 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000032 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000032 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000028 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000028 rt_sigaction(SIGRT_1, {0x37f8c052b0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x37f8c0e4c0}, NULL, 8) = 0
0.000027 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000027 rt_sigaction(SIGRTMIN, {0x37f8c05370, [], SA_RESTORER|SA_SIGINFO, 0x37f8c0e4c0}, NULL, 8) = 0
0.000027 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000023 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000023 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000022 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
0.000022 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000021 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000021 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000021 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000021 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000021 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000019 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
บนเคอร์เนล 3.1.9
$ for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done
futex
1.000129 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000126 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000122 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000115 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000114 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000112 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
1.000109 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
0.000139 futex(0x3f8b8f2fb0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
0.000043 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
0.000041 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
0.000037 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
0.000036 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
0.000034 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
0.000034 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
nanosleep
0.000025 nanosleep({1, 0}, 0x7fff70091d00) = 0
0.000022 nanosleep({1, 0}, {0, 3925413}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
0.000021 nanosleep({1, 0}, 0x7fff70091d00) = 0
0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
rt_sig
0.000045 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000044 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000043 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000040 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000038 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000037 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000036 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000036 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000035 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000034 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000027 rt_sigaction(SIGRT_1, {0x3f892067b0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x3f8920f500}, NULL, 8) = 0
0.000026 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000026 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000024 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000023 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
0.000023 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
0.000022 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
0.000021 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
0.000019 rt_sigaction(SIGRTMIN, {0x3f89206720, [], SA_RESTORER|SA_SIGINFO, 0x3f8920f500}, NULL, 8) = 0
ฉันพบรายงานข้อบกพร่องอายุ 5 ปีซึ่งมีการทดสอบประสิทธิภาพ "ปิงปอง" ที่เปรียบเทียบ
- เธรดเดียว libpthread mutex
- ตัวแปรเงื่อนไข libpthread
- สัญญาณ Unix เก่าธรรมดา
ฉันต้องเพิ่ม
#include <stdint.h>
เพื่อรวบรวมซึ่งฉันทำกับคำสั่งนี้
g++ -O3 -o condvar-perf condvar-perf.cpp -lpthread -lrt
บนเคอร์เนล 2.6.32
$ ./condvar-perf 1000000
NPTL
mutex elapsed: 29085 us; per iteration: 29 ns / 9.4e-05 context switches.
c.v. ping-pong test elapsed: 4771993 us; per iteration: 4771 ns / 4.03 context switches.
signal ping-pong test elapsed: 8685423 us; per iteration: 8685 ns / 4.05 context switches.
บนเคอร์เนล 3.1.9
$ ./condvar-perf 1000000
NPTL
mutex elapsed: 26811 us; per iteration: 26 ns / 8e-06 context switches.
c.v. ping-pong test elapsed: 10930794 us; per iteration: 10930 ns / 4.01 context switches.
signal ping-pong test elapsed: 10949670 us; per iteration: 10949 ns / 4.01 context switches.
ฉันสรุปได้ว่าระหว่างสวิตช์บริบทเคอร์เนล 2.6.32 และ 3.1.9 ได้ชะลอตัวลงอย่างแน่นอนแม้ว่าจะไม่มากเท่าที่คุณสังเกตในเคอร์เนล 3.2 ฉันรู้ว่าสิ่งนี้ยังไม่ตอบคำถามของคุณฉันจะขุดต่อไป
แก้ไข: ฉันพบว่าการเปลี่ยนลำดับความสำคัญแบบเรียลไทม์ของกระบวนการ (ทั้งสองเธรด) ช่วยเพิ่มประสิทธิภาพใน 3.1.9 ให้ตรงกับ 2.6.32 อย่างไรก็ตามการตั้งค่าลำดับความสำคัญเท่ากันใน 2.6.32 ทำให้ช้าลง ... ไปคิด - ฉันจะพิจารณาให้มากขึ้น
นี่คือผลลัพธ์ของฉันตอนนี้:
บนเคอร์เนล 2.6.32
$ ./condvar-perf 1000000
NPTL
mutex elapsed: 29629 us; per iteration: 29 ns / 0.000418 context switches.
c.v. ping-pong test elapsed: 6225637 us; per iteration: 6225 ns / 4.1 context switches.
signal ping-pong test elapsed: 5602248 us; per iteration: 5602 ns / 4.09 context switches.
$ chrt -f 1 ./condvar-perf 1000000
NPTL
mutex elapsed: 29049 us; per iteration: 29 ns / 0.000407 context switches.
c.v. ping-pong test elapsed: 16131360 us; per iteration: 16131 ns / 4.29 context switches.
signal ping-pong test elapsed: 11817819 us; per iteration: 11817 ns / 4.16 context switches.
$
บนเคอร์เนล 3.1.9
$ ./condvar-perf 1000000
NPTL
mutex elapsed: 26830 us; per iteration: 26 ns / 5.7e-05 context switches.
c.v. ping-pong test elapsed: 12812788 us; per iteration: 12812 ns / 4.01 context switches.
signal ping-pong test elapsed: 13126865 us; per iteration: 13126 ns / 4.01 context switches.
$ chrt -f 1 ./condvar-perf 1000000
NPTL
mutex elapsed: 27025 us; per iteration: 27 ns / 3.7e-05 context switches.
c.v. ping-pong test elapsed: 5099885 us; per iteration: 5099 ns / 4 context switches.
signal ping-pong test elapsed: 5508227 us; per iteration: 5508 ns / 4 context switches.
$
/proc/sys/kernel/*
อาจใช้งานได้? หากคุณพบสิ่งที่ใช้งานได้ให้ใส่การกำหนดค่านั้นใน/etc/sysctl.conf
หรือไฟล์/etc/sysctl.d/
เพื่อให้ยังคงอยู่ในระหว่างการรีบูต