Как сократить время GZIPOutputStream - PullRequest
1 голос
/ 06 мая 2019

Я попытался сжать большой (от 100 МБ до 500 МБ) XML-файл. Я создал метод Zip для этого. проблема заключается в том, что он тратит слишком много времени на сжатие. Для 200 МБ это займет 1,2 секунды. Мне нужно сократить время на 100 миллисекунд для 100 МБ файла XML. Как я могу оптимизировать, чтобы сократить время для архивирования?

Я сократил время, немного снизив степень сжатия. попробовал другие алгоритмы, такие как Snappy, Lz4, но не так много улучшений, а также они имеют плохое сжатие. Насколько мне известно, gzipOutputStream.write () занимает 85% времени. Так как я могу оптимизировать этот шаг, чтобы получить лучшую производительность без ущерба для большей части Коэффициент сжатия.

public static String zip(final String str) {
    if ((str == null) || (str.length() == 0)) {
        throw new IllegalArgumentException("Cannot zip null or empty string");
    }

    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(str.length())) {
        try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream){{def.setLevel(Deflater.BEST_SPEED );}};) {
            gzipOutputStream.write(str.getBytes(StandardCharsets.UTF_8));

        } 
            T5 = System.currentTimeMillis();
            byte[] bytes=byteArrayOutputStream.toByteArray();
             T3 = System.currentTimeMillis();

            String zipped_text=DatatypeConverter.printBase64Binary(bytes);
             T4 = System.currentTimeMillis();
            return zipped_text;

    } catch(IOException e) {
        throw new RuntimeException("Failed to zip content", e);
    }

}

1 Ответ

1 голос
/ 06 мая 2019

Вот мой совет:

  1. Создайте правильный эталонный тест, чтобы вы могли получать повторяемые результаты.Я бы посоветовал использовать систему сравнения;например, JMH.

  2. Профилируйте свой код / ​​эталон, чтобы определить, где находятся узкие места / горячие точки;например, используя jVisualVM или Java Mission Control Flight Recorder.

  3. Используйте ориентиры и результаты профилирования для руководства вашими усилиями по оптимизации.

(я бы не сталпросто полагайтесь на звонки на номер System.currentTimeMillis() по разным причинам.)

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

  • Создание входной строки, содержащей XML
  • Захват сжатых байтов в ByteArrayOutputStream
  • Относительно байтов в другую строку.

Так что если вы ищетечтобы найти способы улучшить это, попробуйте организовать вещи так, чтобы сериализатор XML записывал в конвейер, который передает данные посредством преобразования gzip и base64, а затем записывал непосредственно в поток файла или сокета.

Кроме того, я бы не использовалbase64 если возможно.Если сжатый XML находится в ответе HTTP, вы должны быть в состоянии отправить его в двоичном виде.Это будет быстрее и генерирует значительно меньше сетевого трафика.

Наконец, выберите алгоритм сжатия, который дает хороший компромисс между степенью сжатия и временем сжатия.


Как можноЯ оптимизирую этот шаг, чтобы повысить производительность без ущерба для степени сжатия.

Если вы пытаетесь это сделать, ваши цели, вероятно, неверны.(И почему вы тогда Base64 закодировали сжатый файл? Это противоречит вашей цели!)


Обновления с учетом ваших комментариев:

  1. Вы будете (я думаю,) добиться большей производительности за счет потоковой передачи, чем за счет преобразования XML в строку и последующего вызова getBytes().Для начала, вызов getBytes() делает ненужную копию содержимого строки.

  2. Страница Википедии на Сжатие без потерь ссылается на ряд алгоритмов,многие из которых должны иметь легкодоступные реализации Java.Кроме того, он имеет ссылки на ряд тестов.Я не смотрел ссылки на эталонные тесты, но ожидаю, что по крайней мере один из них даст количественную оценку соотношения сжатия и времени вычислений для различных алгоритмов.

  3. Если вы измените таблицу базы данных с CLOBв BLOB:

    • вы можете обойтись без base64, сэкономив ~ 25% памяти
    • вы можете обойтись без шага кодирования base64, сэкономив несколько процентов CPU
    • затем вы можете выбрать более быстрый (но менее компактный) алгоритм, сэкономив больше времени за счет части сэкономленного пространства, перейдя в BLOB.
  4. «Я не могу изменить это в соответствии с требованиями бизнеса». - Правда?Если схема базы данных является бизнес-требованием, то с вашим бизнесом что-то действительно облажалось.С другой стороны, если бизнес диктует технологии на этом уровне, то они также диктуют производительность.

    Нет веских технических причин для сохранения сжатых данных в виде CLOB.

  5. Как кто-то заметил, самый простой способ получить более быстрое сжатие - это купить более быстрый компьютер.Или (моя идея) банк компьютеров, чтобы вы могли сжимать несколько файлов параллельно.

...