Làm thế nào để thứ tự các đối số ảnh hưởng đến tốc độ tìm kiếm


7

Làm thế nào để thứ tự của các đối số trong một findcuộc gọi ảnh hưởng đến tốc độ của kết quả?

So sánh ví dụ (A)

find -name dir -type d

và B)

find -type d -name dir

Hoặc bất kỳ kết hợp đối số nào khác (ví dụ: sử dụng -orhoặc -and). Tôi sẽ mong đợi findđược thông minh theo một cách nào đó.

Tôi đã cố gắng thu thập một số thống kê bằng cách thực hiện cả A và B với timevà 5 lần lặp lại. Tuy nhiên với

 11.86, 7.23, 5.25, 5.87, 7.16

cho A và cho B:

9.73, 6.56, 8.69, 7.14, 6.35

điều này không thực sự kết luận, với các giá trị trung bình xung quanh 7.5scho cả hai và phương sai khá cao.

Vì vậy, để lặp lại câu hỏi của tôi, thứ tự của các đối số có vấn đề sử dụng find?


Chắc chắn có các lệnh sẽ giảm tập hợp các tệp và thư mục khi tìm thấy đi cùng với các lệnh phân tích cú pháp, nhưng tôi không hoàn toàn chắc chắn rằng thứ tự -name ..-type dsẽ có vấn đề. Thử nghiệm của bạn dường như chỉ ra rằng nó không.
slm

@slm Tôi quan tâm đến nhiều hơn ví dụ cụ thể này. Nhưng tôi cũng không thể giải thích sự khác biệt lớn giữa thời gian ...
Bernhard

Tôi sẽ sử dụng một bước tiến để xem những gì tìm thấy bên dưới là để chẩn đoán thêm.
slm

@slm xem câu trả lời của tôi. Điều đó dường như không giúp đỡ.
terdon

Sau đó tôi sẽ chuyển sang một cái gì đó như fatrace, launchpad.net/fatrace . Điều này sẽ cho phép bạn theo dõi các sự kiện tệp findđang kích hoạt sẽ đưa bạn đến một bức tranh chính xác hơn về những gì các tệp đang được "chạm" khi findđang chạy.
slm

Câu trả lời:


11

Điều gì là tốn kém, là thực hiện các cuộc gọi hệ thống trên các tệp (đối với hệ thống tự gọi và cho I / O).

Những thứ như -type, -mtimeyêu cầu một lstat(2)cuộc gọi hệ thống trên tập tin. -name, -path, -regexKhông (mặc dù dĩ nhiên nó sẽ có các cuộc gọi hệ thống thực hiện để các thư mục chứa chúng để đọc nội dung của họ).

Thông thường, findkhông một lstat()anyway (vì nó cần phải biết liệu một tập tin là một thư mục hoặc không đi vào trong nó, trừ khi thông tin được cung cấp trong readdir()), nhưng có những trường hợp nó có thể làm mà không có nó. Chẳng hạn, nếu số lượng liên kết của một thư mục ít hơn 3, thì trong một số hệ thống tập tin, findbiết rằng nó không có các thư mục con và một số findtriển khai sẽ tối ưu hóa bằng cách không thực hiện lstattrong đó.

-xtypesẽ gây ra một stat(2),-printf ... , -lscó thể gây ra stat(), lstat(), readlink(), -lnamemột lstat()readlink().

Đó là lý do tại sao bạn có thể muốn đặt -name/ -path/ -regex... đầu tiên. Nếu họ có thể loại trừ một tập tin, họ có thể tránh một hoặc nhiều tòa nhà.

Bây giờ, một cái -regexcó thể đắt hơn một -name, nhưng tôi không chắc bạn sẽ nhận được nhiều bằng cách hoán đổi chúng.

Cũng lưu ý rằng một số find triển khai như GNU findthực hiện sắp xếp lại các kiểm tra theo mặc định khi có thể. Xem:

info find 'Optimisation Options'

trên hệ thống GNU ( có trên gnu.org cho phiên bản GNU mới nhất findutils).

Thông thường, nếu bạn đã thực hiện các thử nghiệm của mình trên một hệ thống GNU, cả hai lệnh sẽ làm điều tương tự vì dù sao findcũng sẽ di chuyển -namevề phía trước.

Vì vậy, để -type d -name ...so -name ... -type dsánh để tạo sự khác biệt, bạn cần một findtriển khai không tối ưu hóa bằng cách sắp xếp lại các vị từ đó và một trong đó tối ưu hóa bằng cách không thực hiện lstat()trên mỗi tệp.

Trường hợp sẽ có một sự khác biệt (rất lớn) bất kể việc triển khai là ở đâu:

find . -name 'x*' -exec test -d {} \; -print

vs

find . -exec test -d {} \; -name 'x*' -print

find không thể sắp xếp lại -exec như vậy có thể giới thiệu các khác biệt về chức năng ( findkhông thể biết liệu lệnh được thực thi chỉ để thử nghiệm hay thực hiện việc gì khác).

Và dĩ nhiên -exec ... {} \; là một số đơn đặt hàng có giá trị lớn hơn bất kỳ vị từ nào khác vì nó có nghĩa là thực hiện một quy trình và thực thi một lệnh trong đó (bản thân nó đang chạy nhiều lệnh gọi hệ thống) và chờ đợi nó và mã thoát của nó.

$ time find /usr/lib -exec test -d {} \; -name z\* -print > /dev/null
1.03s user 12.52s system 21% cpu 1:03.43 total
$ time find /usr/lib -name z\* -exec test -d {} \;  -print > /dev/null
0.09s user 0.14s system 62% cpu 0.367 total

(cuộc gọi đầu tiên test cho mọi tệp trong /usr/lib(56685), cái thứ hai chỉ trên những tệp có tên bắt đầu bằng z(147)).

Lưu ý rằng -exec test -d {} \;không giống như -type d. Đó là tương đương di động của cụ thể GNU -xtype d.


Nếu tôi hiểu câu đầu tiên của bạn, bạn đang nói rằng mỗi tệp / thư mục là một phần của "tập hợp tìm thấy" cần phải được xử lý bằng cách có một cuộc gọi hệ thống tương ứng? Hành động thực hiện cuộc gọi hệ thống này là một trong những mục tốn kém hơn, b / c một số cuộc gọi nhất định yêu cầu, ví dụ, thông tin lstat (2), phải không?
slm

@slm, tôi đang nói rằng khi nào findphải quyết định xem một tập tin có được chọn hay không, tốt hơn hết là đặt các kiểm tra không liên quan đến một tòa nhà trước.
Stéphane Chazelas

1
Các -execgiấy tờ chứng minh là khá đẹp :)
Bernhard
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.