Компиляция нового скрипта?

Возможно, вы читали недавний пост моего друга и коллеги Питера о том, почему лень, нетерпение и высокомерие толкают разработчиков к написанию сценариев.

Это отличное чтение, и этот пост следует из того, что должен сказать Питер. Если вы меня знаете или следите за мной в среде или твиттере, вы, несомненно, видели мои недавние сообщения на Голанге, более известном как Go. Я пытаюсь выучить язык и какой лучший способ выучить его, чтобы иметь реальный пример/вызов для работы. Итак, прежде чем идти дальше, сначала прочитайте пост Питера, чтобы понять контекст, а затем вернитесь сюда.

Сортировка? Хорошо. Итак, давным-давно я много писал код на C, и мне нравится сходство с C, которое очевидно в Go. Я решил попробовать этот пример синтаксического анализа журнала и посмотреть, как работает версия Go.

Код выглядит следующим образом:

Давайте начнем с того, как он составлен:

  • Строки 75–82: мы определяем нашу основную функцию и используем библиотеку флагов Go, чтобы установить, какие параметры командной строки, которые мы ожидаем, будут переданы исполняемому файлу. Они имеют формат: переменная := флаг.тип(“параметр”, по умолчанию, “сообщение пользователю »), где тип — это тип параметра (bool, int, string), default — это значение по умолчанию, а сообщение для пользователя — это подсказка, которую он увидит в командной строке. В большинстве случаев мы по умолчанию устанавливаем для наших ожидаемых входных данных значение true и устанавливаем значение по умолчанию 1 (секунда) для порогового значения.
  • Команда flag.parse() в строке 82 в основном означает, что вы довольны параметрами, которые вы установили заранее, и что все остальное, поступающее в командную строку после того, как эти параметры были проанализированы, должно быть захвачено в срез (динамический массив). к которому мы можем получить доступ с помощью flag.Args(). Это позволяет нам перебирать пути/имена файлов журнала (testdata/*.log) и передавать их для обработки при запуске grep_elb -b -i -r -t=5 -v testdata/*.log ‹ - этот бит входит в flag.Args()
  • Строки 84:88: Если флаг отладки «d» установлен, выведите некоторую дополнительную информацию о том, какие аргументы установлены и пути к файлам.
  • Строки 91–93: Передайте каждый файл журнала в функцию parseELBLogfile() вместе с любыми параметрами командной строки, такими как пороговые значения и т. д.
  • Строки 31–71: Здесь происходит волшебство. parseELBLogfile() в основном открывает каждый файл и считывает все строки в файле в срез. Для каждой строки он разбивает ее на отдельные элементы массива, используя пробел в качестве разделителя. Затем мы оцениваем состояние наших флагов, которые мы приняли через командную строку. Если установлены i, b или r, то мы хотим, чтобы эти тайминги сравнивались с пороговым значением параметра «t», и если они превышают пороговое значение, выводим их.
  • Строки 15–29: мы в основном читаем строки файла здесь. Обратите внимание на оператор отсрочки. Это работает аналогично блоку «finally» в операторе try-catch-finally. Это гарантирует, что файл будет закрыт перед выходом из функции.
  • Строки 13, 71, 92, 96 — вам может быть интересно, для чего нужны эти операторы wg.x()? Ну, они означают, что мы хотим дождаться завершения параллельных вызовов функций (горутин), прежде чем выйти из программы. Мы определяем группу ожидания в строке 13, а затем в строке 92 увеличиваем значение счетчика группы ожидания, чтобы показать, что мы выполняем функцию одновременно, т. е. мы добавляем к ней префикс с ключевым словом Go, например, go parseElblogfile()
  • Когда мы завершаем выполнение функции, мы обозначаем это с помощью wg.Done() (строка 71) и ждем завершения всех горутин с помощью wg.Wait() (строка 96).

Так как же все это выглядит тогда? Что ж, я запустил приложение с теми же данными журнала (5 файлов с общим количеством строк 411 000), которые использовал Питер, на моем «менеджере» Macbook [1].

  • PERL (5.18.2): perl grep_elb.pl -t 5 testdata/*.log 6,56 с пользователь 0,19 с система 95% процессор 7,067 всего

А теперь момент истины:

  • GO 1.6: grep_elb -t=5 testdata/*.log 1,00 с пользователь 0,17 с система 92% процессор 1,263 всего. Обратите внимание, что в этой версии исключены горутины.

На самом деле я попробовал еще раз с горутинами, и время оказалось около 1,56 с или около того. Я подозреваю, что операции ввода-вывода по чтению файла и записи в стандартный вывод являются узкими местами. И последнее: Питер проверил это на полном наборе лог-файлов ELB за 24 часа для крупного сервиса. Он имеет 1589 файлов журнала, которые содержат 5 159 601 строку и имеют размер 1,6 ГБ. Perl занял 114 секунд. Версия для Go? 26,39 секунд.

Теперь заголовок этого поста спрашивает, является ли компиляция новым сценарием? Возможно. Я написал это маленькое приложение в Sublime Text с плагином GoSublime. Компиляция заняла 0,902 секунды, и я получаю автозаполнение кода, форматирование и REPL из среды. Определенно хороший способ создать простой скрипт — см. этот пост для получения более подробной информации о моей настройке.

Итак, не хотите ли вы сами попробовать другой язык? Дайте нам знать, как вы поживаете.

[1] MacBook, начало 2015 г. (MacBook 8,1). 1,3 ГГц, 8 ГБ ОЗУ 1600 МГц DDR3, 256 ГБ SSD (с поддержкой FileVault), Intel HD Graphics 5300 1536 МБ. Эль-Капитан, 10.11.3