Читаем Crystal Programming. Введение на основе проекта в создание эффективных, безопасных и читаемых веб-приложений и приложений CLI полностью

Теперь, когда и наш процессор, и типы преобразования используют IO, мы можем сделать еще одну оптимизацию. Текущая логика преобразования использует метод класса .parse в соответствующем модуле формата. Этот метод очень удобен, но имеет один главный недостаток: он загружает все входные данные в память. Возможно, это не проблема для небольших тестов, которые мы проводили, но представьте себе, что вы пытаетесь преобразовать гораздо более крупные файлы/входные данные? Вполне вероятно, что это приведет к тому, что наше приложение будет использовать много (и, возможно, исчерпать) памяти.

К счастью для нас, JSON и, как следствие, YAML являются форматами потоковой сериализации. Другими словами, вы можете переводить один формат в другой по одному символу за раз, не загружая все данные заранее. Как упоминалось ранее, это одно из основных преимуществ создания нашего приложения на основе IO. Мы можем использовать это, обновив нашу логику преобразования для вывода преобразованных выходных данных, одновременно анализируя входные данные. Начнем с метода .deserialize в src/yaml.cr. Код этого метода довольно длинный, его можно найти на Github по адресу https://github.com/PacktPublishing/Crystal-Programming/blob/main/Chapter05/yaml_v2.cr.

Здесь много всего происходит, поэтому давайте немного разберем алгоритм:

1. Мы начинаем использовать некоторые новые типы в модуле каждого формата вместо того, чтобы оба они полагались на метод .parse:

YAML::PullParser позволяет использовать входной токен YAML токеном по требованию, поскольку данные доступны из типа входного IO. Он также предоставляет метод, который возвращает тип токена, который он анализирует в данный момент.

JSON::Builder, с другой стороны, используется для создания JSON с помощью объектно-ориентированного API, записывая JSON в выходной тип IO.

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

Метод .serialize следует той же общей идее: код также доступен на Github в том же файле.

Однако в этом случае алгоритм существенно обратный. Мы используем анализатор JSON и построитель YAML. Давайте проведем тест и посмотрим, насколько это помогло.

<p>Тестирование производительности</p>

Для тестирования я буду использовать реализацию GNU утилиты time с опцией -v для подробного вывода. В качестве входных данных я буду использовать файл invItems.yaml, который можно найти в папке этой главы на GitHub. Входные данные не имеют особого значения, если они представлены в формате YAML, но я выбрал эти данные, потому что они довольно большие — 53,2 МБ. Чтобы выполнить тест, мы выполним следующие шаги:

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

2. Соберите двоичный файл в режиме выпуска с помощью shards build --release. Поскольку мы хотим протестировать производительность нашего приложения, а не jq, мы просто будем использовать идентификационный фильтр, чтобы не загружать jq дополнительной работой.

3. Запустите тест через /usr/bin/time -v ./bin/transform . invItems.yaml > /dev/null. Поскольку нас не волнует фактический вывод, мы просто перенаправляем вывод в /dev/null. Эта команда выведет довольно много информации, но нас действительно волнует одна строка — Максимальный размер резидентного набора (кбайт), который представляет общий объем памяти, используемой процессом в килобайтах. В моем случае это значение было 1 432 592, а это значит, что наше приложение потратило почти 1,5 ГБ на преобразование этих данных!

Затем восстановите новый код и снова выполните предыдущие шаги, чтобы увидеть, приведут ли наши изменения к улучшению использования памяти. На этот раз у меня получилось 325 352, что более чем в 4 раза меньше, чем раньше!

До сих пор во входном IO находились данные для обработки либо из входного файла, либо из STDIN. Однако что произойдет, если наше приложение ожидает входные данные, но данных для обработки нет? В следующем разделе мы собираемся изучить, как ведет себя ввод-вывод в этом сценарии.

<p>Объяснение поведения IO</p>

Если вы создадите и запустите приложение как ./bin/transform ., оно просто будет зависать на неопределенный срок. Причина этого связана с тем, как большая часть операций ввода-вывода работает в Crystal. Большая часть операций IO является блокирующей по своей природе, то есть будет ожидать поступления данных через тип входного IO, в данном случае STDIN. Лучше всего это можно продемонстрировать с помощью этой простой программы:

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных