RtlCompressBuffer и LZNT1 - Как подобрать размер вых. буфера
От: sergey77666 Марс  
Дата: 13.01.18 08:14
Оценка:
Пишу функцию — обертку для RtlCompressBuffer, которая позволит максимально упростить код и ускорить написание.

Вот в RtlCompressBuffer очень не нравится, что размер выходного буфера ты подбираешь сам от какой-то балды, типа "с запасом".

Просто сделать его равным входному буферу — не вариант — выходной может оказаться больше входного в неудачном случае (если входной всего несколько байт или вовсе 0 байт). Или не может?

Как быть? Если тупо умножить размер входного в несколько раз (забив на экономию ресурсов), то во сколько?

Сделать так, как это делается обычно (предварительно вызвать функцию с нулевым буфером, чтобы вернуть результат) именно нельзя, судя по всему.
Отредактировано 13.01.2018 8:27 sergey77666 . Предыдущая версия . Еще …
Отредактировано 13.01.2018 8:27 sergey77666 . Предыдущая версия .
Re: RtlCompressBuffer и LZNT1 - Как подобрать размер вых. буфера
От: Alexander G Украина  
Дата: 13.01.18 08:35
Оценка:
Здравствуйте, sergey77666, Вы писали:

S>Вот в RtlCompressBuffer очень не нравится, что размер выходного буфера ты подбираешь сам от какой-то балды, типа "с запасом".


S>Просто сделать его равным входному буферу — не вариант — выходной может оказаться больше входного в неудачном случае (если входной всего несколько байт или вовсе 0 байт). Или не может?


Функция существует для файловой системы, чтобы сжимать куски FILE_ATTRIBUTE_COMPRESSED-файла на лету.

Файл разбивается на куски равного размера, каждый сжимается, если какой-то не сжался, то он записывается несжатым; какие из кусков сжаты, какие нет — обрабатывается на уровне файловой системы.

Соответственно, самый простой способ вызвать функцию правильно — создать FILE_ATTRIBUTE_COMPRESSED файл
Русский военный корабль идёт ко дну!
Re[2]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: sergey77666 Марс  
Дата: 13.01.18 08:39
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, sergey77666, Вы писали:


S>>Вот в RtlCompressBuffer очень не нравится, что размер выходного буфера ты подбираешь сам от какой-то балды, типа "с запасом".


S>>Просто сделать его равным входному буферу — не вариант — выходной может оказаться больше входного в неудачном случае (если входной всего несколько байт или вовсе 0 байт). Или не может?


AG>Функция существует для файловой системы, чтобы сжимать куски FILE_ATTRIBUTE_COMPRESSED-файла на лету.


AG>Файл разбивается на куски равного размера, каждый сжимается, если какой-то не сжался, то он записывается несжатым; какие из кусков сжаты, какие нет — обрабатывается на уровне файловой системы.


AG>Соответственно, самый простой способ вызвать функцию правильно — создать FILE_ATTRIBUTE_COMPRESSED файл


Не пойдет.

Хотя, тут уже хочется взять и самому реализовать LZ77. С одной стороны, стоит, это выгоднее за счет портабельности. С другой стороны, а не лучше ли тогда какой другой реализовать, более совместимый с компрессорами\декомпрессорами?) Свободного времени, строго говоря, 0 секунд, и так будет всегда.
Отредактировано 13.01.2018 8:41 sergey77666 . Предыдущая версия .
Re[3]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: Alexander G Украина  
Дата: 13.01.18 09:10
Оценка:
Здравствуйте, sergey77666, Вы писали:

S>Хотя, тут уже хочется взять и самому реализовать LZ77. С одной стороны, стоит, это выгоднее за счет портабельности. С другой стороны, а не лучше ли тогда какой другой реализовать, более совместимый с компрессорами\декомпрессорами?) Свободного времени, строго говоря, 0 секунд, и так будет всегда.


Может, взять zlib? Он работает в таком широком диапазоне окружений, не думаю, что не заработает в Windows-драйвере.

Судя по исходникам, там даже допиливать ничего не надо, собрать с Z_SOLO, и он не зависит даже на malloc/free (использует переданные извне)
Русский военный корабль идёт ко дну!
Re: RtlCompressBuffer и LZNT1 - Как подобрать размер вых. буфера
От: Pzz Россия https://github.com/alexpevzner
Дата: 13.01.18 09:34
Оценка:
Здравствуйте, sergey77666, Вы писали:

S>Просто сделать его равным входному буферу — не вариант — выходной может оказаться больше входного в неудачном случае (если входной всего несколько байт или вовсе 0 байт). Или не может?


Мне кажется, что если конкретно у этого куска данных результат компрессии оказался больше входных данных, то может конкретно этот кусок и не стоит компрессировать?
Re[2]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: sergey77666 Марс  
Дата: 13.01.18 09:42
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, sergey77666, Вы писали:


S>>Просто сделать его равным входному буферу — не вариант — выходной может оказаться больше входного в неудачном случае (если входной всего несколько байт или вовсе 0 байт). Или не может?


Pzz>Мне кажется, что если конкретно у этого куска данных результат компрессии оказался больше входных данных, то может конкретно этот кусок и не стоит компрессировать?


Я против таких "призраков" в архитектуре.
Слово "призрак" можно определить как неочевидную, редко проявляющуюся особенность формата.
Понятно, что по идее достаточно просто описать ее в документации, но на деле всегда есть шанс, что этому не внемлют, сделают эмпирически, пройдет сотню тестов, а потом упадет в океан.
Отредактировано 13.01.2018 9:43 sergey77666 . Предыдущая версия .
Re[4]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: sergey77666 Марс  
Дата: 13.01.18 09:45
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, sergey77666, Вы писали:


S>>Хотя, тут уже хочется взять и самому реализовать LZ77. С одной стороны, стоит, это выгоднее за счет портабельности. С другой стороны, а не лучше ли тогда какой другой реализовать, более совместимый с компрессорами\декомпрессорами?) Свободного времени, строго говоря, 0 секунд, и так будет всегда.


AG>Может, взять zlib? Он работает в таком широком диапазоне окружений, не думаю, что не заработает в Windows-драйвере.


AG>Судя по исходникам, там даже допиливать ничего не надо, собрать с Z_SOLO, и он не зависит даже на malloc/free (использует переданные извне)


Кстати, у zlib та же история с буфером, но в доках написано, как считать размер.
Re[3]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: Pzz Россия https://github.com/alexpevzner
Дата: 13.01.18 09:52
Оценка: 1 (1)
Здравствуйте, sergey77666, Вы писали:

Pzz>>Мне кажется, что если конкретно у этого куска данных результат компрессии оказался больше входных данных, то может конкретно этот кусок и не стоит компрессировать?


S>Я против таких "призраков" в архитектуре.

S>Слово "призрак" можно определить как неочевидную, редко проявляющуюся особенность формата.

Вот так во имя архитектурной чистоты народ готов сделать заведомое ухудшение. Некоторые данные принципиально не поддаются компрессии (например, зашифрованные данные, вообще, любая псевдослучайная последовательность). Принудительно "компрессировать" их — только раздувать объем выходных данных, и увеличивать время декомпрессии.

Тут надо просто к каждому блоку добавлять явный признак, компрессирован он или нет. Поскольку в этот признак все равно надо что-то писать, то трудно себе представить, что туда запишут константу, не посмотрев.

Собственно, обертка к компрессору может это и делать. Тогда ей всегда достаточно выходного буфера, который на байт больше входного — этот байт и будет признаком.

S>Понятно, что по идее достаточно просто описать ее в документации, но на деле всегда есть шанс, что этому не внемлют, сделают эмпирически, пройдет сотню тестов, а потом упадет в океан.


Если полагаться только на тесты, а голову не включать, всегда так и будет.
Re[4]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: sergey77666 Марс  
Дата: 13.01.18 09:54
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Собственно, обертка к компрессору может это и делать. Тогда ей всегда достаточно выходного буфера, который на байт больше входного — этот байт и будет признаком.


Но тогда ее придется называть Алгоритм cжатия Сергея-77666™.
Потому что если ее назвать LZNT1, то это будет неверно — декомпрессор LZNT1 не сможет с ее выводом работать из-за этого байта.
Отредактировано 13.01.2018 9:56 sergey77666 . Предыдущая версия . Еще …
Отредактировано 13.01.2018 9:56 sergey77666 . Предыдущая версия .
Отредактировано 13.01.2018 9:55 sergey77666 . Предыдущая версия .
Отредактировано 13.01.2018 9:54 sergey77666 . Предыдущая версия .
Re[5]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: Pzz Россия https://github.com/alexpevzner
Дата: 13.01.18 10:10
Оценка:
Здравствуйте, sergey77666, Вы писали:

Pzz>>Собственно, обертка к компрессору может это и делать. Тогда ей всегда достаточно выходного буфера, который на байт больше входного — этот байт и будет признаком.


S>Но тогда ее придется называть Алгоритм cжатия Сергея-77666™.

S>Потому что если ее назвать LZNT1, то это будет неверно — декомпрессор LZNT1 не сможет с ее выводом работать из-за этого байта.

Если мы говорим именно о компрессии файлов в драйвере виртуальной файловой системы, все равно надо как-то seek обеспечивать. Сам по себе LZNT1, я полагаю, этого не делает (нельзя прочитать кусок из середины, можно читать только от начала до конца). Поэтому дополнительные данные (и их самодельный формат) все равно потребуются. А если так, там найдется и место для признака.
Re[6]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: sergey77666 Марс  
Дата: 13.01.18 10:18
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Если мы говорим именно о компрессии файлов в драйвере виртуальной файловой системы


Интересно, почему вы об этом говорите? Я говорю о просто драйвере.
Re: RtlCompressBuffer и LZNT1 - Как подобрать размер вых. буфера
От: wildwind Россия  
Дата: 13.01.18 12:12
Оценка:
Здравствуйте, sergey77666, Вы писали:

S>Вот в RtlCompressBuffer очень не нравится, что размер выходного буфера ты подбираешь сам от какой-то балды, типа "с запасом".


КО подсказывает, что это особенность алгоритма.

S>Просто сделать его равным входному буферу — не вариант — выходной может оказаться больше входного в неудачном случае


Как раз вариант. Если сжатые данные оказались больше несжатых — нет смысла их сжимать вообще.
Re[2]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых. буфера
От: sergey77666 Марс  
Дата: 13.01.18 17:29
Оценка:
Здравствуйте, wildwind, Вы писали:

W>КО подсказывает, что это особенность алгоритма.


А практика опровергает это, ведь та же "особенность" есть и в упомянутой zlib.
Но только там в доках написано, как считать размер этого буфера, а тут нет.

W>Как раз вариант. Если сжатые данные оказались больше несжатых — нет смысла их сжимать вообще.


Это жуткий бардак, когда функция-обертка то возвращает сжатые данные, то несжатые и тебе приходится как-то это обрабатывать уже на прикладном уровне, когда написание драйверов и так отнимает очень много времени.
Re[3]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых. буфера
От: wildwind Россия  
Дата: 14.01.18 04:06
Оценка:
Здравствуйте, sergey77666, Вы писали:

W>>КО подсказывает, что это особенность алгоритма.

S>А практика опровергает это, ведь та же "особенность" есть и в упомянутой zlib.

Так и я о том же, эта особенность будет присутствовать в любой реализации.

S>Но только там в доках написано, как считать размер этого буфера, а тут нет.


Претензии к докам это другой вопрос. Реализация MS проприетарная, может меняться, поэтому написать "считайте так и не ошибетесь" нельзя.

S>Это жуткий бардак, когда функция-обертка то возвращает сжатые данные, то несжатые и тебе приходится как-то это обрабатывать уже на прикладном уровне, когда написание драйверов и так отнимает очень много времени.


Ты хочешь сказать, что время написания драйвера для тебя на первом месте, а эффективность его работы на втором?
Кстати, зачем это обрабатывать на прикладном уровне, драйвер сам с этим не справится?
Re[4]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: sergey77666 Марс  
Дата: 14.01.18 04:29
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Претензии к докам это другой вопрос.

Ну так надо что-то делать.

W>Ты хочешь сказать, что время написания драйвера для тебя на первом месте, а эффективность его работы на втором?

Конечно.
Спорить насчет ахуенной необходимости оптимизации каждого КБ на диске (даже не в ОЗУ!) лучше советую пойти в MS, Google и т.д. Там полено, а тут соринка.

Если продукт реально нужен, то все равно первая прибыль будет, а вот с нее уже и оптимизировать.

Заказчик мне ни гроша не доплатит за эти сэкономленные КБ, а вот сэкономленное время от нескольких минут до несколько часов (столько набежит за время сопровождения этого кода, т.к. лишняя фигота будет грузить твой мозг каждый раз, как будешь работать с этим участком) — это не так и мало.

W>Кстати, зачем это обрабатывать на прикладном уровне, драйвер сам с этим не справится?

Вы не так поняли (вообще сложно вписать архитектуру любой современной системы в любую иерархию — например, в клиент-сервере над якобы прикладным протоколом HTTP может оказаться еще с 5 протоколов, и какие — они?)
Имел в виду — нужно как-то обрабатывать не в самой обертке, а на уровне драйвера ее использующего (обертка — часть фреймворка), т.е. при записи таких сжатых данных в файл придется добавлять дополнительный байт, который будет указывать сжатые там данные или нет.
А еще сжатие можно использовать как "псевдо-шифрование": легкую защиту от "хацкеров" это дает, тем более LZNT1 достаточно атипичен, — а если данные будут лететь несжатыми, то мы это потеряем.
Отредактировано 14.01.2018 4:36 sergey77666 . Предыдущая версия . Еще …
Отредактировано 14.01.2018 4:32 sergey77666 . Предыдущая версия .
Отредактировано 14.01.2018 4:32 sergey77666 . Предыдущая версия .
Отредактировано 14.01.2018 4:31 sergey77666 . Предыдущая версия .
Re[5]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: wildwind Россия  
Дата: 14.01.18 05:08
Оценка:
Здравствуйте, sergey77666, Вы писали:

S>Заказчик мне ни гроша не доплатит за эти сэкономленные КБ


Ты начинаешь противоречить сам себе. Если это так, то зачем ты вообще цепляешься за это сжатие? Откажись от него, все резко упростится и время сэкономишь.
Re[6]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: sergey77666 Марс  
Дата: 14.01.18 06:34
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Здравствуйте, sergey77666, Вы писали:


S>>Заказчик мне ни гроша не доплатит за эти сэкономленные КБ


W>Ты начинаешь противоречить сам себе. Если это так, то зачем ты вообще цепляешься за это сжатие? Откажись от него, все резко упростится и время сэкономишь.


Нет, сжатие нужно, оно было в ТЗ и пользы от него в целом в большинстве случае больше..
А вот требование не сжимать, если плохо получается — это уже редкость и специфика, та же обертка может иметь дополнительную опцию для этого, но необязательно.
Re[5]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: Alexander G Украина  
Дата: 14.01.18 08:25
Оценка:
Здравствуйте, sergey77666, Вы писали:

S>Кстати, у zlib та же история с буфером, но в доках написано, как считать размер.


Вообще есть ещё такой приём: вызывать в цикле, увеличивая буфер в несколько раз, например в полтора.
Жутко неэффективен на гипотетический патологический случай, в реальности же вряд ли сжатие даст увеличение более чем в полтора раза, так что никакого цикла не будет.
Русский военный корабль идёт ко дну!
Re[6]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: sergey77666 Марс  
Дата: 14.01.18 09:02
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, sergey77666, Вы писали:


S>>Кстати, у zlib та же история с буфером, но в доках написано, как считать размер.


AG>Вообще есть ещё такой приём: вызывать в цикле, увеличивая буфер в несколько раз, например в полтора.

AG>Жутко неэффективен на гипотетический патологический случай, в реальности же вряд ли сжатие даст увеличение более чем в полтора раза, так что никакого цикла не будет.

Жестко как. Не додумался бы до такого изврата)
А еще говорят, что я рас...яй и никаким перфекционизмом и не пахнет.
Отредактировано 14.01.2018 9:02 sergey77666 . Предыдущая версия .
Re[7]: RtlCompressBuffer и LZNT1 - Как подобрать размер вых.
От: Alexander G Украина  
Дата: 14.01.18 09:36
Оценка:
Здравствуйте, sergey77666, Вы писали:

S>Жестко как. Не додумался бы до такого изврата)

S>А еще говорят, что я рас...яй и никаким перфекционизмом и не пахнет.

Для некоторых случаев именно вариант с циклом — перфекционизм.
Причём даже если есть способ знать заранее сколько надо.
Это когда результаты не обязательно повторяются.

Например, получаем строку из реестра. Можно сначала спросить размер строки, потом выделять буфер.
Но если кто-то вот именно сейчас редактирует реестр, и удлинение будет между вызовами?
Тут, правда, не нужно увеличивать от балды, предыдущая попытка вернёт, сколько теперь надо, но всё равно, без цикла совершенного решения нет.
Русский военный корабль идёт ко дну!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.