|
10 | 10 | А я ожидал, что результат уже должен быть лучше аналогов. Тем более, что у меня специализированный алгоритм,
|
11 | 11 | а у grep синтаксис иной и алгоритм по определению хуже должен быть.
|
12 | 12 |
|
13 |
| -Потом я заменил алгоритм матча строки с динамическим программированием и памятью O(P*N) на другой, более быстрый и с константной памятью. |
14 |
| -И... я стал медленнее grep всего в 2 раза. Почти успех :))) При этом по профайлеру релизному у меня 80+% проводилось именно в матче строк. |
| 13 | +Потом я заменил алгоритм матча строки с динамическим программированием и памятью O(P*N) на другой, |
| 14 | +более быстрый и с константной памятью. И... я стал медленнее grep всего в 2 раза. Почти успех :))) |
| 15 | +При этом по профайлеру релизному у меня 80+% проводилось именно в матче строк. |
15 | 16 |
|
16 | 17 | Не буду томить, сомневаюсь, что более эффективный алгоритм существует для этой задачи.
|
17 |
| -Победить grep вышло лишь добавив несколько оптимизаций, которые просто ускоренно прокручивали алгоритм в популярных сценариях. |
18 |
| -Это ускорило матчинг примерно в 6 раз, а общее время работы программы раза в 3. И эта дало победу над grep всего лишь на 25-35%. |
| 18 | +Победить grep вышло лишь добавив несколько оптимизаций, которые просто ускоренно прокручивали |
| 19 | +алгоритм в популярных сценариях. Это ускорило матчинг примерно в 6 раз, |
| 20 | +а общее время работы программы раза в 3. И эта дало победу над grep всего лишь на 25-35%. |
19 | 21 |
|
20 | 22 | После этого согласно профайлеру почти ровно половина времени проводилась
|
21 | 23 | в матче строк, а процентов под 40 времени проводилось в синхронном ReadFile().
|
22 | 24 |
|
23 | 25 | Я решил, что вот он звёздный час асинхронного чтения файлов!
|
24 | 26 | Запрограммировал, и... ничего. Общее время работы не изменилось.
|
25 |
| -Но профайлер показал перераспределение времени в сторону алгоритма матча. Очень странно, что он замедлился. Я так и не понял почему так. |
| 27 | +Но профайлер показал перераспределение времени в сторону алгоритма матча. |
| 28 | +Очень странно, что он замедлился. Я так и не понял почему так. |
26 | 29 | Я убеждён, что эти 40% можно было сжать до максимум 5% за счет параллелизации вычитки данных и их обработки.
|
27 |
| -Возможно это как-то связано с тем, что данные лежат в файловом кэше, а не читаются с диска (более короткий путь IRP). |
| 30 | +Возможно это как-то связано с тем, что данные лежат в файловом кэше, |
| 31 | +а не читаются с диска (более короткий путь IRP). |
28 | 32 | Возможно это банальное копирование памяти в kernel mode плохо параллелизуется.
|
29 | 33 | Может стоило переписать, чтобы чтение с диска в выделенном потоке выполнялось...
|
30 | 34 | Если у вас есть идеи почему так вышло или в чём ошибка, то буду рад если поделитесь.
|
31 | 35 |
|
32 | 36 | Также заметил вставку перед циклом команды nop при оптимизации по скорости компилятором.
|
33 |
| -Есть лишь предположения зачем. Если вы вдруг знаете - тоже дайте знать. Есть скриншот, приложил его в проект. |
| 37 | +Есть лишь предположения зачем. Если вы вдруг знаете - тоже дайте знать. |
| 38 | +Есть скриншот, приложил его в проект. |
34 | 39 | Я спросил моих разных коллег, они не в курсе.
|
35 | 40 |
|
36 | 41 | Попробовал на всякий случай отображать файл на память.
|
37 | 42 | Но у меня были сомнения в эффективности скорости подгрузки новых страниц в этом решении.
|
38 | 43 | Так и вышло. Немного медленнее, процентов на 20% (время всей программы).
|
39 | 44 | Хотя тоже странно при прогретом кэше.
|
40 |
| -Теоретически, если данные в кэше лежат, то можно было бы их отобразить на виртуальную память в read-only режиме за O(1), |
| 45 | +Теоретически, если данные в кэше лежат, то можно было бы их отобразить |
| 46 | +на виртуальную память в read-only режиме за O(1), |
41 | 47 | а потом экономить на переходах в kernel mode + экономить на копировании памяти.
|
42 | 48 |
|
43 | 49 | ## Тестирование и заметки
|
|
57 | 63 | В последней версии grep показывает 2.5 секунды, а моё решение - 1.6 секунды на тестовых данных.
|
58 | 64 |
|
59 | 65 | **ДОПОЛНЕНО:**
|
60 |
| -Реализовал также чтение файла в отдельном потоке. Файловая операция синхронная, синхронизация с потоком lock free (spinlock). |
61 |
| -Получил общий выигрыш в 25% относительно решения на синхронном и асинхронном API (1.2 секунды). Итого в 2 раза быстрее чем grep. |
| 66 | +Реализовал также чтение файла в отдельном потоке. Файловая операция синхронная, |
| 67 | +синхронизация с потоком lock free (spinlock). |
| 68 | +Получил общий выигрыш в 25% относительно решения на синхронном и асинхронном API (1.2 секунды). |
| 69 | +Итого в 2 раза быстрее чем grep. |
62 | 70 |
|
63 | 71 | ## Особенности реализации
|
64 | 72 |
|
65 |
| -В итоге у меня остались все три реализации чтения файлов. Я оставил асинхронную версию как самую перспективную. Переключаются так: |
| 73 | +В итоге у меня остались все три реализации чтения файлов. |
| 74 | +Я оставил асинхронную версию как самую перспективную. Переключаются так: |
66 | 75 |
|
67 | 76 | ```cpp
|
68 | 77 | #if 0
|
|
84 | 93 |
|
85 | 94 | Как и в условии задачи, основное консольное приложение собрано с отключенными исключениями и заодно без RTTI.
|
86 | 95 |
|
87 |
| -Я притянул часть STL на мой страх и риск. Ту часть, которая не требует исключений и работает без лишних накладных расходов. |
| 96 | +Я притянул часть STL на мой страх и риск. |
| 97 | +Ту часть, которая не требует исключений и работает без лишних накладных расходов. |
88 | 98 | Не вижу смысла не пользоваться дешевыми абстракциями, позволяющими писать более чистый код
|
89 | 99 | и более защищенный от ошибок программиста. И без велосипедов.
|
90 | 100 | Я имею в виду всякие std::unique_ptr, std::string_view, std::optional.
|
|
0 commit comments