การใช้ 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 ที่ต้องการโดยการเขียนไปยังโหนด ftrace sysfs ที่เหมาะสม อย่างไรก็ตาม เนื่องจาก ftrace รองรับคุณสมบัติเพิ่มเติม คุณอาจตั้งค่าโหนด sysfs บางส่วนด้วยตัวเอง จากนั้นใช้ atrace

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

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

โหนด ftrace sysfs อยู่ใน /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 จาก GitHub และเรียกใช้ trace2html:

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

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

เหตุการณ์ที่สัมพันธ์กัน

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

วิธีค้นหาเหตุการณ์ ftrace ที่กำหนดจากเหตุการณ์ Catapult:

  1. เปิดบันทึก ftrace ดิบ การติดตามใน systrace เวอร์ชันล่าสุดจะถูกบีบอัดตามค่าเริ่มต้น:
    • หากคุณบันทึก systrace ด้วย --no-compress สิ่งนี้จะอยู่ในไฟล์ html ในส่วนที่ขึ้นต้นด้วย BEGIN TRACE
    • ถ้าไม่เช่นนั้น ให้รัน html2trace จาก แผนผัง Catapult ( tracing/bin/html2trace ) เพื่อยกเลิกการบีบอัดการติดตาม
  2. ค้นหาการประทับเวลาแบบสัมพันธ์ในการแสดงภาพหนังสติ๊ก
  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 มาตรฐานไม่เพียงพอ จะมีวิธีแก้ไขครั้งสุดท้าย: dynamic ftrace Dynamic ftrace เกี่ยวข้องกับการเขียนโค้ดเคอร์เนลใหม่หลังการบูต และด้วยเหตุนี้จึงไม่สามารถใช้งานได้ในเคอร์เนลที่ใช้งานจริงเนื่องจากเหตุผลด้านความปลอดภัย อย่างไรก็ตาม ข้อบกพร่องด้านประสิทธิภาพที่ยากลำบากทั้งหมดในปี 2558 และ 2559 ท้ายที่สุดแล้วมีสาเหตุมาจากการใช้ Dynamic 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 และตัวสร้างโปรไฟล์แบบรับล่วงหน้าพร้อมใช้งาน เรา ขอแนะนำอย่างยิ่ง ให้อ่านเอกสาร ftrace ในหัวข้อเหล่านี้ก่อนใช้งานเนื่องจากมีประสิทธิภาพแต่ซับซ้อน irqsoff และ preemptoff มีประโยชน์เป็นหลักในการยืนยันว่าไดรเวอร์อาจออกจากการขัดจังหวะหรือปิดการขอล่วงหน้านานเกินไป

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


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

การใช้ล็อคสแตท

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

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


หากคุณสามารถบูตเคอร์เนลด้วยตัวเลือกการกำหนดค่าได้ การติดตามการล็อกจะคล้ายกับ 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 ทำให้คุณสามารถเพิ่มจุดติดตาม/หมวดหมู่เฉพาะของอุปกรณ์ได้ Tracepoints ถูกรวมเข้ากับแอปการติดตามระบบ perfetto, atrace/systrace และบนอุปกรณ์

API สำหรับการนำจุดติดตาม/หมวดหมู่ไปใช้ ได้แก่:

  • listCategories() สร้าง (vec<TracingCategory> หมวดหมู่);
  • EnableCategories(vec<string> categories) สร้าง (สถานะสถานะ);
  • DisableAllCategories() สร้าง (สถานะสถานะ);
สำหรับข้อมูลเพิ่มเติม โปรดดูคำจำกัดความของ HAL และการใช้งานเริ่มต้นใน AOSP :