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

รายงานปัญหา ดูแหล่งที่มา

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

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

การตรวจสอบอัตรา Hit ของแคช

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

เช่น

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

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

การแก้ปัญหาการพบแคช

หากคุณไม่ได้รับอัตรา Hit ของแคชตามที่คาดไว้ ให้ทำดังนี้

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

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

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

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

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

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

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

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

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

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

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

    หากไม่จำเป็นต้องแยกความแตกต่างของบันทึกการดำเนินการ ให้ใช้แฟล็ก --execution_log_json_file ที่มนุษย์อ่านได้แทน แต่จะใช้กับความแตกต่างที่เสถียรไม่ได้เนื่องจากมีเวลาดำเนินการและไม่ได้รับประกันการสั่งซื้อ

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

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

    หากคุณคิดว่าบรรทัดคำสั่งจริงนั้นยาก ให้ใช้บรรทัดคำสั่ง Canonical จากโปรโตคอลบิลด์เหตุการณ์ดังนี้

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

    b. เปิดบันทึกเวอร์ชันข้อความของบันทึกและค้นหาข้อความ 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_binary_file=/tmp/exec1.log
    
  3. เรียกใช้บิลด์บนเครื่องที่ 2 เพื่อให้แน่ใจว่ารวมการแก้ไขจากขั้นตอนที่ 1 ไว้ด้วยแล้ว

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

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

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

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

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

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

    git clone https://github.com/bazelbuild/bazel.git
    cd bazel
    
  3. ใช้โปรแกรมแยกวิเคราะห์บันทึกการดำเนินการเพื่อแปลงบันทึกเป็นข้อความ การเรียกใช้ต่อไปนี้ยังจัดเรียงการดำเนินการในบันทึกที่ 2 เพื่อให้ตรงกับลำดับการดำเนินการในบันทึกแรกเพื่อให้เปรียบเทียบได้ง่าย

    bazel build src/tools/execlog:parser
    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