การแก้ไขข้อบกพร่องของ Hit แคชระยะไกลสำหรับการดำเนินการระยะไกล

รายงานปัญหา ดูแหล่งที่มา Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

หน้านี้อธิบายวิธีตรวจสอบอัตราการเข้าถึงแคชและวิธีตรวจสอบ การไม่พบแคชในบริบทของการดำเนินการจากระยะไกล

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

ตรวจสอบอัตราการเข้าชมแคช

ในเอาต์พุตมาตรฐานของการเรียกใช้ Bazel ให้ดูบรรทัด INFO ที่แสดงรายการ กระบวนการ ซึ่งสอดคล้องกับการดำเนินการของ Bazel โดยประมาณ บรรทัดนั้นจะแสดงรายละเอียด ตำแหน่งที่เรียกใช้การดำเนินการ มองหาป้ายกำกับ remote ซึ่งระบุการดำเนินการ ที่ดำเนินการจากระยะไกล linux-sandbox สำหรับการดำเนินการที่ดำเนินการในแซนด์บ็อกซ์ในเครื่อง และค่าอื่นๆ สำหรับกลยุทธ์การดำเนินการอื่นๆ การดำเนินการที่มีผลลัพธ์มาจากแคชระยะไกลจะแสดงเป็น remote cache hit

เช่น

INFO: 11 processes: 6 remote cache hit, 3 internal, 2 remote.

ในตัวอย่างนี้ มีการเข้าถึงแคชระยะไกล 6 ครั้ง และการดำเนินการ 2 รายการไม่มี การเข้าถึงแคชและดำเนินการจากระยะไกล คุณสามารถละเว้นส่วนที่ 3 ภายในได้ โดยปกติแล้วจะเป็นการดำเนินการภายในเล็กๆ น้อยๆ เช่น การสร้างลิงก์สัญลักษณ์ การเข้าชมแคชในเครื่องจะไม่รวมอยู่ในข้อมูลสรุปนี้ หากคุณได้รับ 0 processes (หรือตัวเลขที่ต่ำกว่าที่คาดไว้) ให้เรียกใช้ bazel clean ตามด้วยคำสั่งบิลด์/ทดสอบ

การแก้ปัญหาการเข้าชมแคช

หากอัตราการเข้าชมแคชไม่เป็นไปตามที่คาดไว้ ให้ทำดังนี้

ตรวจสอบว่าการเรียกใช้คำสั่งบิลด์/ทดสอบเดียวกันอีกครั้งจะทำให้แคชทำงาน

  1. เรียกใช้บิลด์และ/หรือการทดสอบที่คุณคาดว่าจะสร้างแคช ครั้งแรกที่เรียกใช้บิลด์ใหม่ในสแต็กหนึ่งๆ คุณจะคาดหวังได้ว่าจะไม่มีแคชระยะไกล ที่ตรงกัน ผลลัพธ์ของการดำเนินการจะจัดเก็บไว้ในแคชและควรมีการเรียกใช้ในภายหลัง

  2. เรียกใช้ bazel clean คำสั่งนี้จะล้างแคชในเครื่อง ซึ่งช่วยให้คุณตรวจสอบการเข้าชมแคชระยะไกลได้โดยไม่ต้องให้ผลลัพธ์ถูกปิดบังโดยการเข้าชมแคชในเครื่อง

  3. เรียกใช้บิลด์และการทดสอบที่คุณกำลังตรวจสอบอีกครั้ง (ในเครื่องเดียวกัน)

  4. ตรวจสอบINFOสำหรับอัตราการเข้าชมแคช หากไม่เห็นกระบวนการใดๆ ยกเว้น remote cache hit และ internal แสดงว่าระบบกำลังป้อนข้อมูลและเข้าถึงแคชอย่างถูกต้อง ในกรณีนี้ ให้ข้ามไปยังส่วนถัดไป

  5. แหล่งที่มาของความคลาดเคลื่อนที่อาจเกิดขึ้นคือสิ่งที่ไม่ใช่แบบปิดในบิลด์ ซึ่งทำให้การดำเนินการได้รับคีย์การดำเนินการที่แตกต่างกันในการเรียกใช้ 2 ครั้ง หากต้องการค้นหาการดำเนินการเหล่านั้น ให้ทำดังนี้

    ก. เรียกใช้บิลด์หรือการทดสอบที่เป็นปัญหาอีกครั้งเพื่อรับบันทึกการดำเนินการ

      bazel clean
      bazel --optional-flags build //your:target --execution_log_compact_file=/tmp/exec1.log

    ข. เปรียบเทียบบันทึกการดำเนินการระหว่างการเรียกใช้ 2 ครั้ง ตรวจสอบว่าการดำเนินการเหมือนกันในไฟล์บันทึกทั้ง 2 ไฟล์ ความคลาดเคลื่อนจะให้ข้อมูลเบาะแสเกี่ยวกับการเปลี่ยนแปลงที่เกิดขึ้นระหว่างการเรียกใช้ อัปเดตบิลด์เพื่อขจัดความคลาดเคลื่อนดังกล่าว

    หากแก้ปัญหาการแคชได้แล้วและตอนนี้การเรียกใช้ซ้ำ ทำให้เกิดการเข้าชมแคชทั้งหมด ให้ข้ามไปยังส่วนถัดไป

    หากรหัสการกระทำเหมือนกัน แต่ไม่มีการเข้าชมที่แคช แสดงว่ามีบางอย่าง ในการกำหนดค่าที่ป้องกันไม่ให้แคช ดำเนินการต่อในส่วนนี้เพื่อ ตรวจสอบปัญหาที่พบบ่อย

  6. ตรวจสอบว่าการดำเนินการทั้งหมดในบันทึกการดำเนินการมี cacheable ตั้งค่าเป็น "จริง" หาก cacheable ไม่ปรากฏในบันทึกการดำเนินการสำหรับการดำเนินการที่กำหนด แสดงว่ากฎที่เกี่ยวข้องอาจมีแท็ก no-cache ในคำจำกัดความในไฟล์ BUILD ดูฟิลด์ mnemonic และ target_label ในบันทึกการดำเนินการเพื่อช่วยระบุว่าการดำเนินการมาจากที่ใด

  7. หากการดำเนินการเหมือนกันและcacheable แต่ไม่มีแคชฮิต แสดงว่าบรรทัดคำสั่งอาจมี --noremote_accept_cached ซึ่งจะปิดใช้การค้นหาแคชสำหรับการสร้าง

    หากการหาบรรทัดคำสั่งจริงเป็นเรื่องยาก ให้ใช้บรรทัดคำสั่งที่ถูกต้อง จาก Build Event Protocol ดังนี้

    ก. เพิ่ม --build_event_text_file=/tmp/bep.txt ลงในคำสั่ง Bazel เพื่อรับ บันทึกเวอร์ชันข้อความ

    ข. เปิดบันทึกเวอร์ชันข้อความแล้วค้นหาstructured_command_lineข้อความที่มี command_line_label: "canonical" โดยจะแสดงตัวเลือกทั้งหมดหลังจากขยาย

    ค. ค้นหา remote_accept_cached และตรวจสอบว่าได้ตั้งค่าเป็น false หรือไม่

    ง. หาก remote_accept_cached เป็น false ให้พิจารณาว่ามีการตั้งค่าเป็น false ที่ใด ไม่ว่าจะในบรรทัดคำสั่งหรือในไฟล์ bazelrc

ตรวจสอบว่ามีการแคชในเครื่องต่างๆ

หลังจากที่แคชฮิตเกิดขึ้นตามที่คาดไว้ในเครื่องเดียวกันแล้ว ให้เรียกใช้ บิลด์/การทดสอบเดียวกันในเครื่องอื่น หากสงสัยว่าการแคช ไม่เกิดขึ้นในเครื่องต่างๆ ให้ทำดังนี้

  1. แก้ไขบิลด์เล็กน้อยเพื่อหลีกเลี่ยงการเข้าถึงแคชที่มีอยู่

  2. เรียกใช้บิลด์ในเครื่องแรก

     bazel clean
     bazel ... build ... --execution_log_compact_file=/tmp/exec1.log
  3. เรียกใช้บิลด์ในเครื่องที่ 2 โดยตรวจสอบว่ามีการแก้ไขจากขั้นตอนที่ 1 รวมอยู่ด้วย

     bazel clean
     bazel ... build ... --execution_log_compact_file=/tmp/exec2.log
  4. เปรียบเทียบบันทึกการดำเนินการของการเรียกใช้ 2 ครั้ง หากบันทึกไม่เหมือนกัน ให้ตรวจสอบการกำหนดค่าบิลด์เพื่อหาความคลาดเคลื่อน รวมถึงพร็อพเพอร์ตี้จากสภาพแวดล้อมโฮสต์ที่รั่วไหลไปยังบิลด์ใดบิลด์หนึ่ง

การเปรียบเทียบบันทึกการดำเนินการ

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

คุณสร้างบันทึกการดำเนินการได้ใน 3 รูปแบบ ได้แก่ กะทัดรัด (--execution_log_compact_file) ไบนารี (--execution_log_binary_file) หรือ JSON (--execution_log_json_file) เราขอแนะนำให้ใช้รูปแบบกะทัดรัด เนื่องจากจะสร้างไฟล์ที่มีขนาดเล็กกว่ามากและมีค่าใช้จ่ายในการรันไทม์น้อยมาก วิธีการต่อไปนี้ใช้ได้กับทุกรูปแบบ นอกจากนี้ คุณยังแปลงระหว่างหน่วยต่างๆ ได้โดยใช้เครื่องมือ //src/tools/execlog:converter

หากต้องการเปรียบเทียบบันทึกของ 2 บิลด์ที่ไม่ได้แชร์แคชฮิตตามที่คาดไว้ ให้ทำดังนี้

  1. รับบันทึกการดำเนินการจากแต่ละบิลด์และจัดเก็บเป็น /tmp/exec1.log และ /tmp/exec2.log

  2. ดาวน์โหลดซอร์สโค้ด Bazel แล้วสร้าง//src/tools/execlog:parser เครื่องมือ:

    git clone https://github.com/bazelbuild/bazel.git cd bazel bazel build //src/tools/execlog:parser

  3. ใช้เครื่องมือ //src/tools/execlog:parser เพื่อแปลงบันทึกเป็นรูปแบบข้อความที่มนุษย์อ่านได้ ในรูปแบบนี้ การดำเนินการในบันทึกที่ 2 จะ จัดเรียงให้ตรงกับลำดับในบันทึกแรก ซึ่งจะช่วยให้เปรียบเทียบได้ง่ายขึ้น

    bazel-bin/src/tools/execlog/parser \
      --log_path=/tmp/exec1.log \
      --log_path=/tmp/exec2.log \
      --output_path=/tmp/exec1.log.txt \
      --output_path=/tmp/exec2.log.txt
    
  4. ใช้เครื่องมือเปรียบเทียบข้อความที่คุณชื่นชอบเพื่อเปรียบเทียบ /tmp/exec1.log.txt และ /tmp/exec2.log.txt