zeux / qgrep

Fast regular expression grep for source code with incremental index updates
MIT License
322 stars 41 forks source link

[FIXED] Windows binary #4

Closed sergeevabc closed 7 years ago

sergeevabc commented 7 years ago

Dear Arseny, Could you be so kind to generate .exe for the rest of us who are merely users w/o compiler?

zeux commented 7 years ago

https://github.com/zeux/qgrep/releases/tag/v1.0

sergeevabc commented 7 years ago

Steps to improve.

  1. Depends on qgrep.dll, standalone .exe is preferred.
  2. Not portable as saves .cfg to user profile, current folder is preferred.
  3. Breaks on names with non-ASCII chars.
    Error reading file D:/Lyrics/Lucho Gatica - Moliendo Café.txt
    Error reading file D:/Lyrics/Melotron - Brüder.txt
    Error reading file D:/Lyrics/Natasha St. Pier - Tiens Moi À La Vie.txt
  4. Garbles Russian names when codepage is not 1251, conversion to current codepage is preferred.
    
    chcp 866 (default for Windows with Russian locale)
    D:/Lyrics/╠єч√ър/Scooter - Let me be your valentine.txt

chcp 1251 D:/Lyrics/Музыка/Scooter - Let me be your valentine.txt

chcp 65001 D:/Lyrics/������/Scooter - Let me be your valentine.txt

5. Repeats filename for each match, grouping should be available as well (like [sift][3], [ripgrep][1] or [astrogrep][2]).

d:/Dic/OxfordThesaurus.txt:845: love is a solace to him. d:/Dic/OxfordThesaurus.txt:1811: Christ, the Lord! 3 love, be in love with, cherish, fancy, d:/Dic/OxfordThesaurus.txt:1972: was truly a dull affair. 4 Also, affaire. love affair, amour,

D:\Dic\OxfordThesaurus.txt 845: love is a solace to him. 1811: Christ, the Lord! 3 love, be in love with, cherish, fancy, 1972: was truly a dull affair. 4 Also, affaire. love affair, amour,

6. Match counting is confusing (e.g. 1 string, but 2 “love” within), more verbose stats are preferred.

qgrep.exe search dic2 iS \blove\b d:/Dic2/OxfordThesaurus.txt:1811: Christ, the Lord! 3 love, be in love with, cherish, fancy, Search complete, found 2 matches in 1 line



[1]: http://blog.burntsushi.net/ripgrep/
[2]: http://astrogrep.sourceforge.net/
[3]: https://sift-tool.org/
zeux commented 7 years ago
  1. The DLL is there for the Vim plugin. I could have a separate standalone executable with some project reshuffling I guess - not sure how important that is.

  2. It's very much intentional - current folder is a very unsafe choice by default. The tools is meant to be used indirectly by integrating it into Visual Studio or Vim or other editors/IDEs, and to be used in a current directory-agnostic manner. Something interesting to consider though is a mode where if you don't specify a project name (will have to figure out how that works command line-wise), qgrep scans the ancestry of the current folder for a .cfg file.

  3. Yeah, the tool is basically made for source code trees so it kinda ignores the Unicode issues completely. This one is definitely something I need to fix though.

  4. This is a bit complicated because by default you just can't print an arbitrary file name to console and preserve it. There's also some complexity with running the tool from other programs that I'm not quite sure of - that is, what happens when you run qgrep from something other than the terminal? Not super worried about this one but may need some investigation.

  5. Noted, I'll check it out - the format matches that of grep but in some cases it may be preferable to have a combined format

  6. I mean, it's technically correct, no? :) I'm not sure what exactly you expected in this case?

sergeevabc commented 7 years ago
  1. I mean, it's technically correct, no? :) I'm not sure what exactly you expected in this case?
qgrep.exe search dic2 iS \blove\b
d:/Dic2/OxfordThesaurus.txt:1811:  Christ, the Lord!  3 love, be in love with, cherish, fancy,
Search complete, found 2 matches in 1 line
                                 ^^^^^^^^^ missing (suggested) part

Also would be convenient to get available projects’ list like qgrep.exe list.

zeux commented 7 years ago

Ah, I see. The number of matches printed right now is the line count; finding the correct number involves doing extra matching (that is already done in the highlight mode though).

The list of projects can be retrieved via qgrep projects (which isn't mentioned in README but is mentioned in qgrep help).

sergeevabc commented 7 years ago

Consider trying Zstandard for index compression as well.

zeux commented 7 years ago

zstd has very different tradeoffs that don't seem to match qgrep workload that well. From briefly trying it out, the data pack goes from 156 MB to 120 MB when using zstd level 9, the pack takes ~2x longer to build from scratch on hot data, and, most importantly, the search gets ~2x slower on hot data, so it only would really help on HDD (where read speeds are below zstd decompression speeds) with cold cache but not that much since the data is not that much smaller.

sergeevabc commented 7 years ago

@Bulat-Ziganshin, since you use Zstandard in Freearc Next, feedback by @zeus could be of value.

Bulat-Ziganshin commented 7 years ago

@sergeevabc, in my program, ztsd isn't a one-size-fits-all solution. it's just one of ~15 algos, including lz4, used in various combinations. zstd greatly fits two niches: very fast compression with reasonable compression ratio (unlike lz4) and very fast extraction, and supposed to replace my own tornado that had the same goals

@zeux, compared to lz4, i pretty sure that you can find level (6 or 7) that is 2x faster than 9, still compressing better than maximum-compressing-lz4. also take time to learn compression parameters and tune method to better fit your data. decompression speed can be increased well above 1 GB/s by employing all cores. pzstd employs multiple cores for compression and decompression, hopefully this code can be reused in your project.

zeux commented 7 years ago

@Bulat-Ziganshin Well, the data above is from matching levels; you can switch to another level on zstd but you can also switch to another level on lz4hc (in fact I did yesterday).

The killer is really decompression speeds. I already use all available cores to decompress, the data above includes that. As mentioned, it's just a very different workload - I care less about the compression ratio, in fact I only care about it to the extent it makes loading data from disk or from file system cache (more important!) faster. For me decompression is basically almost always the bottleneck so I can't compromise on decompression speeds.

sergeevabc commented 7 years ago

@zeux, а генерация индекса вообще стоит того? Скажем, обсчитав библиотеку текстов в 1 ГиБ получаем индекс размером ~500 МиБ. Греп по индексу занимает около секунды, а греп без индекса (ripgrep, sift, etc) ну чуть дольше.

zeux commented 7 years ago

Стоит ли того генерация индекса или генерация сжатого индекса? Все зависит от данных и от запроса, я могу посмотреть нет ли чего очевидного улучшить на указанном workload. Вообще библиотека рассчитана на исходный текст, например по ядру Линукса поиск ripgrep-ом на горячем кеше файловой системы литерала "fOO" (которого в тексте нет) занимает 0.58 секунд, а qgrep-ом - 0.07. Этот конкретный литерал слишком короткий и поэтому отключает некоторые другие оптимизации, с которыми разница еще более значительная.

Ну и если кеш холодный, то в qgrep загружается один файл (в случае linux - ~150 MB) с диска, а в ripgrep поднимается вся структура папок и каждый файлик, и это занимает очень долго даже на SSD (десятки секунд).

Очевидно индекс надо обновлять и получается tradeoff, я сейчас работаю над демоном который будет автоматически обновлять индекс при изменениях в файлах чтобы об этом не думать.

zeux commented 7 years ago

Ну и конечно qgrep написан достаточно давно, ripgrep сильно сокращает разрыв :) на небольших проектах наверное qgrep не очень нужен если есть ripgrep.

zeux commented 7 years ago

Вот на таком запросе например:

copy_from_user.*msgbuf

ripgrep возвращает 2 результата за 0.58 sec, qgrep - 0.02 sec...

Короче зависит. Ключевой use case для qgrep - встроенный в редактор быстрый поиск по всему исходному коду когда этого кода - десятки-сотни мегабайт. Например поэтому есть DLL версия, чтобы в Vim plugin не тратить время на запуск процесса :)

Bulat-Ziganshin commented 7 years ago

мой 1 GB/s посчитан для проца уровня 4770, и главное - относительно распакованных данных. если считать относительно запакованных, то может получиться и меньше 500 МБ/с. в целом, мне кажется те кто работает с базами такого объёма, могут позволить себе лишние 30% в размере небольшого по сравнению с codebase индекса даже ради небольшого ускорения поиска

далее

  1. посмотрите lz5, там есть режим "улучшенного lz4"
  2. для usecases где база распаковывается только один раз при старте программы и дальше висит в памяти, может быть оптимален алгоритм с макс. сжатием типа lzma. его скорость распаковки порядка 100 МБ/с относительно распакованных данных. или можно взять тот же lz5, благо что в нём есть всякие режимы, а API на всех одно
  3. для макс. сжатия может оказаться выгоден ещё blocksorting алгоритм типа bsclib. распаковка там не быстрее lzma-шной
  4. улучшение сжатия часто можно достичь небольшим препроцессингом, почти не влияющим на время распаковки, таким как словарная замена. в вашем случае посмотрите, нет ли возможности улучшить сжатие заменой чисел в таблицах на приращение к предыдущему элементу. delta filter в arc/fa делает это автоматом, хотя и не всегда справляется со сложными случаями, но может быть использован как "быстрый тест"
  5. ещё один lz оптимизированный на макс. сжатие + быструю распаковку: http://encode.ru/threads/2427-GLZA aka https://github.com/jrmuizel/GLZA
zeux commented 7 years ago

в целом, мне кажется те кто работает с базами такого объёма, могут позволить себе лишние 30% в размере небольшого по сравнению с codebase индекса даже ради небольшого ускорения поиска

Да, примерно поэтому LZ4 - как я уже писал выше, сжатие важно только настолько насколько оно позволит быстрее читать данные. Например, если считать что LZ4HC разжимается 2 GB/s, а сжимает в 4-5 раз (примерный коэффициент на моих данных, это исходный код на разных языках), то получается очень заметный выигрыш при считывании даже с быстрого SSD (но конечно из памяти все равно быстрее читать без сжатия...)

В основном сжимаемые данные это текст, таблиц с числами там очень мало.