ใช้ ftrace

ftrace เป็นเครื่องมือแก้ไขข้อบกพร่องเพื่อทำความเข้าใจสิ่งที่เกิดขึ้นภายในเคอร์เนล Linux ส่วนต่อไปนี้จะอธิบายฟังก์ชันการทํางานพื้นฐานของ ftrace, การใช้งาน ftrace กับ atrace (ซึ่งบันทึกเหตุการณ์เคอร์เนล) และ ftrace แบบไดนามิก

ดูรายละเอียดเกี่ยวกับฟังก์ชันขั้นสูงของ ftrace ที่ไม่มีใน systrace ได้ที่เอกสารประกอบของ ftrace ที่ <kernel tree>/Documentation/trace/ftrace.txt

บันทึกเหตุการณ์เคอร์เนลด้วย atrace

atrace (frameworks/native/cmds/atrace) ใช้ ftrace เพื่อบันทึกเหตุการณ์เคอร์เนล จากนั้น systrace.py (หรือ run_systrace.py ใน Catapult เวอร์ชันที่ใหม่กว่า) จะใช้ adb เพื่อเรียกใช้ atrace ในอุปกรณ์ โดย atrace จะทําสิ่งต่อไปนี้

  • ตั้งค่าการติดตามในโหมดผู้ใช้โดยการตั้งค่าพร็อพเพอร์ตี้ (debug.atrace.tags.enableflags)
  • เปิดใช้ฟังก์ชันการทำงานของ ftrace ที่ต้องการโดยการเขียนไปยังโหนด sysfs ของ ftrace ที่เหมาะสม อย่างไรก็ตาม เนื่องจาก ftrace รองรับฟีเจอร์เพิ่มเติม คุณจึงอาจตั้งค่าโหนด sysfs บางรายการด้วยตนเองแล้วใช้ atrace

ยกเว้นการติดตามเวลาบูต ให้ใช้ atrace เพื่อตั้งค่าพร็อพเพอร์ตี้เป็นค่าที่เหมาะสม พร็อพเพอร์ตี้นี้เป็นบิตมาสก์และไม่มีวิธีที่ดีในการระบุค่าที่ถูกต้องนอกเหนือจากการดูส่วนหัวที่เหมาะสม (ซึ่งอาจเปลี่ยนแปลงระหว่างรุ่นของ Android)

เปิดใช้เหตุการณ์ ftrace

โหนด sysfs ของ ftrace อยู่ใน /sys/kernel/tracing และเหตุการณ์การติดตามจะแบ่งออกเป็นหมวดหมู่ใน /sys/kernel/tracing/events

หากต้องการเปิดใช้เหตุการณ์ตามหมวดหมู่ ให้ใช้

echo 1 > /sys/kernel/tracing/events/irq/enable

หากต้องการเปิดใช้เหตุการณ์แบบต่อเหตุการณ์ ให้ใช้

echo 1 > /sys/kernel/tracing/events/sched/sched_wakeup/enable

หากเปิดใช้เหตุการณ์เพิ่มเติมโดยการเขียนลงในโหนด sysfs ระบบจะไม่รีเซ็ตเหตุการณ์เหล่านั้นด้วย atrace รูปแบบที่พบบ่อยในการเปิดใช้งานอุปกรณ์ Qualcomm คือเปิดใช้จุดตรวจ kgsl (GPU) และ mdss (การแสดงผลไปป์ไลน์) จากนั้นใช้ atrace หรือ systrace

adb shell "echo 1 > /sys/kernel/tracing/events/mdss/enable"
adb shell "echo 1 > /sys/kernel/tracing/events/kgsl/enable"
./systrace.py sched freq idle am wm gfx view binder_driver irq workq ss sync -t 10 -b 96000 -o full_trace.html

นอกจากนี้ คุณยังใช้ ftrace โดยไม่ต้องใช้ atrace หรือ systrace ได้ด้วย ซึ่งจะมีประโยชน์เมื่อคุณต้องการการติดตามเฉพาะเคอร์เนล (หรือหากคุณได้ใช้เวลาเขียนพร็อพเพอร์ตี้การติดตามในโหมดผู้ใช้ด้วยตนเอง) วิธีเรียกใช้เฉพาะ ftrace

  1. ตั้งค่าขนาดบัฟเฟอร์เป็นค่าที่ใหญ่พอสําหรับการติดตาม
    echo 96000 > /sys/kernel/tracing/buffer_size_kb
    
  2. เปิดใช้การติดตาม
    echo 1 > /sys/kernel/tracing/tracing_on
    
  3. ทำการทดสอบ แล้วปิดใช้การติดตาม
    echo 0 > /sys/kernel/tracing/tracing_on
    
  4. วางข้อมูลเทรซ
    cat /sys/kernel/tracing/trace > /data/local/tmp/trace_output
    

trace_output จะแสดงการติดตามในรูปแบบข้อความ หากต้องการแสดงภาพโดยใช้ Catapult ให้ไปที่ Catapult Repo จาก GitHub แล้วเรียกใช้ trace2html

catapult/tracing/bin/trace2html ~/path/to/trace_file

โดยค่าเริ่มต้น คำสั่งนี้จะเขียน trace_file.html ในไดเรกทอรีเดียวกัน

เชื่อมโยงเหตุการณ์

บางครั้งการดูภาพ Catapult และบันทึก ftrace พร้อมกันจะมีประโยชน์ เช่น Catapult จะไม่แสดงภาพเหตุการณ์ ftrace บางรายการ (โดยเฉพาะเหตุการณ์ที่เฉพาะเจาะจงสำหรับผู้ให้บริการ) อย่างไรก็ตาม การประทับเวลาของ Catapult จะสัมพันธ์กับเหตุการณ์แรกในการติดตามหรือกับการประทับเวลาที่เฉพาะเจาะจงซึ่ง atrace แสดงผล ขณะที่การประทับเวลา ftrace ดิบจะอิงตามแหล่งที่มาของนาฬิกาแบบสัมบูรณ์ที่เฉพาะเจาะจงในเคอร์เนล Linux

วิธีค้นหาเหตุการณ์ ftrace หนึ่งๆ จากเหตุการณ์ Catapult

  1. เปิดบันทึก ftrace ดิบ การติดตามใน systrace เวอร์ชันล่าสุดจะได้รับการบีบอัดโดยค่าเริ่มต้น ดังนี้
    • หากคุณบันทึก Systrace ด้วย --no-compress ข้อมูลนี้จะอยู่ในไฟล์ html ในส่วนที่ขึ้นต้นด้วย BEGIN TRACE
    • หากไม่มี ให้เรียกใช้ html2trace จาก Catapult tree (tracing/bin/html2trace) เพื่อคลายการบีบอัดการติดตาม
  2. ค้นหาการประทับเวลาแบบสัมพัทธ์ในการแสดงภาพ Catapult
  3. ค้นหาบรรทัดตอนต้นของการติดตามที่มี tracing_mark_sync ซึ่งควรมีลักษณะดังนี้
    <5134>-5134  (-----) [003] ...1    68.104349: tracing_mark_write: trace_event_clock_sync: parent_ts=68.104286
    

    หากไม่มีบรรทัดนี้ (หรือหากคุณใช้ ftrace โดยไม่ใช้ atrace) ข้อมูลเวลาจะสัมพันธ์กับเหตุการณ์แรกในบันทึก ftrace
    1. เพิ่มการประทับเวลาแบบสัมพัทธ์ (เป็นมิลลิวินาที) ลงในค่าใน parent_ts (เป็นวินาที)
    2. ค้นหาการประทับเวลาใหม่

ขั้นตอนเหล่านี้ควรนำคุณไปยัง (หรืออย่างน้อยก็ใกล้กับ) เหตุการณ์

ใช้ ftrace แบบไดนามิก

เมื่อ systrace และ ftrace มาตรฐานไม่เพียงพอแล้ว คุณยังมีวิธีสุดท้ายในการแก้ปัญหา ซึ่งก็คือ ftrace แบบไดนามิก Ftrace แบบไดนามิกเกี่ยวข้องกับการเขียนโค้ดเคอร์เนลใหม่หลังจากการบูต ดังนั้นจึงไม่มีให้บริการในเคอร์เนลเวอร์ชันที่ใช้งานจริงเนื่องจากเหตุผลด้านความปลอดภัย อย่างไรก็ตาม ข้อบกพร่องด้านประสิทธิภาพที่แก้ไขได้ยากทุกข้อในปี 2015 และ 2016 ล้วนมีสาเหตุที่แท้จริงซึ่งพบโดยใช้ ftrace แบบไดนามิก ซึ่งมีประสิทธิภาพอย่างยิ่งสำหรับการแก้ไขข้อบกพร่องของโหมดสลีปแบบไม่หยุดชะงัก เนื่องจากคุณจะดูสแต็กเทรซในเคอร์เนลได้ทุกครั้งที่คุณเรียกใช้ฟังก์ชันที่ทริกเกอร์โหมดสลีปแบบไม่หยุดชะงัก นอกจากนี้ คุณยังแก้ไขข้อบกพร่องของส่วนต่างๆ ที่ปิดใช้การขัดจังหวะและการแย่งสิทธิ์ได้ด้วย ซึ่งจะเป็นประโยชน์อย่างยิ่งในการพิสูจน์ปัญหา

หากต้องการเปิดใช้ ftrace แบบไดนามิก ให้แก้ไข defconfig ของเคิร์กัล โดยทำดังนี้

  1. นำ CONFIG_STRICT_MEMORY_RWX ออก (หากมี) แต่จะไม่มีตัวเลือกนี้หากคุณใช้ 3.18 ขึ้นไปและ arm64
  2. เพิ่ม CONFIG_DYNAMIC_FTRACE=y, CONFIG_FUNCTION_TRACER=y, CONFIG_IRQSOFF_TRACER=y, CONFIG_FUNCTION_PROFILER=y และ CONFIG_PREEMPT_TRACER=y
  3. รีบูตและสร้างเคอร์เนลใหม่
  4. เรียกใช้คำสั่งต่อไปนี้เพื่อตรวจสอบว่ามีเครื่องติดตามใดบ้างที่ใช้ได้
    cat /sys/kernel/tracing/available_tracers
    
  5. ยืนยันว่าคําสั่งแสดงผล function, irqsoff, preemptoff และ preemptirqsoff
  6. เรียกใช้คำสั่งต่อไปนี้เพื่อให้แน่ใจว่า ftrace แบบไดนามิกทํางานอยู่
    cat /sys/kernel/tracing/available_filter_functions | grep <a function you care about>
    

หลังจากทำตามขั้นตอนเหล่านี้แล้ว คุณจะมี ftrace แบบไดนามิก เครื่องมือวิเคราะห์ฟังก์ชัน เครื่องมือวิเคราะห์ irqsoff และเครื่องมือวิเคราะห์ preemptoff เราขอแนะนำอย่างยิ่งให้อ่านเอกสารประกอบของ ftrace ในหัวข้อเหล่านี้ก่อนใช้งาน เนื่องจากเครื่องมือเหล่านี้มีประสิทธิภาพแต่ซับซ้อน irqsoff และ preemptoff มีประโยชน์หลักในการยืนยันว่าไดรเวอร์อาจปิดการขัดจังหวะหรือการแย่งสิทธิ์ไว้นานเกินไป

เครื่องมือวิเคราะห์โปรไฟล์ฟังก์ชันเป็นตัวเลือกที่ดีที่สุดสำหรับปัญหาด้านประสิทธิภาพ และมักใช้เพื่อค้นหาตำแหน่งที่มีการเรียกใช้ฟังก์ชัน


หากข้อมูลจากเครื่องมือวิเคราะห์การทำงานของฟังก์ชันไม่เฉพาะเจาะจงพอ คุณก็รวมจุดตรวจ Ftrace เข้ากับเครื่องมือวิเคราะห์การทำงานของฟังก์ชันได้ เหตุการณ์ Ftrace เปิดใช้ได้ในลักษณะเดียวกับปกติทุกประการ และเหตุการณ์ดังกล่าวจะแทรกอยู่ในร่องรอย ซึ่งมีประโยชน์ในกรณีที่มีช่วงพักยาวๆ ที่ขัดจังหวะไม่ได้ในฟังก์ชันที่ต้องการแก้ไขข้อบกพร่องเป็นครั้งคราว ให้ตั้งค่าตัวกรอง ftrace เป็นฟังก์ชันที่ต้องการ เปิดใช้จุดติดตาม และทำการติดตาม คุณสามารถแยกวิเคราะห์การติดตามที่ได้โดยใช้ trace2html ค้นหาเหตุการณ์ที่ต้องการ แล้วดูสแต็กเทรซที่อยู่ใกล้เคียงในการติดตามดิบ

ใช้ lockstat

บางครั้ง ftrace อาจไม่เพียงพอและคุณจำเป็นต้องแก้ไขข้อบกพร่องที่ดูเหมือนว่าจะเป็นการแย่งกันใช้ล็อกเคอร์เนล ตัวเลือกเคอร์เนลอีก 1 รายการที่ควรลองใช้คือ CONFIG_LOCK_STAT วิธีนี้เป็นทางเลือกสุดท้ายเนื่องจากทำให้อุปกรณ์ Android ทำงานได้ยากมาก เนื่องจากจะขยายขนาดเคอร์เนลเกินกว่าที่อุปกรณ์ส่วนใหญ่จะรองรับได้

แต่ lockstat ใช้โครงสร้างพื้นฐานการล็อกสำหรับการแก้ไขข้อบกพร่อง ซึ่งมีประโยชน์สำหรับแอปอื่นๆ อีกมากมาย ทุกคนที่ทำงานเกี่ยวกับการเปิดใช้งานอุปกรณ์ควรหาวิธีทำให้ตัวเลือกดังกล่าวใช้งานได้ในอุปกรณ์ทุกเครื่อง เนื่องจากจะมีบางครั้งที่คุณคิดว่า "หากเปิด LOCK_STAT ได้ ฉันจะยืนยันหรือปฏิเสธได้ว่านี่เป็นปัญหาใน 5 นาทีแทนที่จะใช้เวลา 5 วัน"


หากบูตเคอร์เนลด้วยตัวเลือกการกําหนดค่าได้ การติดตามการล็อกจะคล้ายกับ ftrace ดังนี้

  1. เปิดใช้การติดตาม
    echo 1 > /proc/sys/kernel/lock_stat
    
  2. ทำการทดสอบ
  3. วิธีปิดใช้การติดตาม
    echo 0 > /proc/sys/kernel/lock_stat
    
  4. วางข้อมูลเทรซ
    cat /proc/lock_stat > /data/local/tmp/lock_stat
    

หากต้องการความช่วยเหลือในการตีความเอาต์พุตที่ได้ โปรดดูเอกสารประกอบของ lockstat ที่ <kernel>/Documentation/locking/lockstat.txt

ใช้จุดติดตามของผู้ให้บริการ

ใช้การติดตามเส้นทางจากต้นทางก่อน แต่บางครั้งคุณอาจต้องใช้การติดตามเส้นทางของผู้ให้บริการ

  { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, {
        { OPT,      "events/mdss/enable" },
        { OPT,      "events/sde/enable" },
        { OPT,      "events/mali_systrace/enable" },
    } },

บริการ HAL ขยายจุดติดตามได้ ซึ่งช่วยให้คุณเพิ่มจุดติดตาม/หมวดหมู่เฉพาะอุปกรณ์ได้ จุดติดตามจะผสานรวมกับแอปการติดตามระบบในอุปกรณ์, Perfetto, atrace/systrace

API สําหรับการติดตั้งใช้งานการติดตามจุด/หมวดหมู่มีดังนี้

  • listCategories()generates (vec<TracingCategory> categories);
  • enableCategories(vec<string> categories) generates (Status status);
  • disableAllCategories() จะสร้าง (Status status);
ดูข้อมูลเพิ่มเติมได้ที่คำจำกัดความของ HAL และการใช้งานเริ่มต้นใน AOSP