The Darkest Library

[RU] V is *not* for Vaporware

This article is in Russian. Please use Google Translate to read it.

Почитал у Влада Патрышева о статье “V is for Vaporware”, или, более интеллигентно, “язык V – говно”. Раз уж автор не стесняется писать такую резкую критику, стало быть, я тоже напишу ответочку.

Вот ссылка на статью: https://christine.website/blog/v-vaporware-2019-06-23

А скриншот, к слову, иллюстрирует результаты работы компилятора не V, а Go – сейчас поймете почему.

Везде далее я говорю “автор статьи”, а не “авторка”. Имя Сhristine в названии блога похоже на женское, но кто я такой чтобы assume gender. Кроме того, меня коробит от идеи “грамматического рода”. Хотя в русском языке без него нельзя.

Давайте разберем, что пишет в статье автор.

Скорость компиляции

It’s also worth noting that it was more than 2 seconds to only compile 50,000 lines of code

А что, компиляция 2 миллионов строк одним бэйсик блоком даже за 2 секунды – это что-то очень долгое?

Ну давайте посмотрим, как справится Go.
Короткий эксперимент я оформил в виде гиста: https://gist.github.com/olegchir/43f6d6983e6bd44bdeb1478668f53a45

Для начала, я слегка модифицировал тест. V отказался компилировать 2 миллиона строчек, а Golang продолжал компилировать на протяжении 30 минут, прежде чем я прервал это безнадежное занятие. Причем в процессе он сожрал 25 гигабайт оперативной памяти. Выше память не идет – наверное, ОС не даёт.

Любителям Go: я не утверждаю, что у Go плохой компилятор. Как раз с ним и сравниваю, потому что он хороший. Просто идея компилировать миллионы строк монолитным бэйсик блоком – больная.

Мой генератор программы на языке Go выглядит так:

-- lua
print "package main"
print "import \"fmt\""
print "func main() {"


for i = 0, 49000, 1
do
  print "fmt.Println(\"hello world\")"
end

print "}"

Для сравнения, вот генератор программы для языка V (я взял его у автора исходной статьи):

-- lua
 print "fn main() {"
 for i = 0, 49000, 1
 do
   print "println('hello, world ')"
 end
 print "}"

(Если вдруг интересно, я использую для подсветки синтаксиса tohtml.com.)

Теперь мы генерируем исходник:

"C:\opt\lua-5.4.2_Win64_bin\lua54.exe" -v ./gen.lua > hello-world.go

(Если захотите повторить мой эксперимент, то заметьте, что первая строчка сгенерированного файла – это сообщение о версии Lua. Перед компиляцией её нужно удалить).

Смотрим на результаты выполнения.

Для Go цифры получаются вот такие:

time "C:\Program Files\Go\bin\go.exe" build hello-world-2.go

real    0m0.441s
user    0m0.015s
sys     0m0.000s

Для V – вот такие:

time "C:\opt\v_windows\v\v.exe" hello-world-3.v

real    0m1.497s
user    0m0.000s
sys     0m0.015s

Самое смешное оказалось в том, что обнаружил Влад Балин (а я пропустил, когда писал первую версию этого поста). То, что у автора статьи компилятор V сломался на этих двух миллионах строк и ничего не скомпилировал. Отсюда эти две секунды. Если без прогрева запустить компилятор Go на файл с синтаксической ошибкой – будут те же самые две секунды.

Похоже, автор статьи считал, что компилятор компилировал-компилировал и остановился на 50 тысячах строчек. Я почему-то уверен, что он и не начинал, а остановился на проверке синтаксиса.

Так и быть, проверим на 49000 строчек.

Вот как справился Go:

time "C:\Program Files\Go\bin\go.exe" build hello-world-2.go

real    0m0.457s
user    0m0.015s
sys     0m0.000s

Вот как справился V:

time "C:\opt\v_windows\v\v.exe" hello-world-3.v

real    0m1.576s
user    0m0.000s
sys     0m0.015s

(Я быстро запускал много раз, чтобы добиться стабильного времени выполнения этих команд)

Это что, получается, V всего в три раза медленней Go? Компилятор, написанный энтузиастами на коленке против всего мира, который пилит Go, включая лучших в мире разработчиков на оплачиваемом фуллтайме. Кажется, неплохо.

Но надо тут отметить три факта:

  • Сравнивать производительность компиляторов без оценки качества оптимизации сгенерированного кода – довольно бесполезное занятие. Можно очень быстро генерировать нечто, что не оптимизировано вообще никак.
  • На таких маленьких числах лучше не использовать time. К сожалению, как прецизионно померить в винде я не знаю, а линукса под рукой нет.
  • Неизвестно, какую часть времени составляет вармап компилятора и какую – собственно компиляция. Нужен более хороший тест. Вполне возможно, сам компилятор запускался и прогревался 1.4 секунды из этих 1.5. Не показывайте автору статьи, сколько запускается компилятор Джавы, будет сердечный приступ.

Myth busted, как говорится. Поехали дальше.

Утечки памяти

Surely a “hello world” program has no good reason to leak memory, right?

Сказано с сарказмом, приведены листинги валгринда.

Дальше автор говорит: “Looking at the generated C code it’s plainly obvious to see this memory leak. init_consts creates a 1000 byte allocation and never frees it.”

Теперь мой ход! Хей, автор, а ты замечаешь, что программа завершается сразу после выполнения println? Это значит, что компилятору ничего и не нужно освобождать, это сделает операционная система. По крайней мере, пока это Linux/Windows/Mac на платформе x86-64, а никаких больше платформ V не поддерживает. Наверное, это очень неаккуратная недооптимизация, но ничего ужасного не произошло.

Myth busted. Поехали дальше.

Ноль зависимостей

So the compiler with “zero dependencies” is a dynamically linked binary with dependencies

Зависимости эти – libpthread и libc. Которые всё равно обязательные при разработке на Linux. Это как раз и есть практический “ноль зависимостей”.

Ещё, автор статьи спорит вот с этой фразой: “with zero [wip] dependencies”. Wip – это “work in progress”. Автор компилятора заявил цель – сделать ноль зависимостей. Он не говорил, что у него получилось. Хотя у него получилось (см. предыдущий абзац).

Busted. Поехали дальше.

Размер компилятора

V also claims to only require 400-ish kilobytes of disk space to build itself

Читаем, с чем же автор спорит: “400 KB compiler with zero [wip] dependencies”.

И дальше драматическая история о попытках собрать это в докере под алпайном с дальнейшим измерением размера сгенерированного докерного контейнера.

По-моему, автор не умеет читать по-английски. “Компилятор занимает 400 килобайт” не означает “директория, где ты собирал компилятор занимает 400 килобайт”.

Плюс, 400 килобайт так же не должно включать библиотеки и прочий SDK. Иначе так можно докатиться до того, что в размер Node.js придется включить весь NPM.

Вначале нужно почистить каталог сборки от временных файлов, пострипать и сжать экзешник, и потом измерить размер файла “v.exe”.

Я решил провести своё исследование и скачал V для винды и линукса.

Современная версия компилятора для винды занимает округленно 8 мегабайт, а для линукса – 3. С другой стороны, на сайте исчезло упоминание 400-килобайтного компилятора, так что всё справедливо. Кому какая разница, сколько занимает компилятор? Не показывайте автору, сколько занимает Виужал Студия на винде.

Дальше я сходил на гитхаб и скачал самую первую версию компилятора V. Оказалось, что она весит даже меньше, чем 400 килобайт. К сожалению, исследовать, что умеет или не умеет эта самая первая версия компилятора у меня времени нет, но доверие к выводам из статьи у меня уже немного подпорчено.

Busted.

Чушь в модуле HTTP

V has a http module. It leaves a lot to be desired.

Что же не понравилось автору статьи? Вот эта строчка в функции download_file: os.system2('curl -s -L -o "$out" "$url"'). Автор библиотеки решил не писать скачивание самостоятельно или юзать libcurl, а запустить хорошее, проверенное приложение.

Во-первых, ещё раз: стандартная библиотека – это не компилятор. И тем более, “какая-то библиотека”. Иначе так можно докатиться до того, чтобы сравнивать с Go и вайнить: “а чего сеть написана хуже, чем у Go”.

Автору библиотеки нужно было сделать что-то, и “что-то” он и сделал. И это “что-то” работает хорошо, потому что curl работает хорошо. В задаче загрузки файла по интернету, запуск отдельного процесса на скачивание — это вообще не бутылочное горлышко. Запуск отдельного процесса может гарантировать, что падение курла (если оно когда-то случится) не унесёт за собой само приложение. Вы же знаете, что Хром запускает вкладки в отдельных процессах? Одни плюсы.

Более того, автор статьи сам же замечает, что большая часть библиотеки уже переписана на libcurl, как ему того и хотелось. В свете аргументов выше, я не уверен, что это хорошая идея, ЕСЛИ можно было обойтись без этого, но тем не менее.

Выводы

Читать раздел “выводы” и потом оперировать им в дискуссиях – порочная практика.

Если вы пропустили весь мой пост и проскроллили сразу к абзацу “ВЫВОДЫ” – это плохо.

Читайте что написано внутри текста. Какая была методика исследований. Какие получились сырые данные. Как именно делались выводы. Не выдали ли слабую корреляцию за казуацию.

Ах да, что сказать про V?
V for Vendetta – очень, очень хорошая графическая новелла.
Плох или хорош язык V я не знаю, но по этой статье делать о нем выводы было бы неправильно.

Следи за собой, будь осторожен.

olegchir

Links: Facebook | Twitter | Instagram

Indie game developer. All opinions are my own.

Add comment

Follow me (@olegchir)

Don't be shy, get in touch. I love meeting interesting people and making new friends.

Most popular

Most discussed