- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Crystal Programming. Введение на основе проекта в создание эффективных, безопасных и читаемых веб-приложений и приложений CLI - Джордж Дитрих
Шрифт:
Интервал:
Закладка:
К счастью для нас, 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. Давайте проведем тест и посмотрим, насколько это помогло.
Тестирование производительности
Для тестирования я буду использовать реализацию 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. Однако что произойдет, если наше приложение ожидает входные данные, но данных для обработки нет? В следующем разделе мы собираемся изучить, как ведет себя ввод-вывод в этом сценарии.
Объяснение поведения IO
Если вы создадите и запустите приложение как ./bin/transform ., оно просто будет зависать на неопределенный срок. Причина этого связана с тем, как большая часть операций ввода-вывода работает в Crystal. Большая часть операций IO является блокирующей по своей природе, то есть будет ожидать поступления данных через тип входного IO, в данном случае STDIN. Лучше всего это можно продемонстрировать с помощью этой простой программы:
print "What is your name? "
if (name = gets).presence
puts "Your name is: '#{name}'"
else
puts "No name supplied"
end
Метод get используется для чтения строки из STDIN и будет ждать, пока она не получит данные или пользователь не прервет команду. Такое поведение также справедливо для IO, не связанного с терминалом, например для тел ответов HTTP. Причины и преимущества такого поведения будут объяснены в следующей главе.
Резюме
В этой главе мы добились фантастического прогресса в работе над приложением. Мы не только сделали его действительно удобным для использования, поддержав терминальный IO, но и сделали его еще более гибким, чем раньше, разрешив использовать любой IO. Мы также значительно повысили эффективность нашей логики преобразования, выполнив потоковое преобразование. Наконец, мы немного узнали о блокирующей природе IO, что подготовило почву для следующей главы.
IO является основной частью любого приложения, которое выполняет чтение/запись данных. Наличие знаний о том, когда их использовать и, что более важно, как ими воспользоваться, в конечном счете приведет к созданию более эффективных программ. В этой главе также был затронут вопрос о правильном дизайне приложения, рассмотренный в предыдущей главе, и приведено несколько примеров того, как небольшие изменения могут значительно повысить общую полезность приложения.
В следующей главе мы рассмотрим концепцию параллелизма и то, как она может позволить нашему приложению обрабатывать множество файлов.
6. Параллелизм (Concurrency)
В некоторых сценариях программе может потребоваться обработка нескольких фрагментов работы, например суммирование количества строк в серии файлов. Это прекрасный пример проблемы, которую может помочь решить параллелизм, позволяя программе выполнять фрагменты работы, ожидая выполнения других. В этой главе мы узнаем, как работает параллелизм в Crystal, и рассмотрим следующие темы:
• Использование волокон для одновременного выполнения работы
• Использование каналов для безопасной передачи данных
• Одновременное преобразование нескольких файлов
К концу этой главы вы сможете понять разницу между параллелизмом и параллелизмом, как использовать волокна для выполнения нескольких одновременных задач и как использовать каналы для правильного обмена данными между волокнами. Вместе эти концепции позволяют создавать многозадачные программы, что приводит к повышению производительности кода.
Технические требования
Прежде чем мы углубимся в эту главу, в вашей системе должно быть установлено следующее:
• Рабочая установка Crystal