Чому GNU знаходить так швидко порівняно з утилітами пошуку графічних файлів?


47

Я намагаюся знайти файл, який не існує в моєму домашньому каталозі та всіх підкаталогах.

find ~/ -name "bogus"дає мені цю інформацію через кілька секунд, але менеджеру файлів KDEdolphin потрібно було майже 3 хвилини, щоб зробити те саме. Це відповідає моєму попередньому досвіду роботи з GNOMEbeagle .

Як же findвдається зробити те ж саме дуже швидко, коли графічний пошук (який є більш інтуїтивним у використанні, ніж параметри командного рядка) пробує позаду?


Я не знаю, що таке "Дельфін", але, можливо, він також загляне всередину файлів?
Кусалаланда

1
Це графічний файловий менеджер від KDE: kde.org/applications/system/dolphin. Він має можливість пошуку у файлах, але я не ввімкнув цю опцію під час цього короткого тесту.
Червоний

9
Ви не раз шукали дельфінів? Це може бути "індексування" в перший раз. І "пошук" теж повільний. Спробуйте "знайти", якщо файл старіший за останній раз, коли індексувалася база даних для пошуку ;-)
Rinzwind

Я користуюся locateчастіше, ніж findце швидше, і у величезній папці
phuclv

11
Хоча locateце справді чудово для пошуку файлів, це трохи ОТ, оскільки він використовує зовсім інший підхід: findі такі інструменти графічного інтерфейсу, як Dolphinтрафік, переходять до дерева файлів на вимогу, locateвикористовуючи раніше створену структуру індексу.
Майкл Шаферс

Відповіді:


68

Дивлячись на Дельфіна з Baloo, схоже, шукає метадані кожного файлу в його пошуковому домені, навіть якщо ви робите простий пошук імені файлів. Коли я простежити file.soпроцес, я бачу виклики до lstat, getxattrі getxattrзнову для кожного файлу, і навіть для ..записів. Ці системні виклики отримують метадані про файл, який зберігається в іншому місці від імені файлу (ім'я файлу зберігається у вмісті каталогів, але метадані знаходяться у inode ). Запит на метадані файлу кілька разів є дешевим, оскільки дані знаходяться в кеш-диску диска, але може бути значна різниця між запитом метаданих і не запитом метаданих.

findнабагато розумніший. Він намагається уникати зайвих системних дзвінків. Він не дзвонить, getxattrоскільки не здійснює пошук на основі розширених атрибутів. Під час проходження каталогу, можливо, знадобиться викликати lstatневідповідні імена файлів, тому що це може бути підкаталог для рекурсивного пошуку ( lstatце системний виклик, який повертає метадані файлів, включаючи тип файлу, такий як звичайний / каталог / symlink /…). Однак findє оптимізація: вона знає, скільки підкаталогів має каталог з його кількості посилань , і він припиняє дзвінки, lstatяк тільки знає, що пройшов усі підкаталоги. Зокрема, у довідковому каталозі (каталог без підкаталогів)findперевіряє лише імена, а не метадані. Крім того, деякі файлові системи зберігають копію типу файлу у записі каталогу, так що findнавіть не потрібно дзвонити, lstatякщо це єдина інформація, яка йому потрібна.

Якщо ви працюєте findз параметрами, які потребують перевірки метаданих, вона здійснюватиме більше lstatдзвінків, але він все одно не здійснюватиме lstatвиклик у файлі, якщо йому не потрібна інформація (наприклад, тому що файл виключений попередньою умовою відповідність назви).

Я підозрюю, що інші інструменти пошуку GUI, які винаходять findколесо, менш розумні, ніж утиліта командного рядка, яка зазнала десятиліть оптимізації. Принаймні, дельфін досить розумний, щоб використовувати базу даних locate, якщо ви шукаєте "скрізь" (з обмеженням, яке в інтерфейсі не зрозуміло, що результати можуть бути застарілими).


22
Знайти GNU настільки "розумно", що він пропускає деякі файли в деяких типах файлової системи. Добре відома помилка в GNU полягає в тому, що це робить незаконне припущення, що кількість посилань каталогів є. 2 + number of sub-directories.Це працює для файлових систем, які реалізують помилку дизайну з файлової системи UNIX V7, але не для всіх файлових систем, оскільки це не вимога POSIX . Якщо ви хочете отримати корисний номер продуктивності для GNU, вам потрібно вказати -noleafна замовлення, щоб сказати GNU make поводитись правильно.
шилі

12
@schily, GNU, findможливо, мав цю помилку давно, але я сумніваюся, що ви знайдете випадок, коли вам зараз потрібно вказати -noleafвручну. AFAICT, на Linux , по крайней мере getdents()(і ReadDir ()) вказує , які файли є файлами каталогу на UDF, ISO-9660, Btrfs , які не мають реальних .або ..записи і findповодиться нормально там. Чи знаєте ви один випадок, коли GNU findвиявляє проблему?
Стефан Шазелас

4
Просто використовуйте цей гнилий genisoimage від debian, щоб створити файлову систему Rock Ridge з використанням "graft-points", і кількість посилань у каталозі є випадковим значенням. Оскільки Rock Ridge реалізує кількість посилань та. / .., GNU find зазвичай не знайде всіх файлів у такій файловій системі.
шилі

4
@ StéphaneChazelas: Востаннє, коли я перевіряв (на магістерську дисертацію), помилка була виправлена, стверджуючи, що саме 2 означали відомий лист, а не <= 2. Файлові системи, які не реалізують лічильник 2+, повертають 1 для кількості посилань на каталог, так все добре. Тепер, якщо одного дня хтось створив файлову систему, яка робила жорсткі посилання на каталоги, які не мали цього властивості, у когось буде поганий день.
Джошуа

15
@schily, я не зміг отримати підрахунок випадкових посилань з точками трансплантата та RR з genisoimage 1.1.11 на Debian, і навіть якщо я бінарний редагувати зображення iso, щоб змінити кількість посилань на випадкові значення, я все ще не бачу жодного проблема з GNU find. І в будь-якому випадку, strace -vпоказує, що getdents()правильно повертає d_type = DT_DIR для каталогів, тому GNU знахідки не повинні використовувати трюк підрахунку посилань.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.