1 คะแนน โดย GN⁺ 2024-07-22 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • rr ช่วยให้บันทึกการรันที่ล้มเหลวบน Linux ไว้หนึ่งครั้ง แล้วเล่นซ้ำการรันเดิมด้วย gdb ได้ ทำให้ติดตามบั๊ก C/C++ ที่ทำซ้ำได้ยากได้ง่ายขึ้น
  • ระหว่างการเล่นซ้ำ พื้นที่แอดเดรส, รีจิสเตอร์, ข้อมูล system call และการจัดวางหน่วยความจำจะเหมือนเดิมทุกครั้ง ทำให้ เบาะแสสำหรับการดีบัก เช่น แอดเดรสของอ็อบเจ็กต์หรือลำดับเหตุการณ์ไม่หายไป
  • รองรับคำสั่ง gdb ทั่วไป, scripting, การผสานกับ IDE และผสาน hardware data watchpoint กับ การรันย้อนกลับ เพื่อย้อนกลับไปยังจุดที่ค่าถูกเปลี่ยนได้
  • รองรับ Firefox, Chrome, QEMU, LibreOffice, โปรแกรม Go, workload แบบหลายโปรเซส ไปจนถึงคอนเทนเนอร์ แต่มีข้อจำกัดด้านการจำลองคอร์เดียว, shared memory และขอบเขตการรองรับ CPU/system call
  • มีประโยชน์ในการลดต้นทุนการแก้บั๊กและยกระดับคุณภาพซอฟต์แวร์ เพราะสามารถบันทึกความล้มเหลวที่เกิดเป็นครั้งคราว หรือความล้มเหลวจาก fuzzer/การฉีดความขัดข้องแบบสุ่ม แล้วนำมาวิเคราะห์ซ้ำได้

โมเดลการดีบักของ rr

  • rr เป็นเครื่องมือดีบัก C/C++ สำหรับ Linux ที่ไม่ได้มาแทน gdb แต่เสริม workflow ของ gdb ด้วยความสามารถบันทึกและเล่นซ้ำ
  • เมื่อบันทึกการรันที่เกิดความล้มเหลวไว้หนึ่งครั้ง จากนั้นสามารถดีบักการรันเดิมซ้ำได้มากเท่าที่ต้องการ
  • การเล่นซ้ำจะไม่เปลี่ยนไปแบบไม่กำหนดแน่นอนเหมือนการรันสด แต่จะดำเนินไปด้วยสถานะเดียวกันทุกครั้ง
  • ให้ การรันย้อนกลับ ที่มีประสิทธิภาพภายใต้ gdb
    • สามารถตั้ง breakpoint และ data watchpoint ได้
    • สามารถ reverse-execute ไปยังจุดที่สนใจได้อย่างรวดเร็ว
  • ถูกใช้กับแอปพลิเคชันจริง และนักพัฒนาหลายคนกำลังใช้แก้บั๊กจริงอยู่

ฟีเจอร์ที่รองรับและขอบเขตการใช้งาน

  • ฟีเจอร์ของ rr ถูกออกแบบให้เข้ากับแอปพลิเคชันใช้งานจริงและ workflow ที่อิง gdb
    • overhead ต่ำกว่าเครื่องมือคล้ายกัน โดยเฉพาะใน workload ที่ส่วนใหญ่เป็น single-threaded
    • รองรับการบันทึกและเล่นซ้ำแอปพลิเคชันหลากหลาย เช่น Firefox, Chrome, QEMU, LibreOffice และโปรแกรม Go
    • รองรับการบันทึก·เล่นซ้ำ·ดีบัก workload แบบหลายโปรเซส รวมถึงทั้งคอนเทนเนอร์
    • รองรับ gdb scripting และ การผสานกับ IDE
    • รองรับ trace ที่ทนทาน บีบอัดแล้ว และย้ายข้ามเครื่องได้
    • มี Chaos mode ที่ช่วยเผยบั๊กที่เกิดเป็นครั้งคราวได้ดีขึ้น

ขั้นตอนการบันทึกและเล่นซ้ำ

  • บันทึกแอปพลิเคชันด้วย rr record /your/application --args
  • การรันทั้งหมดรวมถึงความล้มเหลวจะถูกเก็บลงดิสก์ และภายหลังสามารถดีบักได้ด้วย rr replay
  • ระหว่างการเล่นซ้ำ จะดีบัก trace ที่บันทึกไว้ ไม่ใช่การรันสด
  • พื้นที่แอดเดรส, เนื้อหารีจิสเตอร์ และข้อมูล system call จะคงเหมือนเดิมในการเล่นซ้ำทุกครั้ง
  • สามารถใช้คำสั่ง gdb ทั่วไปส่วนใหญ่ได้ตามเดิม
  • เมื่อต้องเริ่มเซสชันดีบักใหม่ ให้ใช้คำสั่ง run ของ gdb เพื่อเล่นซ้ำบันทึกตั้งแต่ต้น
    • หลังรีสตาร์ต การรันเดิมก็จะถูกเล่นซ้ำอีกครั้ง
    • สถานะการดีบักจะถูกคงไว้ระหว่างการรีสตาร์ต
  • ตัวชี้ this ของอ็อบเจ็กต์ที่จัดสรรแบบไดนามิกก็เหมือนกันในทุกเซสชันเล่นซ้ำ
    • เพราะการจัดสรรหน่วยความจำเหมือนเดิมทุกครั้ง จึงสามารถ hardcode แอดเดรสที่จะเฝ้าดูได้

การรันย้อนกลับและ watchpoint

  • rr ทำให้สามารถดีบักแบบ ไล่ย้อนจากผลลัพธ์ไปหาสาเหตุ เมื่อค้นหาต้นเหตุที่ค่าถูกตั้งผิด
  • ในตัวอย่างการดีบัก layout ของ Firefox หลังพบว่าค่า mRect.width ผิด จะใช้ watch -l mRect.width และ reverse-cont
  • ผสาน hardware watchpoint กับ reverse execution เพื่อหาจุดที่ค่าเปลี่ยนจาก 11220 เป็น 12000
  • วิธีนี้ช่วยลดงานในการย้อนกลับจากจุดที่ปัญหาแสดงออกไปยังจุดที่เกิดการเปลี่ยนแปลงจริง

การติดตั้งและเริ่มใช้งาน

  • หากต้องการ build จากซอร์ส ให้ทำตามคำแนะนำ Building And Installing
  • เมื่อแพ็กเกจไม่ตรงกับระบบ แนะนำให้ build จากซอร์ส
    • บางครั้งการเปลี่ยนแปลง kernel หรือการอัปเดต OS อาจทำให้ต้องมีการเปลี่ยนแปลง rr
  • ตัวอย่างการติดตั้งบน Fedora คือดาวน์โหลด rr-5.9.0-Linux-$(uname -m).rpm แล้วติดตั้งด้วย sudo dnf install
  • ตัวอย่างการติดตั้งบน Ubuntu คือดาวน์โหลด rr-5.9.0-Linux-$(uname -m).deb แล้วติดตั้งด้วย sudo dpkg -i

วิธีรับมือกับความล้มเหลวที่เกิดเป็นครั้งคราว

  • แรงจูงใจเดิมของ rr คือทำให้การดีบัก ความล้มเหลวที่เกิดเป็นครั้งคราว ง่ายขึ้น
    • ความล้มเหลวที่เกิดเป็นครั้งคราวดีบักได้ยาก เพราะบางการรันไม่แสดงความล้มเหลว
    • สามารถบันทึกการรันทดสอบด้วย overhead ต่ำ และเมื่อเกิดความล้มเหลว ก็เล่นซ้ำการรันนั้นในดีบักเกอร์ได้ซ้ำๆ
  • การเล่นซ้ำแบบ deterministic ช่วยให้สะสมเบาะแสต่อเนื่องได้แม้ในการดีบักบั๊กทั่วไป
    • ในดีบักเกอร์ทั่วไป เมื่อรันใหม่ แอดเดรสของอ็อบเจ็กต์ที่สนใจหรือลำดับเหตุการณ์สำคัญอาจเปลี่ยน ทำให้ข้อมูลก่อนหน้าไร้ประโยชน์
    • ใน rr ความรู้เกี่ยวกับการรันที่ล้มเหลวจะยังคงอยู่แม้เล่นซ้ำหลายครั้ง
  • การดีบักโดยทั่วไปเป็นกระบวนการไล่ย้อนจากผลลัพธ์ไปหาสาเหตุ ดังนั้นหากรันย้อนเวลาได้ การตามหาสาเหตุก็ง่ายขึ้น
  • rr ให้ระบบบันทึก·เล่นซ้ำที่ overhead ต่ำ และเป็น backend ที่ใช้งานได้จริงสำหรับคำสั่ง reverse execution ของ gdb
  • เป็นเครื่องมือที่ใช้งานได้จริง ซึ่งนักพัฒนาในโปรเจ็กต์ใหญ่น้อยจำนวนมากใช้อย่างสม่ำเสมอ

สถานะที่การเล่นซ้ำแบบ deterministic รับประกัน

  • rr บันทึกกลุ่มโปรเซส user space ของ Linux
  • จับอินพุตทั้งหมดที่โปรเซสเป้าหมายได้รับจาก kernel และผลของ CPU ที่ไม่กำหนดแน่นอน
  • การเล่นซ้ำรับประกันการคงไว้ของ control flow ระดับคำสั่ง, หน่วยความจำ และเนื้อหารีจิสเตอร์
  • การจัดวางหน่วยความจำจะเหมือนเดิมเสมอ แอดเดรสของอ็อบเจ็กต์ไม่เปลี่ยน ค่ารีจิสเตอร์เหมือนเดิม และ system call คืนข้อมูลเดิม
  • fuzzer และเครื่องมือฉีดความขัดข้องแบบสุ่มจะทรงพลังขึ้นเมื่อใช้ร่วมกับ rr
    • เครื่องมือเหล่านี้เก่งในการก่อให้เกิดความล้มเหลวที่เกิดเป็นครั้งคราว แต่อาจทำซ้ำความล้มเหลวเดิมได้ยาก
    • rr บันทึกการรันแบบสุ่ม และหากล้มเหลว ก็ให้ดีบักปัญหาแบบ deterministic จากบันทึกที่เก็บไว้ได้

ความแตกต่างจากเครื่องมือบันทึก·เล่นซ้ำเดิม

  • rr นำแนวคิดเก่าอย่าง record-and-replay debugging มาทำให้เป็นจริงตามเป้าหมายการออกแบบเฉพาะ
  • จุดโฟกัสแรกเริ่มคือ Firefox
    • เทคนิคบันทึก·เล่นซ้ำจำนวนมากต้องใช้ภาษาบางภาษาโดยเฉพาะ หรือสเกลไม่เหมาะ จึงรับมือกับ Firefox ได้ยาก
    • Firefox เป็นแอปพลิเคชันซับซ้อน ดังนั้นถ้ามีประโยชน์ต่อการดีบัก Firefox ก็มีแนวโน้มว่าจะมีประโยชน์โดยทั่วไปด้วย
  • ให้ความสำคัญกับความสามารถในการนำไปใช้งานจริง
    • rr ทำงานบน Linux kernel ทั่วไปและฮาร์ดแวร์ทั่วไป
    • ไม่ต้องเปลี่ยนการตั้งค่าระบบ
    • เทคนิคอื่นจำนวนมากต้องเปลี่ยน kernel หรือรัน OS ใน virtual machine
  • ตั้งเป้า overhead เวลารันต่ำ
    • หากจะมาแทน workflow ของ gdb ต้องได้ผลลัพธ์ด้วยความเร็วใกล้เคียงกับตอนใช้ gdb
    • overhead ต่ำยังช่วยลดการรบกวนการทดสอบด้วย
  • ให้ความสำคัญกับความเรียบง่ายของการออกแบบ
    • หลีกเลี่ยงแนวทางที่พึ่งพาเทคนิคซับซ้อน เช่น dynamic binary instrumentation
    • ความเรียบง่ายยังช่วยให้ rr แข็งแกร่งและมี overhead ต่ำ

ประสิทธิภาพและข้อจำกัด

  • overhead ของ rr ขึ้นอยู่กับ workload ของแอปพลิเคชัน
  • ในชุดทดสอบของ Firefox ประสิทธิภาพการบันทึกอยู่ในระดับใช้งานได้จริง
    • ในบางกรณี slowdown ลดลงถึง ≤ 1.2x
    • ชุดทดสอบที่ใช้เวลา 10 นาที จะใช้เวลาประมาณ 12 นาทีเมื่อบันทึกด้วย rr
  • overhead อาจแตกต่างกันมากตาม workload
  • ในโปรแกรมที่ส่วนใหญ่เป็น single-threaded จะมี overhead ต่ำกว่าระบบบันทึก·เล่นซ้ำคู่แข่งที่รู้จักกันอย่างมาก
  • ข้อจำกัดหลักมีดังนี้
    • เนื่องจากจำลองเครื่องแบบคอร์เดียว โปรแกรมแบบขนานจะเจอ slowdown จากการรันบนคอร์เดียว
    • ไม่สามารถบันทึกโปรเซสที่แชร์หน่วยความจำกับโปรเซสนอก tree ที่ถูกบันทึกได้
    • ฟีเจอร์อย่าง X shared memory ในโปรเซสที่ถูกบันทึกจะถูกปิดใช้งานอัตโนมัติ
    • ต้องใช้ x86 CPU ที่ค่อนข้างใหม่ หรือ ARM CPU บางรุ่น เช่น Apple M1+
    • ต้องรู้จัก system call ทั้งหมดที่โปรเซสที่ถูกบันทึกเรียกใช้
    • รองรับ system call ในวงกว้างที่จำเป็นต่อ Firefox และแอปพลิเคชันหลายตัว แต่ยังไม่สมบูรณ์ทั้งหมด
    • สามารถรายงาน system call ที่ไม่รองรับได้ที่ GitHub issue
    • อาจต้องมีการอัปเดตเพื่อรองรับการเปลี่ยนแปลง kernel, การอัปเดตไลบรารีระบบ และตระกูล CPU ใหม่

แหล่งข้อมูลและชุมชน

  • Extended Technical Report เป็นเอกสารภาพรวมที่อธิบายวิธีทำงานและประสิทธิภาพของ rr
  • rr wiki ครอบคลุมหัวข้อทางเทคนิคเกี่ยวกับ rr
  • สามารถถามคำถามได้ที่ mailing list หรือ #rr on chat.mozilla.org
  • มีวิดีโอเดโมให้ดูด้วย
    • Video 7: เดโมสั้นๆ ของการบันทึก·เล่นซ้ำ Firefox
    • Video 8: การสาธิตฟีเจอร์พื้นฐานของ rr อย่างละเอียด
    • Video 9: การบรรยายเชิงเทคนิคระดับสูงเกี่ยวกับ rr โดย Robert O'Callahan

1 ความคิดเห็น

 
GN⁺ 2024-07-22
ความคิดเห็นบน Hacker News
  • เคยใช้ rr ร่วมกับ breakpoint เมื่อตัวแปรเปลี่ยนค่า และ reverse-continue เพื่อทำ reverse engineering กับ codebase ขนาดใหญ่ได้สำเร็จมาก
    ใช้เวลาพอสมควรกว่าจะดึง core logic ที่อยู่ลึก ๆ ออกมาได้ แต่มีประโยชน์มาก

    • ฟังดูน่าสนใจ อยากรู้ว่ามี บทความสรุป ที่พอจะแชร์ได้ไหม
    • อยากรู้ว่า codebase ขนาดใหญ่นั้น พูดแบบอาจจะไม่ค่อยตรงนัก ถือว่าเขียนด้วยภาษาแบบ dynamic typing ได้ไหม
  • น่ากล่าวถึงด้วยว่ามีคนเคยพยายาม พอร์ต rr ไปเป็น Rust และเขียนไปได้ราว 60,000 บรรทัดก่อนจะ archive โปรเจกต์
    น่าจะเป็นกรณีศึกษาที่น่าสนใจสำหรับเปรียบเทียบผลกระทบ ข้อดี ข้อจำกัด และความยากลำบากของการเขียนใหม่จาก C++ เป็น Rust
    https://github.com/sidkshatriya/rd/

    • จากมุมมองของผู้ดูแล rr งานของ Sid นั้นดี และพวกเราก็สนับสนุน
      แต่เหตุผลใหญ่ที่ยากจะย้ายสิ่งนั้นมาเป็นเวอร์ชันทางการคือ 1) rr มีการแก้ไขซับซ้อนจำนวนมากที่สะสมมา 10 ปีเพื่อรับมือกับ พฤติกรรมของเคอร์เนล/โปรเซส แปลก ๆ จึงกังวลว่าจะสูญหายไประหว่างการพอร์ต และ 2) ยังต้องพอร์ต remix[0] ซึ่งเป็นโปรเจกต์ซอร์สปิดที่สร้างอยู่บน rr ไปด้วย
      [0] https://robert.ocallahan.org/2020/12/rr-remix-efficient-repl...
    • ไม่ค่อยเข้าใจกระแส “มาเขียน X/Y/Z ใหม่ด้วย Rust กันเถอะ” ที่มีมาหลายปี
      ไม่ค่อยรู้จัก Rust แต่คิดว่าน่าจะทำงานร่วมกับ C ได้ดี ถ้าซอฟต์แวร์ที่มีอยู่ทำงานได้ดีอยู่แล้ว ก็สงสัยว่าประโยชน์ของการ เขียนใหม่ด้วย Rust คืออะไร
    • คงเป็นการวิเคราะห์ที่ดี แต่ไม่น่าจะง่าย
      ดูคร่าว ๆ แล้ว rr 1.0 ใช้เวลา 3 ปี มีผู้มีส่วนร่วมรายใหญ่ราว 3–4 คน และดูเหมือนมีผู้มีส่วนร่วมอย่างน้อย 5 คน ส่วน rr ในปัจจุบันคือผลลัพธ์ที่มี งานเพิ่มเติมอีก 10 ปี ทับลงไป
  • สงสัยว่ามันสำหรับ C/C++ เท่านั้นจริงหรือเปล่า
    เท่าที่เข้าใจอย่างจำกัด debugger ต้องมีรายการ symbol, ไฟล์ .pdb ของ Windows และสิ่งที่เทียบเท่าบน Linux, ความเข้าใจ system call และสิ่งคล้าย ๆ กัน คิดว่ามันไม่ได้สนใจมากนักว่าไบนารีที่กำลัง debug ถูกสร้างจากอะไร แน่นอนว่าต้องอยู่บนสมมติฐานว่าเป็น native code
    สงสัยว่า rr ใช้กับภาษาอย่าง Rust, Zig, Odin, Nim ไม่ได้หรือไม่ ส่วนภาษาที่ใช้ managed memory อย่าง Python, JS, C# นั้นแน่นอนว่าไม่ได้คาดหวัง

    • ใช้อยู่กับ Zig
      ใช้คู่กับ allocator ของ Zig แล้วค่อนข้างสะดวก ตอน free มันจะเขียนไบต์ 0xaa และไม่ใช้ address ซ้ำ ทำให้มีโอกาส crash สูง จากนั้นก็สามารถตั้ง watchpoint บน memory นั้นแล้วย้อนกลับไปถึงจุดที่ถูก free ได้
    • เคยทำให้ rr ใช้ได้กับ build ของ rpython ที่เฉพาะเจาะจงมาก ๆ มาก่อน ซึ่งอาจน่าแปลกใจว่ายังมีความสนใจในเรื่องนี้ต่อเนื่อง
      https://github.com/python/devguide/issues/1283
      https://morepypy.blogspot.com/2016/07/reverse-debugging-for-...
      https://github.com/mesalock-linux/mesapy/blob/mesapy2.7/READ...
    • ใช้ RR กันเยอะใน Julia
      แม้มันจะแสดงระบบผ่านมุมมองของ GDB เท่านั้น แต่ก็ทำงานได้ไม่ว่าจะเป็น ภาษา interpreted หรือภาษา compiled
      สิ่งที่ใช้ไม่ได้คือกรณีที่ driver อัปเดต address ที่ map ไว้โดยตรง CUDA เป็นตัวอย่างหนึ่ง ซึ่งถ้าจะ replay ก็ต้อง model การโต้ตอบกับ driver และเป็นอย่างนั้นตั้งแต่ก่อนจะไปถึง UVM แล้ว
      อีกข้อดีคือ RR บันทึก process tree ทำให้ดูโปรเซสอื่น ๆ ที่ executable เรียกขึ้นมาได้ง่าย
    • rr ใช้ gdb เป็นส่วน debugger จริง ๆ ดังนั้นสิ่งที่ทำได้ใน gdb ก็ทำได้ใน rr
      แต่ rr ต้องครอบ system call ทั้งหมด จึงเฉพาะทางกับ Linux มาก และไม่ทำงานบน Windows รูปแบบข้อมูล symbol ของ Linux คือ DWARF
    • ใช้กับ Rust ด้วย: https://bitshifter.github.io/rr+rust/index.html#1
  • rr เจ๋งมากจริง ๆ แต่ทุกครั้งที่ผมตัดสินใจหยิบมันออกมาใช้เป็น “อาวุธหนัก” แทบทุกครั้งจะเป็น บั๊ก concurrency และเพราะอย่างนั้น rr จึงมัก reproduce ไม่ได้
    ถึงอย่างนั้น ถ้าบางภาษานำ rr เข้าไปอยู่ใน toolchain โดยตรงได้ก็คงดีมาก แน่นอนว่าเราสามารถ “แค่” ใช้ rr/gdb ได้เสมอ แต่ลองนึกภาพว่าการตั้งค่าและใช้งานการเรียก rr ง่ายพอ ๆ กับ pdb ของ Python

    • ถ้าใช้ตัวเลือก chaos mode ตอนรัน rr อาจช่วยเผยปัญหา concurrency บางอย่างได้
      โดยพื้นฐานคือสลับ thread ที่กำลังรันบ่อย ๆ เพื่อจำลองสถานการณ์ที่หลายคอร์รันพร้อมกัน จริง ๆ แล้วมันช่วยผมหา race condition ได้บางตัว แต่แน่นอนว่ามีข้อจำกัด
    • เคยมีบั๊ก concurrency ที่จับได้ด้วย rr จริง ๆ
      ในงาน MPI ผมแนบ rr ไว้เฉพาะกับ rank 0 และพบจุดที่ลำดับ send/recv ต่างกันทำให้เกิดปัญหา แถมยังเป็นปัญหาค่อนข้างซับซ้อนเพราะเป็นโมเดล Python ที่เชื่อมกับการสร้าง native code จำนวนมาก
    • อีกอย่างที่ rr น่าเสียดายที่ยังไม่รองรับคือ GPU
      อยากใช้มาก แต่แทบทุกงานที่ผมทำเกี่ยวข้องกับ GPU ไม่ทางใดก็ทางหนึ่ง
    • ผมก็คล้ายกัน
      ตอนที่ต้องการจริง ๆ คือบน Mac แต่น่าเสียดายที่ rr ทำงานบน Linux เท่านั้น
      มี Undodb ที่ทำงานบน Mac และอาจรองรับ multithreading ได้ด้วย แต่เสียดายที่ราคาประมาณ 50,000 ดอลลาร์
  • แม้จะอิงจาก rr แต่ https://pernos.co/ ซึ่งเพิ่มการรันโปรแกรมทั้งโปรแกรมให้เป็นฐานข้อมูลที่สืบค้นได้ ก็น่าดูเช่นกัน
    ทำสิ่งแบบนี้ได้

    [...] แค่คลิกค่าที่ผิดก็พอ เนื่องจากมีประวัติทั้งหมดของโปรแกรม Pernosco จึงอธิบายได้ทันทีว่าค่านี้มาจากไหน ค่าจะถูกไล่ย้อนผ่านเหตุการณ์อย่าง memcpy หรือการย้ายเข้าออกรีจิสเตอร์ และแต่ละขั้นตอนจนถึงจุดที่ค่านั้น “originated” จะถูกแสดงในแผง “Dataflow” ที่เปิดขึ้นโดยอัตโนมัติ ไม่ต้องอ่านหรือทำความเข้าใจโค้ดแล้วเดาว่าอาจเกิดอะไรขึ้น แค่ถามดีบักเกอร์ว่าเกิดอะไรขึ้นจริง ๆ ก็พอ
    https://pernos.co/examples/race-condition

  • ยังมี การดีบักย้อนกลับ ที่มีอยู่ใน GDB ด้วย: https://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial
    มองว่า rr ให้ฟีเจอร์และความยืดหยุ่นมากกว่า แต่ถึงอย่างไร GDB เองก็ทำการดีบักย้อนกลับได้มาระยะหนึ่งแล้ว

    • ถ้าอยากพูดถึงสิ่งนี้ ก็แทบจะแน่นอนว่าไม่ได้ลองใช้จริง
      การใช้งานของ GDB สะดวกกว่า rr ตรงที่เริ่ม/หยุดการบันทึกเมื่อไรก็ได้ แต่ ประสิทธิภาพต่ำกว่าหลายลำดับขั้น ใช้ได้กับโค้ดชิ้นเล็กมาก ๆ เท่านั้น นอกเหนือจากนั้นแทบจะใช้เวลาตลอดกาลหรือทรัพยากรหมด
    • เคยใช้การดีบักย้อนกลับในตัวของ GDB ได้สำเร็จครั้งหนึ่งบนแพลตฟอร์มที่ rr ยังไม่รองรับในตอนนั้น
      มันทำงานและช่วยตามหาบั๊กได้ แต่ช้าจนเจ็บปวด ต้องลดขนาดอินพุตเพื่อให้พอใช้งานได้ และโชคดีที่หลังจากทำแบบนั้นแล้วก็ยังทำให้เกิดปัญหาซ้ำได้
    • การใช้งาน replay ในตัวของ gdb ทำให้โปรแกรมช้าลงประมาณ 10000 เท่า
      ถ้าสามารถค้นหาแบบไบนารีไปยังสถานะโปรแกรมที่ต้องการได้ด้วยการรีสตาร์ตน้อยกว่า 10000 ครั้ง ก็ใช้เวลาเครื่องน้อยกว่าการรันย้อนกลับ ในทางปฏิบัติ ความช้าลงมันมากจนหลายครั้งการเลื่อนดีบักเกอร์แบบโต้ตอบไปให้ใกล้สถานะที่ถูกต้องหลาย ๆ รอบแล้วรีสตาร์ตโปรแกรมก็เพียงพอแล้ว
      ที่สามารถใช้ฟีเจอร์ replay ของ gdb ให้เป็นประโยชน์ได้ เพราะมีไฟล์อินพุตที่ทำให้โปรแกรมแครชภายในไม่ถึง 1 วินาทีหลังเริ่มรัน ดังนั้นจึงสามารถย้อนจาก “ตัวแปรนี้ผิด” ไปถึง “ตัวแปรนี้ถูกตั้งเป็นค่าที่ผิดนั้นได้อย่างไร?” ได้โดยรอเพียงไม่กี่นาที
    • ถ้าจำไม่ผิด rr ออกมาก่อนของ gdb
  • บน Windows สามารถใช้ WinDbg เพื่อจุดประสงค์เดียวกันได้
    รองรับการดีบักปัญหาแบบมัลติเธรดได้ดีกว่า
    https://www.forrestthewoods.com/blog/windbg-time-travelling-...

    • WinDbg ใช้การทำ time travel ที่อิงกับการจำลองระดับคำสั่ง จึงเกิด ความช้าลง 10~20 เท่า ตามเทคนิคนั้น
      rr ใช้การทำ time travel debugging แบบ record-replay และถ้าทำอย่างถูกต้องก็มี overhead น้อยกว่ามาก ครั้งล่าสุดที่ดู overhead ของ rr อยู่ที่ประมาณช้าลง 2 เท่า และถ้าจำไม่ผิดเคยเห็น time travel debugger แบบ record-replay ตัวอื่นอยู่ในระดับ 10% ด้วย
      10% นั้นถูกกว่า WinDbg 100 เท่า และต่ำพอที่จะเปิดทิ้งไว้ตลอดเวลาใน production ได้ นี่เป็นความแตกต่างที่เปลี่ยนเกม
  • เมื่อนานมาแล้ว VMWare Workstation ก็เคยรองรับฟีเจอร์แบบนี้
    ทำได้ไม่ใช่แค่โปรแกรมใน user space แต่รวมถึง เคอร์เนลและไดรเวอร์ ภายใน VM ด้วย ฟีเจอร์นี้ถูกปล่อยออกมาและอยู่มาหลายเวอร์ชัน ก่อนจะถูกถอดออกเพราะการเมืองภายใน

    • ก่อนหน้านั้นน่าจะมี AMD SimNow
      ขยายได้ด้วยปลั๊กอิน และปลั๊กอินสามารถควบคุม CPU ที่กำลังถูกจำลองได้อย่างสมบูรณ์ สงสัยว่ายังมีอะไรคล้าย ๆ กันอยู่ที่ไหนสักแห่งหรือไม่
  • สงสัยว่าปัญหา CPU Ryzen ของ rr ตอนนี้กลายเป็นเรื่องในอดีตไปอย่างแน่นอนแล้วหรือยัง

    • ใช่
      ใช้ rr ตลอดทั้งวันทุกวันเพื่อบันทึกการรัน Firefox บน Threadripper Pro 7950 ที่ค่อนข้างใหม่มาก และใช้ร่วมกับ Pernosco ด้วย วิกิ rr บน GitHub อธิบายวิธีทำให้ใช้งานได้อยู่แล้ว แค่ใช้ workaround เล็ก ๆ ก็ทำงานได้เสถียรมาก
  • ยังมีการถกเถียงเก่า ๆ ด้วย
    https://news.ycombinator.com/item?id=31617600 (มิถุนายน 2022)
    https://news.ycombinator.com/item?id=18388879 (พฤศจิกายน 2018)