เหตุใดการลบไฟล์ด้วยชื่อจึงช้าลงอย่างมากและเร็วเป็นพิเศษ


11

Faux pas: วิธี "เร็ว" ที่ฉันพูดถึงข้างล่างนี้ไม่ได้เร็วกว่าวิธีช้า 60 เท่า เร็วกว่า 30 เท่า ฉันจะโทษความผิดพลาดในชั่วโมงนั้น (3AM ไม่ใช่เวลาที่ดีที่สุดของฉันสำหรับการคิดที่ชัดเจน :) ..

อัปเดต: ฉันได้เพิ่มบทสรุปของเวลาทดสอบ (ด้านล่าง)
ดูเหมือนจะมีสองประเด็นที่เกี่ยวข้องกับปัจจัยด้านความเร็ว:

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

การทดสอบทั้งหมดเสร็จสิ้นด้วย 1 ล้านไฟล์
(เวลาจริงผู้ใช้และ sys อยู่ในสคริปต์ทดสอบ)
สคริปต์ทดสอบสามารถพบได้ที่paste.ubuntu.com

#
# 1 million files           
# ===============
#
#  |time   |new dir   |Files added in  ASCENDING order  
#  +----   +-------   +------------------------------------------------- 
#   real    01m 33s    Add files only (ASCENDING order) ...just for ref.
#   real    02m 04s    Add files, and make 'rm' source (ASCENDING order) 
#                      Add files, and make 'rm' source (DESCENDING order) 
#   real    00m 01s    Count of filenames
#   real    00m 01s    List of filenames, one per line
#   ----    -------    ------
#   real    01m 34s    'rm -rf dir'
#   real    01m 33s    'rm filename' via rm1000filesPerCall   (1000 files per 'rm' call)
#   real    01m 40s    'rm filename' via  ASCENDING algorithm (1000 files per 'rm' call)
#   real    01m 46s    'rm filename' via DESCENDING algorithm (1000 files per 'rm' call)
#   real    21m 14s    'rm -r dir'
#   real    21m 27s    'find  dir -name "hello*" -print0 | xargs -0 -n 1000 rm'
#   real    21m 56s    'find  dir -name "hello*" -delete'
#   real    23m 09s    'find  dir -name "hello*" -print0 | xargs -0 -P 0 rm'
#   real    39m 44s    'rm filename' (one file per rm call) ASCENDING
#   real    47m 26s    'rm filename' (one file per rm call) UNSORTED
#                                                       

ฉันเพิ่งสร้างและลบไฟล์ทดสอบเปล่า10ล้านไฟล์ การลบไฟล์ตามชื่อ (เช่นrm filename) ฉันพบวิธีที่ยากที่จะมีความแตกต่างครั้งใหญ่ระหว่าง 2 วิธีที่แตกต่างกัน ...

ทั้งสองวิธีใช้rm filenameคำสั่ง เดียวกันแน่นอน

อัปเดต: ตามที่ปรากฏคำสั่งนั้นไม่เหมือนกัน ... หนึ่งในนั้นกำลังส่ง 1,000 ชื่อไฟล์พร้อมกันเป็น 'rm' ... มันเป็นปัญหาของการขยายตัวของเชลล์ที่ฉันคิดว่าแต่ละชื่อไฟล์ถูกเขียน ไปยังไฟล์ feeder บนบรรทัดของมันเอง แต่จริงๆแล้วมันคือ 1,000 ต่อบรรทัด

ชื่อไฟล์จะถูกจัดเตรียมผ่าน 'ไฟล์ตัวป้อน' ลงในwhile readลูป ..
ไฟล์ของตัวป้อนข้อมูลเป็นผลลัพธ์ของls -1 -f
วิธีการนี้เหมือนกันในการตรวจหาซ้ำทั้งหมดยกเว้นสิ่งเดียว:

  • ช้าวิธีใช้แฟ้มป้อนไม่ได้เรียงลำดับโดยตรงls -1 -f
  • รวดเร็ววิธีใช้รุ่นที่เรียงลำดับของไฟล์ไม่ได้เรียงลำดับเดียวกัน

ฉันไม่แน่ใจว่าการเรียงลำดับเป็นปัญหาที่นี่หรืออาจเป็นไปได้ว่าไฟล์ตัวเรียงลำดับเพิ่งเกิดขึ้นเพื่อให้ตรงกับลำดับที่ไฟล์ถูกสร้างขึ้น (ฉันใช้อัลกอริธึมจำนวนเต็มน้อยไปหามาก)

สำหรับไฟล์ 1 ล้านไฟล์วิธีที่รวดเร็ว rm filenameคือเร็วกว่าวิธีที่ช้ากว่า60เท่า... อีกครั้งฉันไม่รู้ว่านี่เป็นปัญหา "การเรียงลำดับ" หรือปัญหาแฮชหลังโต๊ะ ... ฉันสงสัยว่า มันไม่ได้เป็นปัญหาที่ง่ายเรียงลำดับเพราะทำไมจะจงใจให้ฉันunsortรายการเพิ่มสด "เรียง" ลำดับของชื่อไฟล์ ... ls -1 -f

ฉันแค่สงสัยว่าเกิดอะไรขึ้นที่นี่ดังนั้นจึงไม่ใช้เวลาหลายวัน (ใช่วัน) ในการลบไฟล์ 10 ล้านไฟล์ถัดไป :) .... ฉันพูดว่า "วัน" เพราะฉันลองใช้ตัวเลือกมากมายและ จำนวนครั้งที่เกี่ยวข้องเพิ่มขึ้นอย่างไม่เป็นสัดส่วนกับจำนวนไฟล์ที่เกี่ยวข้อง .. ดังนั้นฉันจึงทดสอบรายละเอียดเพียง1ล้านเท่านั้น

BTW: การลบไฟล์ผ่านทาง "รายการเรียงลำดับ" ของชื่อจริงเร็วกว่าrm -rfโดยใช้ตัวคูณของ 2
และ: rm -rช้ากว่าวิธีเรียงลำดับรายการ 30 ครั้ง

... แต่ "เรียงลำดับ" เป็นปัญหาที่นี่หรือไม่ หรือมันเกี่ยวข้องกับวิธี hashing (หรืออะไรก็ตาม) ของการจัดเก็บที่ใช้โดย ext4?

สิ่งที่ค่อนข้างลึกลับสำหรับฉันคือการโทรแต่ละครั้งrm filenameไม่เกี่ยวข้องกับการโทรก่อนหน้า .. (อย่างน้อยก็เป็นอย่างนั้นจากมุมมอง 'ทุบตี')

ฉันใช้ Ubuntu / bash / 'ext4' / ไดรฟ์ SATA II


1
คุณทำผิด! (tm) เคยได้ยินfind -deleteหรือ
alex

การทดสอบ 2 รายการของคุณเริ่มต้นในเงื่อนไขที่ไม่เท่าเทียมกัน (ฉันไม่ได้แกล้งทำเป็นสิ่งนี้สำคัญ): หนึ่งอ่านชื่อไฟล์จากไฟล์และอีกหนึ่งอ่านชื่อไฟล์จากไฟล์ที่สร้างขึ้น (เรียงลำดับ) ทันทีก่อนการทดสอบ อาจเป็นได้ว่าไฟล์ที่ถูกแคชในกรณีที่ 2 เล่นบางไฟล์ (หรืออาจจะไม่รู้ว่าใคร) เพื่อให้การทดสอบอยู่ในสภาพที่เท่าเทียมกันมากขึ้นบางทีคุณควรทำไฟล์ง่าย ๆcatก่อนการทดสอบครั้งที่ 1 - sortก่อนการทดสอบครั้งที่ 2
imz - Ivan Zakharyaschev

และฉันขอแนะนำให้คุณนำเสนอข้อสังเกตและคำถามของคุณอย่างชัดเจนยิ่งขึ้น ได้โปรดทีละอย่าง: เปรียบเทียบเพียง 2 กรณีในคำถามเดียวนำทั้งสองกรณีสำคัญมาไว้ที่พื้นก่อนอื่น ๆ ทั้งหมดเป็นเพียงข้อมูลเบื้องหลัง กรุณาทำให้ชัดเจน โปรดอย่ารวมข้อสังเกตหลายอย่างไว้ในการโพสต์เดียว
imz - Ivan Zakharyaschev

การนำเสนอระบบและเวลาว่างจากผู้ใช้ของคุณอาจเป็นสิ่งสำคัญสำหรับการไขปริศนาดังนั้นโปรดรวมไว้ในคำถามของคุณ ข้อใดที่ทำให้การทดสอบของคุณแตกต่างอย่างมาก?
imz - Ivan Zakharyaschev

1
การเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากของความชั่วร้ายทั้งหมด :) เมื่อไหร่ที่คุณจะลบไฟล์ 10 ล้านไฟล์? 100,000 ต่อวินาทีดูเหมือนจะเร็วพอสำหรับฉัน (เพื่อทำลายระบบของคุณ)
ผู้ใช้ที่ไม่รู้จัก

คำตอบ:


2

rm -r คาดว่าจะช้าตามที่เรียกซ้ำ การสำรวจเส้นทางแรกที่มีความลึกจะต้องทำบนโครงสร้างไดเรกทอรี

ตอนนี้คุณสร้างไฟล์ได้ 10 ล้านไฟล์อย่างไร คุณใช้สคริปต์ที่วนรอบบางคำสั่งหรือไม่? 1.txt, 2.txt, 3.txt ... หากใช่ไฟล์เหล่านั้นอาจถูกจัดสรรในลำดับเดียวกันในบล็อกที่ต่อเนื่องกันใน hdd.so การลบคำสั่งเดิมจะเร็วขึ้น

"ls -f" จะเปิดใช้งาน -aU ซึ่งจะแสดงรายการตามลำดับไดเรกทอรีซึ่งเรียกซ้ำอีกครั้ง


1
McAlot: ฉันไม่เห็นว่า 'recursive' จะสำคัญอย่างไรในกรณีนี้เนื่องจากไม่มีไดเรกทอรีย่อยที่เกี่ยวข้อง ... ใช่ฉันใช้ "1.txt, 2.txt, 3.txt 'บางทีอาจมีหลายอย่าง สิ่งที่มีปฏิสัมพันธ์: เช่นทำไมมันใช้เวลาเพียง 1 นาที 30 วินาทีเพื่อสร้าง 1,000,000 ไฟล์ แต่มันต้องใช้ 10s 7m เพื่อสร้าง 2 ล้านและหลังการลบสูตร 1 ล้าน. มากใช้เวลานาน (30s 9m) แปลก ๆ ของตนทุกอย่างทำงานได้ อย่างช้า ๆ ในทันทีสิ่งนี้เคยเกิดขึ้นมาก่อนด้วยฉันคิดว่า (?) การลบไดเรกทอรีแก้ไขมันมี daemon ไฟล์ที่เกี่ยวข้อง (nautilus; ค้นหา) อาจจะมีการดำเนินการต่อไป ...
Peter.O

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

1
ฉันลบไดเรกทอรี 'ช้าลงแล้ว' และใช้ชื่ออื่นสำหรับไดเรกทอรีใหม่ เวลาในการสร้างไฟล์ 1 ล้านไฟล์ตอนนี้กลับลงไปที่ 1m 33s (เทียบกับ 9m 30s เมื่อไดเรกทอรี "มี" 2 ล้านไฟล์ที่ถูกลบซึ่งเป็นครั้งแรกที่มีชื่อเดียวกับที่เพิ่มใหม่ 1 ล้าน) ... น่าสนใจและมัน นับด้วยความคิดเห็นของคุณ"... เพิ่งทำเครื่องหมายว่าไม่ได้ใช้"การเดินทาง ... มันเริ่มต้นที่จะทำให้ความรู้สึก :)
Peter.O

@ fred.bear ฉันไม่ดีจริง ๆ ฉันไม่ทราบลำดับชั้นที่แท้จริงและคำตอบของฉันเดา นอกจากนี้การทดสอบของคุณเน้นข้อมูลเมตา แต่ไม่ใช่ไฟล์จริงเนื่องจากเป็นไฟล์ว่าง วิธีที่ดีที่สุดในการกำหนดมาตรฐานของปัญหานี้คือการใช้ไฟล์จาก / var หรือแคชของเว็บเซิร์ฟเวอร์ อย่างไรก็ตามการทดสอบของคุณฟังดูน่าสนใจเกินไปคุณสามารถลองลบด้วยวิธีการสองวิธีที่ระบุไว้ในไดเรกทอรีที่แตกต่างกันได้ไหม .. เช่น /sample1/1.txt,2.txt ... และ /sample2/1.txt,2.txt ..
rajaganesh87

@ Mr.Confused.A.Lot ... ขอบคุณสำหรับความช่วยเหลือของคุณ คำอธิบายของคุณช่วยให้ฉันเข้าใจเพิ่มเติมเกี่ยวกับระบบไฟล์และลักษณะบางอย่างของมัน ... ตอนนี้ฉันมีความรู้สึกที่สมเหตุสมผลว่าอะไรเป็นสาเหตุของปัญหาความเร็วที่แตกต่างกัน ... บางตัวเลือกเพียงแค่คำสั่ง bash และอื่น ๆ เป็นปัญหาระบบไฟล์ ฉันทิ้งคำขวัญใหม่: "ใหญ่ไม่ดี" สำหรับไดเรกทอรี ... (สำหรับการกระทำบางอย่างน้อย) ...
Peter.O

2

คุณควรปรับโครงสร้างไฟล์ให้เหมาะสม ดังนั้นแทนที่จะ

for i in $(seq 1 1000); do touch file.$i; done

ทำสิ่งที่ชาญฉลาดเช่น (สันนิษฐานว่าทุบตี):

function bucklocate() 
{ 
    hash=$(echo -n "$1"|md5sum|cut -f1); 
    echo -n "${hash:1:1}/${hash:7:1}/${hash:9:2}/$1"; 
}

hexdig="{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}"
eval mkdir -p $hexdig/$hexdig/$hexdig$hexdig


for i in $(seq 1 1000); do touch $(bucklocate file.$i); done

ตอนนี้ตัวอย่างนี้ค่อนข้างช้าเนื่องจากการใช้ md5sum [1] ใช้สิ่งต่อไปนี้เพื่อการตอบสนองที่เร็วขึ้นตราบใดที่คุณไม่ต้องการชื่อไฟล์ใด ๆ ซ้ำซ้อนไม่มีความกังวลและไม่จำเป็นต้องมี แฮชที่ทำซ้ำได้ของชื่อหนึ่ง :)

mkdir -pv {0,1,2,3,4,5,6}/{0,1,2,3,4,5,6,7,8,9,10,12}
for  a in $(seq 1 100); do i=$RANDOM; echo touch "$(($i%7))/$(($i%13))/file.$i"; done

แน่นอนว่านี่คือแนวคิดที่ยืมมาจากแฮชเทเบิลทั้งหมด


ฉันคิดว่าคุณกำลังพูดว่า"ใช้ไดเร็กตอรี่เล็กลง" ... นั่นเป็นความคิดที่ขัดจังหวะ DBMS ที่ปลูกในบ้านซึ่งสร้างต้นไม้จากกลุ่มไฟล์ 'tree-less' 'บางคนอาจเรียกมันว่าการวางแผนล่วงหน้า :) ... ถ้ามันใช้งานได้ (และอาจเป็นเช่นนั้น) มันก็เป็นความคิดที่ดี ! ... ฉันเริ่มที่จะเข้าใจว่า 'ใหญ่ไม่ดี' เมื่อมันมาถึงจำนวนไฟล์ในไดเรกทอรี (สำหรับ ext4 อย่างน้อย) ... คุณได้แสดงวิธีแก้ปัญหาที่ต้องห้าม (+1) และฉัน ' ฉันค่อยๆทราบว่าทำไมบางวิธีการลบจึงเร็วกว่าวิธีอื่น ๆ ในไดเรกทอรีใดก็ตามไม่ว่าเล็กหรือใหญ่ ... ขอบคุณ
Peter.O

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