Android 8.0 มีการทดสอบประสิทธิภาพ Binder และ HwBinder สำหรับปริมาณงานและเวลาแฝง แม้ว่ามีหลายสถานการณ์สำหรับการตรวจจับปัญหาประสิทธิภาพที่รับรู้ได้ แต่การรันสถานการณ์ดังกล่าวอาจใช้เวลานานและมักจะไม่แสดงผลลัพธ์จนกว่าจะรวมระบบแล้ว การใช้การทดสอบประสิทธิภาพที่ให้มาทำให้ง่ายต่อการทดสอบระหว่างการพัฒนา ตรวจพบปัญหาร้ายแรงตั้งแต่เนิ่นๆ และปรับปรุงประสบการณ์ผู้ใช้
การทดสอบประสิทธิภาพประกอบด้วยสี่ประเภทต่อไปนี้:
- ปริมาณงานของ Binder (มีอยู่ใน
system/libhwbinder/vts/performance/Benchmark_binder.cpp
) - Binder latency (มีอยู่ใน
frameworks/native/libs/binder/tests/schd-dbg.cpp
) - ปริมาณงาน hwbinder (มีอยู่ใน
system/libhwbinder/vts/performance/Benchmark.cpp
) - hwbinder latency (มีอยู่ใน
system/libhwbinder/vts/performance/Latency.cpp
)
เกี่ยวกับเครื่องผูกและhwbinder
Binder และ hwbinder เป็นโครงสร้างพื้นฐานการสื่อสารระหว่างกระบวนการ (IPC) ของ Android ที่ใช้ไดรเวอร์ Linux เดียวกัน แต่มีความแตกต่างเชิงคุณภาพดังต่อไปนี้:
ด้าน | เครื่องผูก | วิธีบินเดอร์ |
---|---|---|
วัตถุประสงค์ | จัดให้มีโครงการ IPC สำหรับวัตถุประสงค์ทั่วไปสำหรับกรอบงาน | สื่อสารกับฮาร์ดแวร์ |
คุณสมบัติ | ปรับให้เหมาะสมสำหรับการใช้งานกรอบงาน Android | ค่าใช้จ่ายขั้นต่ำเวลาแฝงต่ำ |
เปลี่ยนนโยบายการกำหนดเวลาสำหรับเบื้องหน้า/เบื้องหลัง | ใช่ | เลขที่ |
ข้อโต้แย้งผ่านไป | ใช้การทำให้เป็นอนุกรมที่รองรับโดยออบเจ็กต์ Parcel | ใช้บัฟเฟอร์กระจายและหลีกเลี่ยงค่าใช้จ่ายในการคัดลอกข้อมูลที่จำเป็นสำหรับการจัดลำดับพัสดุ |
มรดกลำดับความสำคัญ | เลขที่ | ใช่ |
กระบวนการ Binder และ hwbinder
Visualizer systrace จะแสดงธุรกรรมดังต่อไปนี้:
ในตัวอย่างข้างต้น:
- กระบวนการ schd-dbg สี่ (4) กระบวนการเป็นกระบวนการไคลเอนต์
- กระบวนการเครื่องผูกสี่ (4) กระบวนการคือกระบวนการเซิร์ฟเวอร์ (ชื่อขึ้นต้นด้วย Binder และลงท้ายด้วยหมายเลขลำดับ)
- กระบวนการไคลเอนต์จะจับคู่กับกระบวนการเซิร์ฟเวอร์เสมอซึ่งมีไว้สำหรับไคลเอนต์โดยเฉพาะ
- คู่กระบวนการไคลเอ็นต์-เซิร์ฟเวอร์ทั้งหมดได้รับการกำหนดเวลาอย่างเป็นอิสระโดยเคอร์เนลพร้อมกัน
ใน CPU 1 เคอร์เนลระบบปฏิบัติการจะเรียกใช้งานไคลเอ็นต์เพื่อออกคำขอ จากนั้นจะใช้ CPU เดียวกันทุกครั้งที่เป็นไปได้เพื่อปลุกกระบวนการเซิร์ฟเวอร์ จัดการคำขอ และสลับบริบทกลับหลังจากการร้องขอเสร็จสมบูรณ์
ปริมาณงานเทียบกับเวลาแฝง
ในการทำธุรกรรมที่สมบูรณ์แบบ ซึ่งกระบวนการไคลเอ็นต์และเซิร์ฟเวอร์สลับกันได้อย่างราบรื่น การทดสอบปริมาณงานและค่าหน่วงเวลาไม่ได้สร้างข้อความที่แตกต่างกันอย่างมีนัยสำคัญ อย่างไรก็ตาม เมื่อเคอร์เนล OS จัดการคำขอขัดจังหวะ (IRQ) จากฮาร์ดแวร์ รอการล็อค หรือเพียงแค่เลือกที่จะไม่จัดการข้อความในทันที ฟองเวลาแฝงก็อาจเกิดขึ้นได้
การทดสอบปริมาณงานจะสร้างธุรกรรมจำนวนมากที่มีขนาดเพย์โหลดที่แตกต่างกัน โดยให้การประมาณที่ดีสำหรับเวลาการทำธุรกรรมปกติ (ในกรณีที่ดีที่สุด) และปริมาณงานสูงสุดที่ Binder สามารถทำได้
ในทางตรงกันข้าม การทดสอบเวลาแฝงจะไม่ดำเนินการใด ๆ กับเพย์โหลดเพื่อลดเวลาการทำธุรกรรมปกติให้เหลือน้อยที่สุด เราสามารถใช้เวลาในการทำธุรกรรมเพื่อประเมินค่าใช้จ่ายของ Binder สร้างสถิติสำหรับกรณีที่เลวร้ายที่สุด และคำนวณอัตราส่วนของธุรกรรมที่มีค่าหน่วงเวลาตรงตามกำหนดเวลาที่กำหนด
จัดการกับการผกผันลำดับความสำคัญ
การกลับลำดับความสำคัญเกิดขึ้นเมื่อเธรดที่มีลำดับความสำคัญสูงกว่ากำลังรอเธรดที่มีลำดับความสำคัญต่ำกว่าในทางลอจิคัล แอปพลิเคชันแบบเรียลไทม์ (RT) มีปัญหาการกลับลำดับความสำคัญ:
เมื่อใช้การกำหนดเวลา Linux Completely Fair Scheduler (CFS) เธรดจะมีโอกาสรันเสมอแม้ว่าเธรดอื่นจะมีลำดับความสำคัญสูงกว่าก็ตาม ด้วยเหตุนี้ แอปพลิเคชันที่มีการกำหนดเวลา CFS จึงจัดการการกลับลำดับความสำคัญตามลักษณะการทำงานที่คาดไว้ และไม่เป็นปัญหา ในกรณีที่เฟรมเวิร์ก Android ต้องการการกำหนดเวลา RT เพื่อรับประกันสิทธิ์ของเธรดที่มีลำดับความสำคัญสูง การกลับลำดับความสำคัญจะต้องได้รับการแก้ไข
ตัวอย่างการกลับลำดับความสำคัญระหว่างธุรกรรม Binder (เธรด RT ถูกบล็อกทางตรรกะโดยเธรด CFS อื่น ๆ เมื่อรอเธรด Binder เพื่อให้บริการ):
เพื่อหลีกเลี่ยงการอุดตัน คุณสามารถใช้การสืบทอดลำดับความสำคัญเพื่อขยายเธรด Binder เป็นเธรด RT ชั่วคราว เมื่อให้บริการคำขอจากไคลเอนต์ RT โปรดทราบว่าการจัดกำหนดการ RT มีทรัพยากรที่จำกัด และควรใช้อย่างระมัดระวัง ในระบบที่มี n CPU จำนวนสูงสุดของเธรด RT ปัจจุบันก็คือ n เช่นกัน เธรด RT เพิ่มเติมอาจต้องรอ (และทำให้พลาดกำหนดเวลา) หากเธรด RT อื่นใช้ CPU ทั้งหมด
หากต้องการแก้ไขการกลับลำดับความสำคัญที่เป็นไปได้ทั้งหมด คุณสามารถใช้การสืบทอดลำดับความสำคัญสำหรับทั้ง Binder และ hwbinder อย่างไรก็ตาม เนื่องจากมีการใช้ Binder กันอย่างแพร่หลายทั่วทั้งระบบ การเปิดใช้งานการสืบทอดลำดับความสำคัญสำหรับธุรกรรม Binder อาจส่งสแปมระบบด้วยเธรด RT มากกว่าที่จะให้บริการได้
รันการทดสอบปริมาณงาน
การทดสอบปริมาณงานจะรันกับปริมาณงานของธุรกรรม Binder/hwbinder ในระบบที่ไม่มีการโอเวอร์โหลด ฟองเวลาแฝงนั้นเกิดขึ้นได้ยาก และผลกระทบของฟองนั้นสามารถขจัดออกไปได้ตราบใดที่จำนวนการวนซ้ำสูงเพียงพอ
- การทดสอบทรูพุต ของ Binder อยู่ใน
system/libhwbinder/vts/performance/Benchmark_binder.cpp
- การทดสอบปริมาณงาน ของ hwbinder อยู่ใน
system/libhwbinder/vts/performance/Benchmark.cpp
ผลการทดสอบ
ตัวอย่างผลการทดสอบปริมาณงานสำหรับธุรกรรมที่ใช้ขนาดเพย์โหลดที่แตกต่างกัน:
Benchmark Time CPU Iterations --------------------------------------------------------------------- BM_sendVec_binderize/4 70302 ns 32820 ns 21054 BM_sendVec_binderize/8 69974 ns 32700 ns 21296 BM_sendVec_binderize/16 70079 ns 32750 ns 21365 BM_sendVec_binderize/32 69907 ns 32686 ns 21310 BM_sendVec_binderize/64 70338 ns 32810 ns 21398 BM_sendVec_binderize/128 70012 ns 32768 ns 21377 BM_sendVec_binderize/256 69836 ns 32740 ns 21329 BM_sendVec_binderize/512 69986 ns 32830 ns 21296 BM_sendVec_binderize/1024 69714 ns 32757 ns 21319 BM_sendVec_binderize/2k 75002 ns 34520 ns 20305 BM_sendVec_binderize/4k 81955 ns 39116 ns 17895 BM_sendVec_binderize/8k 95316 ns 45710 ns 15350 BM_sendVec_binderize/16k 112751 ns 54417 ns 12679 BM_sendVec_binderize/32k 146642 ns 71339 ns 9901 BM_sendVec_binderize/64k 214796 ns 104665 ns 6495
- เวลาบ่ง บอกถึงความล่าช้าในการเดินทางไปกลับที่วัดแบบเรียลไทม์
- CPU ระบุเวลาสะสมเมื่อมีการกำหนดเวลา CPU สำหรับการทดสอบ
- การวนซ้ำ ระบุจำนวนครั้งที่ฟังก์ชันทดสอบดำเนินการ
ตัวอย่างเช่น สำหรับเพย์โหลด 8 ไบต์:
BM_sendVec_binderize/8 69974 ns 32700 ns 21296
… ปริมาณงานสูงสุดที่เครื่องผูกสามารถทำได้ได้รับการคำนวณดังนี้:
ปริมาณงานสูงสุดพร้อมเพย์โหลด 8 ไบต์ = (8 * 21296)/69974 ~= 2.423 b/ns ~= 2.268 Gb/s
ตัวเลือกการทดสอบ
หากต้องการรับผลลัพธ์ในรูปแบบ .json ให้รันการทดสอบด้วยอาร์กิวเมนต์ --benchmark_format=json
:
libhwbinder_benchmark --benchmark_format=json
{
"context": {
"date": "2017-05-17 08:32:47",
"num_cpus": 4,
"mhz_per_cpu": 19,
"cpu_scaling_enabled": true,
"library_build_type": "release"
},
"benchmarks": [
{
"name": "BM_sendVec_binderize/4",
"iterations": 32342,
"real_time": 47809,
"cpu_time": 21906,
"time_unit": "ns"
},
….
}
เรียกใช้การทดสอบเวลาในการตอบสนอง
การทดสอบเวลาแฝงจะวัดเวลาที่ลูกค้าใช้ในการเริ่มต้นธุรกรรม สลับไปที่กระบวนการของเซิร์ฟเวอร์เพื่อจัดการ และรับผลลัพธ์ การทดสอบยังค้นหาลักษณะการทำงานของตัวกำหนดเวลาที่ไม่ดีซึ่งอาจส่งผลเสียต่อเวลาแฝงของธุรกรรม เช่น ตัวกำหนดเวลาที่ไม่สนับสนุนการสืบทอดลำดับความสำคัญหรือให้เกียรติแฟล็กการซิงค์
- การทดสอบเวลาแฝงของ Binder อยู่ใน
frameworks/native/libs/binder/tests/schd-dbg.cpp
- การทดสอบเวลาแฝงของ hwbinder อยู่ใน
system/libhwbinder/vts/performance/Latency.cpp
ผลการทดสอบ
ผลลัพธ์ (ในสกุล .json) แสดงสถิติสำหรับเวลาแฝงโดยเฉลี่ย/ดีที่สุด/แย่ที่สุด และจำนวนกำหนดเวลาที่พลาดไป
ตัวเลือกการทดสอบ
การทดสอบเวลาในการตอบสนองใช้ตัวเลือกต่อไปนี้:
สั่งการ | คำอธิบาย |
---|---|
-i value | ระบุจำนวนการวนซ้ำ |
-pair value | ระบุจำนวนคู่กระบวนการ |
-deadline_us 2500 | ระบุกำหนดเวลาในเรา |
-v | รับเอาต์พุตแบบละเอียด (การดีบัก) |
-trace | หยุดการติดตามเมื่อถึงกำหนดเวลา |
ส่วนต่อไปนี้ให้รายละเอียดแต่ละตัวเลือก อธิบายการใช้งาน และให้ผลลัพธ์ตัวอย่าง
ระบุการวนซ้ำ
ตัวอย่างที่มีการวนซ้ำจำนวนมากและปิดใช้งานเอาต์พุตแบบละเอียด:
libhwbinder_latency -i 5000 -pair 3
{
"cfg":{"pair":3,"iterations":5000,"deadline_us":2500},
"P0":{"SYNC":"GOOD","S":9352,"I":10000,"R":0.9352,
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996},
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
},
"P1":{"SYNC":"GOOD","S":9334,"I":10000,"R":0.9334,
"other_ms":{ "avg":0.19, "wst":2.9 , "bst":0.055, "miss":2, "meetR":0.9996},
"fifo_ms": { "avg":0.16, "wst":3.1 , "bst":0.066, "miss":1, "meetR":0.9998}
},
"P2":{"SYNC":"GOOD","S":9369,"I":10000,"R":0.9369,
"other_ms":{ "avg":0.19, "wst":4.8 , "bst":0.055, "miss":6, "meetR":0.9988},
"fifo_ms": { "avg":0.15, "wst":1.8 , "bst":0.067, "miss":0, "meetR":1}
},
"inheritance": "PASS"
}
ผลการทดสอบเหล่านี้แสดงสิ่งต่อไปนี้:
-
"pair":3
- สร้างคู่ไคลเอนต์และเซิร์ฟเวอร์หนึ่งคู่
-
"iterations": 5000
- รวมการวนซ้ำ 5,000 ครั้ง
-
"deadline_us":2500
- กำหนดเวลาคือ 2500us (2.5ms); ธุรกรรมส่วนใหญ่คาดว่าจะเป็นไปตามมูลค่านี้
-
"I": 10000
- การทดสอบซ้ำครั้งเดียวประกอบด้วยธุรกรรมสอง (2) รายการ:
- หนึ่งธุรกรรมตามลำดับความสำคัญปกติ (
CFS other
) - หนึ่งธุรกรรมตามลำดับความสำคัญตามเวลาจริง (
RT-fifo
)
- หนึ่งธุรกรรมตามลำดับความสำคัญปกติ (
-
"S": 9352
- ธุรกรรม 9352 ถูกซิงค์ใน CPU เดียวกัน
-
"R": 0.9352
- ระบุอัตราส่วนที่ไคลเอ็นต์และเซิร์ฟเวอร์ซิงค์กันใน CPU เดียวกัน
-
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996}
- กรณีเฉลี่ย (
avg
) แย่ที่สุด (wst
) และดีที่สุด (bst
) สำหรับธุรกรรมทั้งหมดที่ออกโดยผู้โทรที่มีลำดับความสำคัญปกติ ธุรกรรมสองรายการmiss
กำหนดเวลา ทำให้อัตราส่วนตอบสนอง (meetR
) 0.9996 -
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
- คล้ายกับ
other_ms
แต่สำหรับธุรกรรมที่ออกโดยลูกค้าที่มีลำดับความสำคัญrt_fifo
เป็นไปได้ (แต่ไม่จำเป็น) ว่าfifo_ms
จะให้ผลลัพธ์ที่ดีกว่าother_ms
โดยมีค่าavg
และwst
ต่ำกว่า และmeetR
ที่สูงกว่า (ความแตกต่างอาจมีนัยสำคัญยิ่งขึ้นเมื่อโหลดในพื้นหลัง)
หมายเหตุ: การโหลดในเบื้องหลังอาจส่งผลต่อผลลัพธ์การรับส่งข้อมูลและทูเพิล other_ms
ในการทดสอบเวลาแฝง เฉพาะ fifo_ms
เท่านั้นที่อาจแสดงผลลัพธ์ที่คล้ายกันตราบใดที่การโหลดพื้นหลังมีลำดับความสำคัญต่ำกว่า RT-fifo
ระบุค่าคู่
กระบวนการไคลเอ็นต์แต่ละกระบวนการจะจับคู่กับกระบวนการเซิร์ฟเวอร์สำหรับไคลเอ็นต์โดยเฉพาะ และแต่ละคู่อาจได้รับการกำหนดเวลาแยกจากกันกับ CPU ใดๆ อย่างไรก็ตาม การโยกย้าย CPU ไม่ควรเกิดขึ้นระหว่างการทำธุรกรรมตราบใดที่แฟล็ก SYNC นั้นเป็น honor
ตรวจสอบให้แน่ใจว่าระบบไม่โอเวอร์โหลด! แม้ว่าคาดว่าจะมีเวลาแฝงสูงในระบบโอเวอร์โหลด แต่ผลการทดสอบสำหรับระบบโอเวอร์โหลดไม่ได้ให้ข้อมูลที่เป็นประโยชน์ หากต้องการทดสอบระบบที่มีแรงดันสูงกว่า ให้ใช้ -pair #cpu-1
(หรือ -pair #cpu
ด้วยความระมัดระวัง) การทดสอบโดยใช้ -pair n
กับ n > #cpu
ทำให้ระบบโอเวอร์โหลดและสร้างข้อมูลที่ไร้ประโยชน์
ระบุค่ากำหนดเวลา
หลังจากการทดสอบสถานการณ์ของผู้ใช้อย่างกว้างขวาง (ทำการทดสอบเวลาแฝงกับผลิตภัณฑ์ที่ผ่านการรับรอง) เราพบว่า 2.5 มิลลิวินาทีคือกำหนดเวลาที่ต้องปฏิบัติตาม สำหรับแอปพลิเคชันใหม่ที่มีความต้องการสูงกว่า (เช่น 1,000 ภาพ/วินาที) ค่ากำหนดเวลานี้จะเปลี่ยนแปลง
ระบุเอาต์พุตแบบละเอียด
การใช้ตัวเลือก -v
จะแสดงเอาต์พุตแบบละเอียด ตัวอย่าง:
libhwbinder_latency -i 1 -v
-------------------------------------------------- service pid: 8674 tid: 8674 cpu: 1 SCHED_OTHER 0-------------------------------------------------- main pid: 8673 tid: 8673 cpu: 1 -------------------------------------------------- client pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0-------------------------------------------------- fifo-caller pid: 8677 tid: 8678 cpu: 0 SCHED_FIFO 99 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 ??? 99-------------------------------------------------- other-caller pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 SCHED_OTHER 0
- เธรดบริการ ถูกสร้างขึ้นโดยมีลำดับความสำคัญ
SCHED_OTHER
และทำงานในCPU:1
พร้อมด้วยpid 8674
- ธุรกรรมแรก จะเริ่มต้นโดย
fifo-caller
เพื่อให้บริการธุรกรรมนี้ hwbinder จะอัปเกรดลำดับความสำคัญของเซิร์ฟเวอร์ (pid: 8674 tid: 8676
) เป็น 99 และยังทำเครื่องหมายด้วยคลาสการกำหนดเวลาชั่วคราว (พิมพ์เป็น???
) ตัวกำหนดเวลาจะทำให้กระบวนการเซิร์ฟเวอร์อยู่ในCPU:0
เพื่อทำงานและซิงค์กับ CPU เดียวกันกับไคลเอนต์ - ผู้เรียก ธุรกรรมรายที่สอง มีลำดับความสำคัญ
SCHED_OTHER
เซิร์ฟเวอร์จะดาวน์เกรดตัวเองและให้บริการผู้โทรตามลำดับความสำคัญSCHED_OTHER
ใช้การติดตามสำหรับการดีบัก
คุณสามารถระบุตัวเลือก -trace
เพื่อแก้ไขปัญหาเวลาแฝงได้ เมื่อใช้ การทดสอบเวลาแฝงจะหยุดการบันทึกการติดตามในขณะที่ตรวจพบเวลาแฝงที่ไม่ดี ตัวอย่าง:
atrace --async_start -b 8000 -c sched idle workq binder_driver sync freq
libhwbinder_latency -deadline_us 50000 -trace -i 50000 -pair 3
deadline triggered: halt ∓ stop trace log:/sys/kernel/debug/tracing/trace
ส่วนประกอบต่อไปนี้อาจส่งผลต่อเวลาแฝง:
- โหมดการสร้าง Android โหมด Eng มักจะช้ากว่าโหมด userdebug
- กรอบ . บริการกรอบงานใช้
ioctl
เพื่อกำหนดค่าให้กับเครื่องผูกอย่างไร - คนขับรถเครื่องผูก . คนขับรองรับการล็อคแบบละเอียดหรือไม่? มันมีแพตช์การเปลี่ยนประสิทธิภาพทั้งหมดหรือไม่?
- เวอร์ชันเคอร์เนล ยิ่งเคอร์เนลมีความสามารถแบบเรียลไทม์ที่ดีกว่า ผลลัพธ์ก็จะยิ่งดีขึ้นเท่านั้น
- การกำหนดค่าเคอร์เนล การกำหนดค่าเคอร์เนลมีการกำหนดค่า
DEBUG
เช่นDEBUG_PREEMPT
และDEBUG_SPIN_LOCK
หรือไม่ - ตัวกำหนดเวลาเคอร์เนล เคอร์เนลมีตัวกำหนดเวลา Energy-Aware (EAS) หรือ Heterogeneous Multi-Processing (HMP) หรือไม่ ไดรเวอร์เคอร์เนลใด ๆ (ไดรเวอร์
cpu-freq
, ไดรเวอร์cpu-idle
,cpu-hotplug
ฯลฯ ) ส่งผลกระทบต่อตัวกำหนดตารางเวลาหรือไม่