เหตุใด Git .git / objects / โฟลเดอร์จึงถูกแบ่งย่อยในหลาย ๆ โฟลเดอร์ของ SHA-prefix


21

Git เก็บวัตถุ (Blobs, trees) ไว้ใน.git/objects/โฟลเดอร์ แต่ละวัตถุสามารถอ้างอิงได้โดยแฮช SHA1 ที่คำนวณจากเนื้อหาของวัตถุ

อย่างไรก็ตามวัตถุจะไม่ถูกเก็บไว้ใน.git/objects/โฟลเดอร์โดยตรง แต่ละวัตถุจะถูกเก็บไว้ในโฟลเดอร์ที่ขึ้นต้นด้วยคำนำหน้าของแฮช SHA1 ดังนั้นวัตถุที่มีแฮชb7e23ec29af22b0b4e41da31e868d57226121c84จะถูกเก็บไว้ที่.git/objects/b7/e23ec29af22b0b4e41da31e868d57226121c84

เหตุใด Git จึงแบ่งการจัดเก็บวัตถุด้วยวิธีนี้

ทรัพยากรที่ฉันสามารถหาเช่นหน้า internals Git ของใน Git-SCM, เท่านั้นอธิบายวิธีการที่ไม่ว่าทำไม

คำตอบ:


33

เป็นไปได้ที่จะวางไฟล์ทั้งหมดไว้ในไดเรกทอรีเดียว แต่บางครั้งอาจมีขนาดใหญ่ขึ้นเล็กน้อย ระบบไฟล์หลายคนมีขีด จำกัด คุณต้องการที่จะวางที่เก็บ git บนไดรฟ์ที่จัดรูปแบบ FAT32 บนแท่ง USB หรือไม่? คุณสามารถจัดเก็บไฟล์ได้ 65,535 ไฟล์ในไดเรกทอรีเดียว ซึ่งหมายความว่าจำเป็นต้องแบ่งโครงสร้างไดเรกทอรีเพื่อให้การเติมไดเรกทอรีเดียวมีโอกาสน้อยลง

สิ่งนี้จะกลายเป็นปัญหากับระบบไฟล์อื่นและที่เก็บ git ที่ใหญ่ขึ้น repo คอมไพล์ค่อนข้างเล็กที่ฉันได้ออกไปเที่ยว (ประมาณ 360MiB) และมันมี 181,546 วัตถุสำหรับไฟล์ 11k ดึงrepo Linuxและคุณมีวัตถุ 4,374,054 ชิ้น หากคุณจะใส่สิ่งเหล่านี้ไว้ในไดเรกทอรีเดียวมันจะเป็นไปไม่ได้ที่จะตรวจสอบและจะผิดพลาด (สำหรับความหมายบางอย่างของ 'ความผิดพลาด') ระบบไฟล์

ดังนั้น? คุณแยกมันทีละไบต์ วิธีการที่คล้ายกันจะทำกับแอปพลิเคชันเช่น FireFox:

~/Li/Ca/Fi/Pr/7a/Cache $ ls
0/           4/           8/           C/           _CACHE_001_
1/           5/           9/           D/           _CACHE_002_
2/           6/           A/           E/           _CACHE_003_
3/           7/           B/           F/           _CACHE_MAP_

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

Windows NT ใช้เวลานานในการดำเนินการกับไดเรกทอรีในระบบไฟล์ Windows NT (NTFS) ที่จัดรูปแบบไดรฟ์ที่มีไฟล์จำนวนมากที่มีชื่อไฟล์ยาว (ชื่อที่ไม่เป็นไปตามข้อตกลง 8.3) ในไดเรกทอรีเดียว

เมื่อ NTFS ระบุไฟล์ในไดเรกทอรีมันจะต้องค้นหาชื่อ 8.3 ที่เกี่ยวข้องกับชื่อไฟล์แบบยาว เนื่องจากไดเรกทอรี NTFS นั้นยังคงอยู่ในสถานะเรียงลำดับชื่อไฟล์ที่ยาวและชื่อ 8.3 ที่สอดคล้องกันโดยทั่วไปจะไม่ติดกับชื่ออื่นในรายการไดเรกทอรี ดังนั้น NTFS ใช้การค้นหาเชิงเส้นของไดเรกทอรีสำหรับทุกไฟล์ที่มีอยู่ เป็นผลให้ระยะเวลาที่ต้องใช้ในการทำรายการไดเรกทอรีเพิ่มขึ้นด้วยกำลังสองของจำนวนไฟล์ในไดเรกทอรี สำหรับไฟล์จำนวนน้อย (น้อยกว่าสองสามร้อย) การหน่วงเวลาจะไม่สำคัญ แต่เมื่อจำนวนไฟล์ในไดเรกทอรีเพิ่มขึ้นเป็นหลายพันเวลาที่ต้องใช้ในการดำเนินการรายชื่อสามารถเพิ่มเป็นนาทีชั่วโมงหรือแม้แต่วัน ปัญหาจะรุนแรงขึ้นถ้าชื่อไฟล์ยาวคล้ายกันมาก - แตกต่างกันเพียงไม่กี่ตัวอักษรสุดท้าย

ด้วยไฟล์ที่ตั้งชื่อตาม checksum ของ SHA1 นี่อาจเป็นสูตรสำหรับภัยพิบัติและประสิทธิภาพสุดซึ้ง

ในขณะที่ด้านบนจากบันทึกเทคโนโลยีจาก Windows NT 3.5 (และ NTFS 1.2 - ใช้กันทั่วไป 1995 ช่วงต้นยุค 2000) นอกจากนี้ยังสามารถมองเห็นในสิ่งต่างๆเช่นEXT3กับการใช้งานของระบบแฟ้มที่ถูกเชื่อมโยงรายการที่กำหนด O (n) การค้นหา . และถึงแม้จะมีการเปลี่ยนแปลงต้นไม้ B:

ในขณะที่อัลกอริทึม HTree ปรับปรุงเวลาค้นหาอย่างมีนัยสำคัญ แต่อาจทำให้ประสิทธิภาพการทำงานลดลงสำหรับเวิร์กโหลดที่ใช้ readdir () เพื่อดำเนินการบางอย่างของไฟล์ทั้งหมดในไดเรกทอรีขนาดใหญ่
...
วิธีแก้ปัญหาหนึ่งที่เป็นไปได้เพื่อลดปัญหาประสิทธิภาพการทำงานซึ่งได้รับการแนะนำโดย Daniel Phillips และ Andreas Dilger แต่ยังไม่ได้ใช้งานเกี่ยวข้องกับเคอร์เนลที่เลือก inode ฟรีที่มีหมายเลข inode ตรงกับคุณสมบัติที่จัดกลุ่ม inodes ด้วยชื่อไฟล์แฮช Daniel และ Andreas แนะนำให้จัดสรร inode จากช่วงของ inodes ตามขนาดของไดเรกทอรีจากนั้นเลือก inode ที่ว่างจากช่วงนั้นโดยยึดตามชื่อไฟล์แฮช ในทางทฤษฎีควรลดจำนวนการฟาดฟันที่เป็นผลเมื่อเข้าถึง inodes ที่อ้างอิงในไดเรกทอรีตามลำดับ readdir ในไม่ชัดเจนว่ากลยุทธ์นี้จะส่งผลในการเร่งความเร็วอย่างไรก็ตาม; ในความเป็นจริงมันสามารถเพิ่มจำนวนรวมของบล็อกไอโหนดที่อาจต้องมีการอ้างอิงและทำให้ประสิทธิภาพของ readdir () + stat () เวิร์กโหลดแย่ลง เห็นได้ชัดว่า

อนึ่งบิตนี้เกี่ยวกับวิธีการปรับปรุงประสิทธิภาพมาจากปี 2005 มีการปล่อยคอมไพล์ในปีเดียวกัน

เท่าที่เห็นกับ Firefox และแอพพลิเคชั่นอื่น ๆ ที่มีไฟล์แคชจำนวนมากการออกแบบการแบ่งแคชเป็นไบต์ มันมีค่าใช้จ่ายเล็กน้อยและเมื่อใช้ cross platform กับระบบที่อาจจะเก่าไปหน่อยอาจเป็นความแตกต่างระหว่างโปรแกรมที่ทำงานหรือไม่


1
คุณสังเกตเห็นว่าบทความประสิทธิภาพของ NTFS ที่คุณอ้างถึงนั้นใช้กับ NT 3.5 เผยแพร่ในปี 1994 ใช่ไหม?
Avner Shahar-Kashtan

1
@ AvnerShahar-Kashtan yep Git เปิดตัวในปี 2005 ฉันรู้ว่าฉันใช้ระบบไฟล์ที่ใช้ NTFS v1.2 ในสภาพแวดล้อมขององค์กรในช่วงต้นยุค 2000 (ที่ บริษัท เทคโนโลยีแห่งหนึ่ง) มีการทับซ้อนกันระหว่างข้อกำหนดของ git และระบบไฟล์ในระบบที่มีอยู่ทั่วไปในเวลานั้น

บางทีมันอาจจะชัดเจนกว่านี้ถ้าคุณบอกว่านี่อาจเป็นสิ่งประดิษฐ์ทางประวัติศาสตร์ของสถานะของเทคโนโลยีเมื่อมีการแนะนำคอมไพล์เนื่องจากเป็นคำถามที่ถามในปี 2558 โดยอ้างถึงข้อ จำกัด ทางเทคนิคอายุยี่สิบปี ) ดูเหมือนสับสน
Avner Shahar-Kashtan

เพื่อความยุติธรรมgitระบบ "แพ็ค" จะช่วยลดปัญหาเหล่านี้ได้มากมาย ในทางทฤษฎีgitอาจใช้เพียงไดเรกทอรีเดียวและเพิ่งบรรจุใหม่เมื่อจำนวนไฟล์ในไดเรกทอรีนั้นเกินขีด จำกัด ที่แน่นอน (ขึ้นอยู่กับ FS)
nneonneo

5
@ AvnerShahar-Kashtan หากคุณอ่านบทความ SO ที่เชื่อมโยงคุณจะเห็นว่าการจัดการกับไดเรกทอรีที่มีไฟล์จำนวนมากเป็นปัญหาในระบบไฟล์หลายระบบและระบบปฏิบัติการไม่ใช่เพียงแค่ 3.5 NT การ จำกัด ไฟล์ไว้ข้าง ๆ แม้เพียงแค่การแสดงรายชื่อไฟล์ก็อาจมีค่าใช้จ่ายจำนวนมาก

8

มีสองเหตุผลว่าทำไมสิ่งนี้จึงเป็นที่ต้องการ

ไดเรกทอรีไม่สามารถมีขนาดใหญ่โดยพลการ เช่นบางระบบไฟล์ (ทันสมัยพอสมควร!) ถูก จำกัด ไว้ที่ 32000 รายการในไดเรกทอรีเดียว จำนวนการคอมมิตในเคอร์เนล Linux อยู่ในลำดับความสำคัญ การแบ่งย่อยคอมมิทด้วยตัวเลขฐานสิบหกสองตัวแรกนั้น จำกัด ขนาดสูงสุดถึง 256 รายการ ไดเรกทอรีย่อยจะเล็กกว่ามากสำหรับ repos คอมไพล์ทั่วไป

ไดเรกทอรีจะถูกสแกนเป็นเส้นตรง ในบางระบบไฟล์ (เช่นตระกูล Ext *) ไดเรกทอรีเป็นรายการที่เชื่อมโยงหรือสารบัญ ในการค้นหาไฟล์รายการทั้งหมดจะถูกสแกนจนกว่าจะพบชื่อไฟล์ที่ตรงกัน เห็นได้ชัดว่านี่เป็นสิ่งที่ไม่พึงประสงค์สำหรับประสิทธิภาพ ระบบไฟล์ที่ทันสมัยหลายแห่งใช้ตารางแฮชหรือ B-trees เพิ่มเติมเพื่อค้นหาอย่างรวดเร็ว แต่ไม่ใช่ทุกคนที่มี การทำให้แต่ละไดเรกทอรีมีขนาดเล็กหมายถึงเวลาในการเข้าถึงที่รวดเร็ว


1
"ระบบไฟล์บางส่วน (ทันสมัยพอสมควร!) ถูก จำกัด ไว้ที่ 32000 รายการในไดเรกทอรีเดียว" ถ้านั่นเป็นข้อ จำกัด ที่เข้มงวดที่สุดที่ Git พบคือมันจะดีกว่าไหมถ้า Git จะใช้ตัวอักษรสามตัวแรกของแฮชแทนที่จะเป็นสองตัวแรก? ซึ่งหมายความว่าobjectsไดเรกทอรีสามารถเก็บได้สูงสุด 4096 ไดเรกทอรีแทนการ จำกัด 256 ตามข้อกำหนดข้างต้น แต่ด้วยความได้เปรียบเพิ่มเติมที่ไดเรกทอรีย่อยเหล่านั้นจะมีความเสี่ยงน้อยกว่า 16x ที่จะจบลงด้วย> 32000 ไฟล์เอง
sampablokuper

1

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


1

มีบางระบบไฟล์และ / หรือการใช้งานระบบไฟล์และ / หรือการใช้งาน libc ที่ประสิทธิภาพลดลงกับรายการไดเรกทอรีจำนวนมาก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.