Больше чем Java?

Закончив очередной проект на Java, я попытался разобраться в причинах накопившегося раздражения. Да я люблю Яву и все такое, но… Есть несколько «но», которые досаждают. Приходится писать довольно много шаблонного кода, с генерацией которого вполне может справиться сам компилятор, IDE, конечно, выручает, но это не решение проблемы, а скорее костыль: если что-то изменилось, нужно перегенерить и вычистить и т.д. Проверки на null! Это зубная боль, по-хорошему, нужно делать их всегда дабы не нарваться на «нежданчик» в виде NullPointerException в самый неподходящий момент. Короче говоря, появилось желание посмотреть, что еще появилось в природе и сможет ли это нечто заменить мне Java. Дальше имеет смысл описать участников данного сравнения. Сразу скажу, что не претендую на полноту анализа, к сожалению, у меня было слишком мало времени, чтобы как следует познакомиться с каждым языком.

Обязательные требования к претендентам, которые у меня были:

• Язык общего назначения
• Кроссплатформенность (хотя бы Windows/Linux)
• Стабильность
• Статическая типизация
• Автоматическая уборка памяти
• Поддержка полноценной объектно-ориентированной парадигмы
• Хорошая поддержка в IDE (Eclipse, IDEA или на худой конец NetBeans)
• Безгемморойный доступ к существующим фреймворкам/библиотекам
• Производительность на уровне Java

Помимо этого очень хотелось бы:

• Null pointer безопасность обеспечивающаяся языком на этапе компиляции
• Простые приведения типов без рудиментов из С
• Возможность разумной перегрузки операторов
• Чтобы, наконец-то, были почищены базовые типы. Ну на фига тянуть в новый язык из бородатых времен всякие float/double, short/int/long? Может это и имело смысл во времена i386 процессоров, которые могли иметь математический сопроцессор, а могли и нет. Все эти тонкости могут жить в ядре операционной системы поближе к железу и не высовываться наверх. Базовые сущности: Integer и Float вот и все, что должно быть, детали пусть рулит компилятор.

• Гармоничное сосуществование лямбд
• Общий продуманный и целостный дизайн языка
• Выразительность, поменьше ASCII арта и загадочных конструкций, на которые хочется побрызгать святой водой
• Нормальные строки, в которых символы представлены не суррогатными парами или россыпью байтов, а полноценными Unicode point-ами.

Должен отметить, что в обзор не попал целый пласт языков, которые компилируются в нативные бинари или в C. Возможно, они и замечательные, но попробовав несколько вариантов типа D, Nim, Eiffel, Rust, Go, и еще чего-то я пришел к выводу, что не буду углубляться в эти изыскания. Проверка была очень простая – HelloWord. Бинарь получившийся на выходе обычно измерялся мегабайтами. Т.е. маленькая програмулька, которая печатает в консоль тупую строчку и должна занимать от силы 3-4Кб весит мегабайты! Мелочь скажете вы. Да мелочь, я понимаю, создатели языка впихивают в бинари всю мощь и богатство своего детища, но можно же было как-то оптимизировать это!? Если требуется только печать, зачем запузыривать в бинарь все что есть на свете? Ну вынесите минимально необходимую часть в статическую библиотеку, а все остальное в динамические либы. Если не ошибаюсь, создатели D и Rust позиционируют эти языки пригодными для написания ядра операционной системы. Вы серьезно, ребята? А вот всю эту “красоту”, мегабайты вспомогательного кода языка, с кучей системных вызовов Window/Linux вы тоже предлагаете затянуть в ядро? В общем, этот класс языков не вписался в мое требование «кросплатформенность» и «стабильность» (ну и с «автоматической уборкой памяти» и «объектно-ориентированностью» не всегда все гладко, то интерфейсы забудут добавить, то вместо классов какие-то сомнительные альтернативы предлагают) т.к. они содержат очень жирную прослойку между языком и операционной системой, а качество и стабильность этого кода вызывает много вопросов. Может быть он очень хорош, я не знаю, а если нет? Все-таки JVM и Java SDK проверены годами и прекрасно трудятся на разных ОС. Поэтому все рассматриваемые далее языки в той или иной мере опираются на JVM. Теперь перейдем к списку наших участников, с небольшим описанием, а точнее с моими субъективными впечатлениями, не стоит воспринимать их слишком серьезно.

C# (MSVC2015) — вошел в обзор только потому, что мне довелось написать на нем немалое количество строк, и никаких преимуществ по сравнению с Java я в нем не обнаружил. Скорее наоборот. К тому же с кросплатформенностью тут все не слишком радужно, родная для него платформа Windows, а mono не дает полноценной замены на Linux (см. ниже). Но мне было интересно сравнить его с точки зрения производительности с остальными участниками.

Qt/C++ (5.10) — так же был добавлен исключительно для сравнения производительности.

Ceylon (1.3.3) – этот замечательный язык был создан в 2011 Гавином Кингом, автором известного фреймворка для Java Hibernate и поддерживается сейчас сообществом RedHat. Язык очень красив, продуман, и выразителен. Наверное, так бы выглядела Java если бы развивалась без гнета обратной совместимости. Язык включает в себя все мои вышеперечисленные «хотелки» и даже более того. Я действительно стал поклонником этого языка и потратил больше всего времени на его изучение, к сожалению, информации по нему не очень много, а сообщество не слишком многочисленное и активное. На мой вкус язык почти идеален, но хотелось бы упомянуть и о недостатках. Есть плагины для Eclipse/IDE, они сделаны весьма хорошо, но оптимизация не на высшем уровне, короче говоря, они безбожно тормозят. Запуск тестов (есть специальный фреймворк для тестирования) может занять 7(!) секунд, причем сами тесты выполняются мгновенно, но старт очень неторопливый.

Скорее всего, это связано со вторым недостатком – вшитую в язык систему модульности, нет, я не хочу сказать, что модульность сама по себе это недостаток, я лишь имел ввиду, что встроенные в язык конкретные вещи становятся безальтернативными и это плохо. Так вот в Цейлоне модули имеют свой формат (.car файлы), а основано это все на системе модулей JBoss. Еще создатели языка почему-то отказались от 'protected', что не дает возможность реализовать, например, такой шаблон проектирования как «Шаблонный метод».

Scala (2.12) – такое впечатление, что создатели языка руководствовались, в основном, принципом «а давайте сделаем все ни как у людей». Вместо привычной * сделали _, а зачем? Видимо, «чтобы никто не догадался» (с). Все знают, что массив это обычно [], так давайте сделаем () и пусть им вынесет мозг. А что же тогда будет значить []? А давайте это будут дженерики? Давайте… И так далее. Чтобы вы думали значит a < — b? Я было подумал, ну небось, клонирование, или запихнуть все из коллекции b в коллекцию a, ан нет, это обход коллекции…

А почему? Да потому, что это Scala, потому что они с Тау Кита, кровь у них фиолетовая и мозги работают по-другому, короче они иные… Взяли и вшили в язык XML… Нужно, видимо, пойти дальше и встроить прям в язык Microsoft Office, почему нет? Строго внести в стандарт языка формат xls файлов… По началу, все это вызывает раздражение (еще и дурацкие названия стандартных классов – StringOps как вам?), кто-то плюнет и скажет, а ну ее эту скалу. А адепты презрительно пожмут плечами, мол, нехай сиволапый лезть в наши микросхемы, раз не понимаешь ни хрена, мы тут элита. Ну а если серьезно, обычные язык, без откровений, к сожалению, нет защиты от null pointer, только optional. Есть скользкие места и ловушки для новичков, я не уверен, что это хорошее решение для коллективного творчества.

Kotlin (1.2) – напомнил мне гнездо сороки: тут серебряная ложечка, тут фантик от конфетки… Девизом ребят, видимо, была песня «я тебя слепила из того что было». Взять из других языков проверенные временем решения и соединить, почему нет? Создатели языка называют это прагматичным подходом. Только иногда, как мне кажется, их подводил недостаток вкуса что ли (или чувства «прекрасного», на секундочку). Глядя на такую дичь как, return@forEach (прям e-mail какой-то) хочется выругаться интеллигентно и дать зарок не пользоваться этим. Но в целом язык мне все-таки понравился, лаконичный, все, что нужно есть. Жаль только присваивание в выражениях запретили и базовые типы не почистили как в Ceylon-е (вероятно, для меньших усилий при стыковке с Явой).

Fantom (1.0.69) – это такая «вещь в себе», фантомная, вроде бы уже существует с 2005 года, а вроде как и нет его. Взял в оборот исключительно из-за байки будто бы он рвет «как Тузик грелку» по производительности Яву на ее же JVM-е, ну и вообще, интересно было взглянуть на язык который компилируется в некие самопальные fcode, которые потом могут транслироваться как на JVM так и на CLR. Что сказать про сам язык? После того как я прочитал, что дженерики «пока еще не поддерживается», но это «пока» длится с каких-то там мохнатых годов и по-видимому так и останется, мой практический интерес к этому языку угас. Если быть точным поддержка дженериков там есть, но только для встроенных коллекций, а этого для инструмента разработки промышленного уровня, на мой взгляд, недостаточно. С одной стороны вроде бы есть nullable types – “Str? str”, но компилятор не препятствует обращению к str без проверки на null. Обидно…

D (dmd 2.078.2) — был добавлен позднее, исключительно из спортивного интереса как дополнительный участник не с JVM. К сожалению писать на D не слишком комфортно из-за отсутствия IDE с «человеческим лицом». На сайте приводится целый список «IDE», некоторые даже написаны на самом D, но на поверку все это оказывается, пардон, лаж… неправдой. Все они непригодны для комфортного написания кода. Реально на чем можно хоть как-то «лабать» это плагин для Idea, но и там нет кода завешителя даже после точки. Наиболее пригодный для работы это DDT плагин для Eclipse, но его автор написал, что прекращает работу над проектом, видимо, разочаровавшись в D. Прискорбно.

У меня не было времени, чтобы детально исследовать/анализировать/тестировать каждый аспект языка отдельно, поэтому было принято решение написать на всех исследуемых языках, похожий код с тем же набором классов/логики и чтобы обязательно было задействовано:

• Интенсивный I/O
• Парсинг строк
• Вычисления с плавающей точкой с использованием математических функций: sin, cos, atan2, toRadians, sqrt
• Работа с коллекциями: ассоциативными массивами и просто массивами
• Лямбды (если есть)

Если в языке присутствовали свои библиотеки, я старался использовать их, если нет, то из Java.
Под руками оказались громадные текстовые файлы из предыдущего проекта с картографическими данными, поэтому тестовые приложения делают следующую работу. В командную строку предается путь к каталогу с файлами, участник должен получить список файлов отфильтровав их по расширению и обработать каждый. Обработка заключается в построчном чтении и парсинге строки и если это сегмент (т.е. отрезок на местности с координатами начала и конца), вычислить его длину и положить в map все сегменты которые находятся в определенном радиусе от заданной точки. Ключом в map-е служит идентификатор группы сегментов. Программа сама засекает время выполнения всей операции в миллисекундах и выдает количество найденных групп сегментов.

Самый лаконичный код получился на Kotlin, самый изящный и доступный для быстрого понимания на Ceylon.

Немного скучных цифр, объем кода в строках/килобайтах:

• Ceylon: 128/4.7
• C#: 177/6.2
• Fantom: 153/3.8
• Java: 203/6.1
• Kotlin: 117/3.9
• Qt/C++: 413/8.3
• Scala: 123/3.6
• D: 204/5

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

• Ceylon (*.class): 31.1
• C# (.exe): 8.7
• Fantom (.pod): 7.5
• Java (*.class): 9.9
• Kotlin (*.class): 20.9
• Qt/C++ (*.exe Release): 37.7
• Scala (*.class): 20.7
• D (.exe, Release): 1765

Ну а теперь самое вкусное, результаты забега… Кто прибежал первым, а кто оказался аутсайдером? Делайте ваши ставки, господа! Лично мои предсказания не оправдались, а результаты удивили. Тестирование проводилось на одной машине, но на двух платформах: Windows 7 x64 Professional и Linux Debian x64 Stretch Stable. И там и там была установлена Orcale Java 8.152. На Linux скомпилированный .exe файл C# запускался через mono из стандартного репозитория Debian. Запускалось все в одинаковых условиях на незагруженной системе. Я провел два раунда, в первом на входе был только один относительно небольшой файл 30Мб — спринт, в этом случае от запуска к запуску был некоторый разброс результатов, поэтому запускал по 20 раз каждого участника и брал средний результат. Во втором раунде условия резко ужесточились, на входе было несколько файлов общим объемом около 900Мб — марафон. В этом случае разброс был значительно меньше, видимо из-за «прогретости» JVM-а. Но для чистоты эксперимента все-таки запускал 10 раз:

Windows 7 x64 Professional

Один файл (30Мб)

• Java: 621ms, 1,00
• Kotlin: 667ms, 1,07
• Scala: 745ms, 1,20
• D: 797ms, 1,28
• C#: 1143ms, 1,84
• Ceylon(JavaLibs): 1160ms, 1,87
• Fantom: 1362ms, 2,19
• Qt/C++: 1378ms, 2,22
• Ceylon: 1479ms, 2,38

Несколько файлов (~900Мб)

• Java: 22932ms, 1,00
• Scala: 23013ms, 1,00
• Kotlin: 23300ms, 1,02
• Fantom: 32047ms, 1,40
• C#: 33349ms, 1,45
• Ceylon(JavaLibs): 38466ms, 1,68
• Qt/C++: 40444ms, 1,76
• Ceylon: тест провален, участник не смог добежать до финиша и был принудительно снят с пробега по прошествии 5 минут работы над крупным файлом 738Мб (см. комментарий ниже).
• D: Мирно почил в бозе, эпитафия: “core.exception.OutOfMemoryError@src\core\exception.d(702): Memory allocation failed”

Debian x64 Stretch Stable:

Один файл (30Мб)

• Java: 612ms, 1,00
• Kotlin: 652ms, 1,07
• Scala: 686ms, 1,12
• D: 785ms, 1,28
• Qt/C++: 1023ms, 1,67
• Ceylon(JavaLibs): 1190ms, 1,94
• Fantom: 1356ms, 2,22
• Ceylon: 1480ms, 2,42
• C#: 2119ms, 3,46

Несколько файлов (~900Мб)

• Java: 22161ms, 1,00
• Scala: 22625ms, 1,02
• Kotlin: 22865ms, 1,03
• D: 22876ms, 1,03
• Qt/C++: 31349ms, 1,41
• Ceylon(JavaLibs): 34664ms, 1,56
• Fantom: 40903ms, 1,85
• C#: 68038ms, 3,07
• Ceylon: тест провален, участник испустил дух не добежав до финала с таким эпикризом: «Exception in thread «main» java.lang.OutOfMemoryError: GC overhead limit exceeded»

К сожалению, так понравившийся мне Ceylon (песня ты моя не спетая), еле-еле приплелся где-то в конце, отставание от Java существенное. Scala гнал ноздря в ноздрю с Java. Fantom естественно не произвел никаких революций. Java лидер по скорости, а вот C# немного удивил, я думал, будет где-то наравне с Java. Совсем не ожидал, что нативный код окажется в хвосте! Можно, конечно, списать на неторопливость Qt, но все же… Не, ну можно, конечно, переписать на std либах или вообще на чистый C с ассемблерным вставками, но это уже будет совсем другой код. Была надежда, что молодой да ранний Kotlin покажет близкую с Java производительность, но отставание все же есть, значительно меньше, чем Ceylon, но больше чем Scala. Причем как-то непонятно где в Kotlin может проседать перформанс, ведь у него нет своего ввода/вывода, математической библиотеки и коллекций, все это используется из Java. Вот, например, Ceylon подвели самодельные коллекции, как выяснилось, когда я стал разбираться в причинах его провала на большом объеме входных данных. Они оказались слишком прожорливы к памяти, и съели 8Гб оперативки даже не заметив, поэтому тест и «подвис», например, при запуске на машине с 24Гб памяти, тест на Ceylon проходит нормально, но, конечно, абсолютные цифры сравнивать уже нельзя, это другое железо. Мне все же удалось заставить Ceylon работать, когда я заменил коллекции из его стандартной библиотеки на коллекции из Java (HashMap и ArrayList) и тест был пройден. Так же добавил результат для Ceylon когда используются Java библиотеки для I/O и коллекция, результаты немного лучше, но не спасают ситуацию.

Кстати, попутно можно отметить, что на одном и том же железе Debian обеспечивает чуть лучшую производительность (исходные данные я подкладывал ему на ext4 раздел, а не брал их с NTFS).

Выводы

Как я уже говорил, из всех участников мне больше всего понравился Ceylon, на нем мне действительно захотелось покодить. Но, похоже, что он еще не созрел для промышленного использования, создателям нужно всерьез озаботиться профилированием и подчистить узкие места, тем не менее, я буду следить за его судьбой. Из оставшихся вариантов я бы выбирал между Scala и Kotlin, они, кстати, синтаксически весьма схожи, тот же а-ля паскальный стиль объявления функций и переменных. Scala лучше оптимизирован по скорости и более стабилен, но зато в Kotlin есть «умное приведение» и null-безопасность. Я, пожалуй, пока остановлюсь на Kotlin и буду изучать его детальнее, возможно, следующий внутренний проект мы напишем на нем.

P.S. Да, да, я предвидел «код в студию» J
Вот исходники: drive.google.com/open?id=1N3sEsw4MZ33GI-PPQOw_vocahGdjg9bq
Вот тулза mp2dcf, которая конвертирует карты в «польском» формате в DCF: drive.google.com/open?id=12SlixUmpnrKH5Eh8k69m_T1tmWCVy6Ko
Карты можно скачать например тут: navitel.osm.rambler.ru
Я успел попробовать на Италии: navitel.osm.rambler.ru/?country=Italy

Выложил исходники на GitHub: github.com/akornilov/LangBenchmark

UPD
Обновлены цифры тестов на производительность.

Благодаря замечаниям в обсуждении код был улучшен/исправлен:
asdf87 — в C# добавлено использование BufferedStream (не оказывает заметного влияния на результат);
stack_trace — поправлен код Qt/C++, добавление в map (не оказывает заметного влияния на результат);
AlexPublic — важное замечание в Java имплементации, длина сегмента, в отличии от других языков, вычислялась по требованию, а не при создании объекта.

Еще в Scala, Kotlin и Ceylon (JavaLibs) была добавлена проверка IOException как в Java.
В Kotlin вместо Java API для чтения строк теперь используется функция-расширение из стандартной библиотеки: .useLines.

Так же поменялась методика получения результатов: был написан скрипт который автоматически запускает всех участников «забега» несколько раз и вычисляет среднее время работы и контролирует чтобы количество найденных сегментов совпадало у всех. Для теста на небольших файлах (спринт) каждый участник запускается 20 раз, на больших файлах (марафон) 10 раз. Для всех языков с JVM выставлено -Xmx2g.

UPD
1) Ради спортивного интереса добавил в «забег» D. Участник показал неплохой (но не блестящий) результат, но, к сожалению, в марафоне под Windows скончался от недостатка памяти (это при 8-то гигах оперативы). При том, что на этом же железе, но под Linux смог отработать нормально. Это, в общем-то, подтверждает мои сомнения насчет кросплатформенности и стабильности рантайма языка.
2) На днях вышло обновление для Kotlin 1.2.30-release-78, я пересобрал котлиновского «участника» и прогонял, соответственно, на новом релизе. И произошло чудо — на короткой дистанции Kotlin смог вырваться на второе место! И это без каких-либо оптимизаций в коде. Выражаю респект команде разработчиков Kotlin, молодцы ребята — так держать! Верю что Kotlin может показать равную с Java производительность сохранив все свои «плюшки».
Share post

Comments 171

    +3
    Базовые сущности: Integer и Float вот и все, что должно быть, детали пусть рулит компилятор.
    Вы предлагаете компилятору всегда использовать максимальный тип (long и double в случае Java) или вычислять необходимый размер анализируя код? В первом случае у нас будет неэффективное использование памяти и просадка по производительности (особенно на 32х битных системах), а во втором риск переполнения и/или увеличение времени компиляции.
      –4
      Ну в языке высокого уровня я хотел бы видеть класс, например, Float, который эффективно решал бы свои задачи не загружая мне мозг лишней информацией, сколько он в данный момент занимает в памяти бит. Похоже я неудачно выразился, компилятор, конечно же не сможет решить это на этапе компиляции, но в рантайме это вполне возможно.
        +3
        в рантайме это вполне возможно

        Покажите хоть один язык, где это возможно и при этом эффективно?


        Проблема в том, что числа не одинаковые. И плавающая точка ни разу не замена целым числам. И число произвольной точности практически не реально реализовать так, чтобы это было также эффективно, как числа, укладывающиеся скажем в 128 бит. Не можете вы этим не загружать мозг.

          –2
          Я не имел ввиду классы которые считают с произвольной точностью типа Decimal, пусть они себе живут отдельно, но написать класс заменяющий float и double вполне здравая идея и, например, в Ceylon так и сделали: ceylon-lang.org/documentation/1.3/tour/language-module/#numeric_types

          Насчет эффективности, я специально запрофилировал getDistance в моих тестах, где происходят самые интенсивные вычисления с плавающей точкой и Ceylon показал результат лучше чем Kotlin, но хуже чем Java.
          Мое мнение что если такой класс реализован достаточно эффективно в 99% случаев можно не парится и использовать его. Но, конечно, если на финальной стадии при профилировании обнаруживаются узкие места, тогда уже есть смысл начать что-то оптимизировать.
          –1
          Из-за таких как ты, мы сейчас и имеем тормозное вирзо вместо половины компьютеров. Мозг нагружать? Не, это слишком сложно.
            –3
            Не хами, для начала. А мозг нужно включать там где это действительно нужно.
              +1
              Ты можешь, конечно, мне не поверить, но при сравнении производительности действительно нужно нагружать мозг. Хотя бы для того чтобы понимать, что ты измеряешь то, что хотел, а не то что получилось. И что вся эта затея вообще имеет хоть какой-то
              практический смысл.
                –2
                Я, конечно, дико извиняюсь, но по-моему снова «порожняк гоняем». Бла-бла-бла…
                Я то как раз прекрасно понимаю что я измеряю и как, если ты чего-то не понял из статьи — спрашивай, начнем нагружать тебе мозг :)
                Если хочешь предложить что-то конкретное, предлагай — рассмотрим.

                P.S. с теми кто обращается на Вы я тоже на Вы, с теми кто на ты, тоже на ты, так что без обид :)
                  +2
                  Хорошо, если действительно представляешь, что ты измеряешь. Тогда ответь на такой простой вопрос: какой смысл в том чтобы сравнивать буферизированное чтение в Java версии с небуферизированным чтением в C# версии?
                    –2
                    А кто тебе сказал что StreamReader в C# не буферизирован?
                    Смотри например: msdn.microsoft.com/en-us/en-en/library/system.io.streamreader.discardbuffereddata(v=vs.110).aspx
                      +1
                      Ты придуриваешься или правда такой? По-твоему буфер в 128 и 4096 байт одно и то же? Самое смешное, что тут даже голову особо включать не нужно было. Достаточно было загуглить и добавить BufferedStream.
                        –1
                        Спокойнее, батенька, зачем же так горячиться? :)

                        Во-первых, я не ставил перед собой целью исследовать исходники библиотек ввода-вывод и сравнивать сколько они там байт себе под буфера выделяют.
                        Во-вторых, первичная буферизация при чтении все равно происходит в драйверах/системе, а вторичная будь то 128 или 4096 байт может не дать существенного эффекта (как и показал эксперимент).
                        Не совсем в тему, но помню, что, например, игра с флагами FILE_FLAG_RANDOM_ACCESS и FILE_FLAG_SEQUENTIAL_SCAN для нативного Windows API CreateFile оказывают значительное влияние на скорость чтения.

                        Добавил BufferedStream в C# реализацию и проверил на небольших файлах, погоды он не делает, разница 10-15ms.
                        Но все равно добавлю в код, спасибо за совет :)
          0
          Решается опциональной типизацией. В узком месте указываем тип, в некритичной ситуации пусть компилятор сам думает
            0
            Это не опциональная типизация. При опциональной типизации в некритичных ситуациях думает не компилятор, а рантайм.
          +5
          Какой смысл выкладывать цифры без кода и данных?
            +8
            Помимо mono для C# существует ещё и .net core — который, во-первых открытый, во-вторых кросс-платформенный. Если не затруднит — прогоните ваш бенчмарк и на нём.
              +1
              Не знал. Постараюсь проверить.
              +3
              Хорошо бы увидеть исходный код тестовых программ (иногда, особенности применения операторов могут кратно менять скорость работы), а также используемые режимы компиляции. Без исходного кода можно только «на слово» верить циферкам в статье. Т.е. лучше не верить.

              P.S. Вы сами признаетесь, что являетесь профессионалом в Java. Написание кода на языках, которые вы знаете не так хорошо, может содержать неэффективные решения. Особенно меня настораживает проигрыш в 1.5-2 раза кода на С++.
                –2
                Код выложил (см. ниже). Насчет C++ сам в шоке :)
                  0

                  Насколько я помню был пост про то что на некоторых задачах Java быстрее C++ за счет оптимизаций в рантайме, но там разница была довольно несущественной (вроде бы меньше 10%).

                  –1
                  Да, проблема в том, что часто ламаки берутся меряться пиписьками. Плюсы проиграли 1.5-2 раза? Не смешите мои тапки. Нативные языки (Delphi, C++) не могут проиграть виртуалкам просто физически. В идеальном случае идеальной виртуалки — пойдут вровень.
                    0
                    Не знаю с кем Вы там меряетесь, не смею мешать.
                    Просто в JVM ввод-вывод лучше оптимизирован чем в Qt, вот и все — никаких чудес.

                    P.S. ты давай там завязывай с тапкапи общаться, так и до дурки недалеко :)
                      0
                      Вообще-то могут. «Виртуалки» в отличие от компиляторов имеют информацию о выполнении и нагрузке определённых участков кода не только во время компиляции, но и во время выполнения. И могут дооптимизировать программу во время работы, «на лету». Не говоря уже о том, что каждый экземпляр программы становится максимально оптимизирован под конкретное оборудование конкретного пользователя, а C++-ники вынуждены компилировать неизменную программу под широкий набор конфигураций.
                        0
                        C++-ники вынуждены компилировать неизменную программу под широкий набор конфигураций

                        В серьёзных вычислительных задачах код обычно компилируется вот прямо под ту железку, которая его будет исполнять.
                          –1
                          В реально серьёзных вычислительных задачах делаются специальные ассемблерные вставки или специальные узкоспециализированные компиляторы. Мы тут прикладное ПО обсуждаем.
                            +1
                            специальные ассемблерные вставки

                            Не всегда.

                            специальные узкоспециализированные компиляторы

                            Тоже не всегда.

                            Мы тут прикладное ПО обсуждаем.

                            Ну в худшем случае будет у вас несколько вариантов функции под разные доступные SIMD-расширения, скажем, которые будут выбираться однократно при первом выполнении функции. Это для прикладного ПО хоть где-то навредит?
                    0
                    Да, да, я предвидел «код в студию» :) нужно просто было срочно почистить его от проприетарных данных и дать возможность потестить на каких-нибудь свободных картах:
                    Вот исходники: drive.google.com/open?id=1N3sEsw4MZ33GI-PPQOw_vocahGdjg9bq
                    Вот тулза mp2dcf (набросал на Kotlin за час :) ), которая конвертирует карты в «польском» формате в DCF: drive.google.com/open?id=12SlixUmpnrKH5Eh8k69m_T1tmWCVy6Ko
                    Карты можно скачать например тут: navitel.osm.rambler.ru
                    Я успел попробовать на Италии: navitel.osm.rambler.ru/?country=Italy
                      0
                      Если ищется производительность, то почему не что-то наподобие:
                      QMAKE_CFLAGS_RELEASE = -O3 -march=native -mtune=native

                      для Qt?
                        0
                        Давайте попробуем, но, на мой взгляд, выбирая профиль Release я уже и так явно выразил свои намерения и «подписался» под производительностью. А если пользователю после этого нужно все-таки лезть в настройки и прописывать какие-то дополнительные ключи, это недоработка среды/билдсистемы.
                        Я вообще старался не пользоваться какими-то специфичными трюками конкретного языка чтобы не создавать ему преференций.
                          +2
                          выбирая профиль Release я уже и так явно выразил свои намерения и «подписался» под производительностью

                          Нет. Вы подписались под некоторой минимально-безопасной степенью оптимизации.

                          А если пользователю после этого нужно все-таки лезть в настройки и прописывать какие-то дополнительные ключи, это недоработка среды/билдсистемы.

                          Снова нет. Это гибкость, которая нужна только тому, кому она на самом деле нужна.
                            0
                            Хорошо, не будем спорить о частностях здесь. В контексте статьи, я не «ищу производительность», я сравниваю производительность языков в их дефолтной конфигурации. Для Qt это Release.
                            Взять хотя бы "-march=native -mtune=native" — это уже нарушение одинаковых условий для всех, ведь JVM не был скомпилирован конкретно для моей машины.
                              +4
                              я сравниваю производительность языков в их дефолтной конфигурации. Для Qt это Release.
                              Взять хотя бы "-march=native -mtune=native" — это уже нарушение одинаковых условий для всех, ведь JVM не был скомпилирован конкретно для моей машины.

                              Абсолютно некорректное сравнение.
                              Неважно под какую машину была скомпилирована Java, всё равно её JIT-компилятор скомпилирует ваш код под конкретно ваш компьютер (если вы прямо не запретите ей это ключами).
                              C++ же язык статический, он применяет оптимизации не в процессе работы программы, а в процессе компиляции.

                              Так что сейчас вы установили, что для очень простых программ максимальная оптимизация HotSpot работает лучше чем средняя C++ компиллятора.
                              Что и так очевидно.

                              Так как С++ компилятор используется в самых различных вариантах оптимизации (от дебага, до полного инлайна всех функций с разворотом всех циклов), то как дефолтный принят некий средний уровень.
                              И если уж вы пользуетесь этим компилятором, то и настраивайте его соответственно.
                                –6
                                Я рад что работа JIT подсистемы для вас очевидна. Но мне не хотелось «думать» за JVM, как она там будет оптимизировать в рантайме, меня не особо тревожит, это ее дело. Кстати, JIT компилятор тоже написан на C/C++ и настройки компилятора с которыми он был построен напрямую влияют на его производительность так что с корректностью здесь я не вижу никаких проблем.
                                Повторюсь, компилятор настроен профилем Release — точка. И у меня нет желания прогонять его с десятками разных ключей для GCC или Microsoft Compiler-а и выбирать лучший вариант для C++. Как настроили разработчики — так и поехало.
                                Предлагаю завершить на этом дискуссию, если вам интересно с O3 — исходники в вашем распоряжении, проверяйте, делитесь результатами.
                                  +3
                                  Повторюсь, компилятор настроен профилем Release — точка.

                                  Ваше право.
                                  Только статья тогда должна называться: «Проверка дефолтных настроек различных языков, технологий, компиляторов и реализаций потоков данных».
                                    –4
                                    Думаю что не стоит выносить это в заголовок, это будет понятно из контекста по мере прочтения.
                                    Но все равно спасибо за Ваше мнение, я, если честно, тоже колебался добавить O3 или нет, примерно с такими же аргументами как в нашем диалоге :)
                          +1
                          Бесполезно. Потоки в С++ исторически медленные. Видимо, в Qt тоже.
                          Для производительности — только прямое чтение.

                          Не понял, о чем статья: JVM works well — К.О. Но за счет памяти. Еще на ней можно писать парсеры. Всё.
                            –1
                            Сравнивалось не C++ с JVM, а производительность разных языков на JVM. То что JVM работает нормально и на нем можно писать все что угодно у меня сомнений не вызывало.
                              +2
                              Здесь сравниваются не языки, но реализация библиотеки ввода-вывода. И немного Map. Всего лишь.

                              Нужны другие тесты.

                              P.S И код лучше выкладывать на гитхаб — удобнее смотреть, да и может коммитеры подтянутся — исправят ошибки, например.
                                –2
                                Во-первых, вы как-то забыли упомянуть арифметику с плавающей точкой и работу со строками.
                                Во-вторых, для языков с JVM подсистема ввода-вывода особой роли как раз не играет, т.к. используется из Java, а результаты тем не менее существенно различаются.
                                Так что здесь, всего лишь, сравниваются производительность языков на JVM и тесты на мой, естественно, субъективный взгляд вполне адекватные и показательные :)
                                Кому нужны другие тесты могут проделать эту работу самостоятельно и поделиться результатом, с большим интересом почитаю :)

                                P.S. на гитхаб выложу на досуге, может и правда блох наловим в коде :)
                              –2
                              Хм… как-то не доводилось сталкиваться с их медленностью, это надо очень постараться чтобы так накосорезить в коде чтения из файла в стандартной проверенной-перепроверенной либе.
                                +1
                                Делать руками mmap и string_view потом поверх него — быстрее в несколько раз.

                                fscanf, правда, медленнее, но то такое.
                                  –2
                                  mmap это уже завязки на платформу. Понятно, что если все сделать вручную будет быстрее, но это надо тогда в каждом языке делать. Можно в той же Java не пользоваться стандатной библиотекой I/O, а прокинуть нативный вызов и сделать тот же mmap.
                                  Только зачем? Мне интересно было сравнить пользуясь стандартными средствами языка, если его библиотека I/O плохо оптимизирована эту уже минус.
                                    0
                                    Как вариант, можно воспользоваться std::filebuf — он ощутимо быстрее, чем fstream.
                            0
                            deleted
                              +2
                              Бинарь получившийся на выходе обычно измерялся мегабайтами.

                              Сравниваете тёплое с мягким. *.class получается сравнительно небольшим, но для его запуска нужна отдельная программа. Бинарник на Rust получается 500Кб, что много, если не думать о том, что он сам же и обеспечивает уборку за собой.

                                0
                                Да нет, размеры классов я выложил просто для информации, чтобы, можно было сравнить их, например, с размерами классов в чистой Java и посмотреть насколько толста прослойка нагенеренная Scala или Kotlin компилятором. С Rust-ом, конечно, сравнивать не будем, там не получится отделить мух от котлет, сколько Кб на логику ушло, сколько на сам язык.
                                  +1
                                  По сравнению с размерами рантайма такое сравнение имеет не очень большой смысл
                                    0
                                    Ну почему же, ведь классы выполняются на одной и той же JVM.
                                      +1
                                      Ну у C# совсем другая среда исполнения. И у С++ тоже. Кроме того, даже у JVM-based языков может быть выделенный в отдельный файл рантайм. И наоборот, набор просто утилит, который по-умолчанию включен в сборку, даже если не используется. Поэтому просто по размеру сложенных в директорию файлов и их размерам сложно дать оценку «нагенеренной прослойки», а размер «полезной» части бинарника, в свою очередь напрямую зависит от того насколько богат рантайм.

                                      Можно относительно честно сравнить размеры компилируя всё статически (и даже здесь будет чувствоваться влияние разных ОС и архитектуры системы под которую собираем). Но даже сравнивая эти цифры, довольно сложно сделать какие-то выводы наверняка.
                                        0
                                        Если посмотреть на языки с JVM, то, например, объем классов (с практически идентичной функциональностью) в Kotlin и Scala примерно в 2,1 раза больше классов Java. А для Ceylon уже в 3,1 раза. Это и так ощутимо «толсто», но, вы правы, если заглянуть в байт-код и посмотреть есть ли там еще и вызовы в рантайм языка, прослойка может оказаться еще толще.
                                –2
                                Я не очень понимаю, почему статья (на момент моего прочтения) так низко оценена. Человек проделал работу и поделился результатами. Понятно, что первые опыты писания программ на новом языке могут привести к неэффективному коду, который профессионал может улучшить в несколько раз. Понятно что проверялась только малая часть функциональности. И тональность слегка залихватская. Но информация в целом интересная и полезная.
                                  0
                                  Спасибо! По мне так про бенчмаки всегда интересно почитать тем более когда за тебя кто-то уже это все проделал :)
                                  Ну а профессиональные (и адекватные :) ) комментарии к коду только приветствуются.
                                    0
                                    И ещё одно замечание/дополнение. Всё-таки использование Optional позволяет начиная с Java 8 обходиться без null.
                                      –1
                                      Верно. Но Optional мне не нравится, под защитой я имел ввиду:
                                      String str = null; // Ошибка компиляции, тип не поддерживает null
                                      — String? str = null; // OK.
                                      str.length() // Ошибка компиляции (не рантайма!)
                                      Это может отловить кучу проблем на раннем этапе.
                                        +1
                                        Тут я с Вами не соглашусь.
                                        Задавая Optional вы одновременно указываете тип обьекта, который он может содержать. И с этого момента компилятор помогает Вам.
                                        Мой опыт по использованию Optional очень позитивный.
                                        Осмелюсь предложить Вам почитать вот эту серию статей.
                                          –1
                                          Спасибо, почитаю!
                                      +3
                                      первые опыты писания программ на новом языке могут привести к неэффективному коду, который профессионал может улучшить в несколько раз.

                                      Это лишает статью смысла, ведь в ней сравнивается производительность. Методика сравнения описана общими словами, а код вообще не сразу появился, а когда появился — в комментариях, в виде архива в облаке. То есть, имхо, работа сделана как попало, статья оформлена как попало.
                                      Плохая статья — плохие оценки, все логично. Но, кмк, это должно мотивировать автора совершенствовать навыки, а не обижаться и замыкаться в себе. Эго отращивать вредно, а на качество жизни рейтинг хабра не влияет.
                                        –2
                                        Дык я и не обижаюсь, и тем более не замыкаюсь, а отвечаю по мере возможности в свободное время :)
                                        Кому-то будет интересно, кому-то нет, это нормально.
                                        Код постараюсь выложить на гитхаб если он станет для Вас лучше от этого :)
                                        А судить о качестве статьи по тому где выложен код, это как-то… странно :)
                                          +4
                                          Я о качестве оформительской работы, за которую автор комментария выше предлагает закрыть глаза на качество работы технической.
                                          А судить о качестве статьи по тому где выложен код, это как-то… странно :)
                                          Согласитесь, услышать про джаву, которая в очередных синтетических тестах чудным образом обогнала натив и не найти пруфы — это не менее странно.
                                            –2
                                            Я сам удивился, но думаю, что объяснение очень простое, как я уже написал выше, в JVM ввод-вывод лучше оптимизирован чем в Qt, вот и все. Тем более код есть желающие могут с ним поиграть.
                                              0
                                              Об этом кричат с тех пор, как для Java появился JIT-компилятор. Чтобы узнать, отличается ли ваши тесты от десятков других, нужно смотреть код, а скачивать его себе с гуглдрайва — это не удобно. Спасибо, что хоть так.
                                        +2

                                        Информация интересная, если принять её на веру. Но все тут люди опытные, к информации относятся критически и для многих (например для меня) множество пассажей выглядят очень сомнительными, как и полученные результаты. Статьи содержащие сомнительную информацию минусят, и это правильно.

                                          –1
                                          Я думаю, это вопрос перспективы. С одной стороны каждый имеет право поставить свой плюсик или минусик. Даже если их уже стоит 10, 100 или больше. Но с другой стороны, если минусиков стоит много — стоит ли ещё один добавлять? Может лучше поставить плюсики за понравившиеся критические комментарии?
                                          Тем более я посмотрел, это самая первая статья автора.
                                          Но это моё личное мнение. Я никому её не навязываю.
                                            –1
                                            Мне было бы интересно почитать конструктивную критику, к сожалению, ее здесь не много, в основном, пустое сотрясание воздуха.
                                              –1
                                              Другие коммениаторы внесли немало конструктивных предложений, как мне представлчется. Моя идея очень простая — если у статьи стоит уже 10 минусов, какой смысл ставить 11,12 ...120?
                                              Разумеется, если нет понравившихся комментариев, то и плюсики ставить некуда. Тогда может стоить подумать что в статье не понравилось и свой комментарий написать.
                                                –3
                                                Так тут, в основном, C++ перевозбудились. Призывают не пользоваться стандартным вводом, а прям системными вызовами шпарить. Мне это не интересно, и я уже написал почему.
                                              +2
                                              Может лучше поставить плюсики за понравившиеся критические комментарии?

                                              Для этого можно поставить плюсик конкретным критическим комментариям. А ставить оценку именно статье за комментарии в ней – ну это как минимум странно.

                                                +1
                                                Из чего Вы заключили, что я призываю ставить оценку статье за комментарии к ней?
                                                  0
                                                  Может лучше поставить плюсики за понравившиеся критические комментарии?

                                                  Перечитал эту фразу. Теперь сижу и думаю, что я дебил. Я вот её расценил почему-то сначала как "поставить + статье за комментарии". Извиняюсь за свой мозг, который почему-то таким образом информацию воспринял.

                                                    +1
                                                    Не наговаривайте на себя. К тому же — Вы не одинок. Поскольку ещё два читателя, поствившие плюсики за ваш комментарий, тоже видимо о том же подумали.
                                                      +1
                                                      Оценка за статью ставится статье, оценка за комментарий комментарию. И не надо К статье можно отнестить «нейтрально» — не поставить оценку, можно оценить как «хорошо» и как «плохо». И это три разных оценки. А в предлагаемом Вами подходе стирается разница между неудачной публикацией и откровенно плохой. Все таки разница -10 и -20 существенна, равно как и между +10 и +20.

                                                      Конечно, чтобы мнение было непредвзято, было бы здорово не видеть текущую оценку, до момента «голосования» или истечения срока голосования. Мне попадалось исследование, по итогу которого был сделан вывод, что люди ставят более охотно оценку которая совпадает с большинством. Но если не показывать текущую оценку статьи это может поломать систему, по которой статьи отбираются и показываются в лучшем. Так как если ты читаешь статью из лучшего — значит у нее высокая оценка, хотя ты не знаешь, может быть все статьи за выбранный период имеют отрицательную оценку. :) Так что, может быть, сокрытие оценки и было бы полезным.
                                                        +1
                                                        чтобы мнение было непредвзято, было бы здорово не видеть текущую оценку, до момента «голосования» или истечения срока голосования
                                                        А как же хайп вокруг сильно заплюсованных/заминусованных свежих статей?) ТМовцы не с проста спрашивали об этом не так давно.
                                                        Кмк, неплохо было бы показывать градиент оценок за некотороый крайний отрезок времи, а не абсолютное значение.
                                          +3
                                          Беглым взглядом находятся различия между джавовским кодом и С++
                                          например вместо
                                          mSegments.contains(segment.getClustId())
                                          нужно использовать find для получения идентичного поведения
                                          Объекты вы передаёте копиями — зачем? Можно по ссылке(как в джаве) или move. Я думаю это не все, но с телефона смотреть не удобно.
                                            –7
                                            Вполне возможно, что есть небольшие расхождения, код писался в урывками в свободное от работы время, но если вы убедите меня что это может существенно повлиять на перформанс я постараюсь исправить и обновить результаты.
                                            Вообще, я вроде старался активно использовать константные ссылки где можно. Возможности по перемещению из C++11, действительно не использовал.
                                              +5

                                              Да, это может существенно повлиять на результаты. Например, взять небольшой фрагмент кода из performer.cpp:


                                              if (mSegments.contains(segment.getClustId())) {
                                                  mSegments[segment.getClustId()] << segment;
                                              } else {
                                                  QList<DcfSegment> list;
                                                  list << segment;
                                                  mSegments[segment.getClustId()] = list;
                                              }

                                              Во первых, два поиска по мапу вместо одного (про это уже сказали). Но наиболее характерный код из ветки else, очень характерный для Java и ужасный для C++. По таким моментам очень легко заметить, что вы обычно пишите на Java и плохо разбираетесь в C++. Для джавы код вполне логичен — вы создаёте новый список и помещаете его в мап. Однако в C++ это будет выполняться так: вы создаёте сначала временный экземпляр класса, кладёте в него элемент, потом создаёте ещё один список внутри хэшмапа, присваиваете локальный список тому, что находится в хэшмапе, при этом по новой происходит выделение памяти в хипе и копирование всего содержимого (пусть это даже всего один элемент), после чего локальная копия уничтожается с освобождением памяти. Итого, у вас лишние поиски по хэшмапу, лишние копирования, и лишние операции с памятью, которые достаточно дорогие.


                                              Но важнее всего то, что здесь вообще не нужен if и ветвление. Создание нового списка происходит при вызове оператора []. Плюсовик написал бы вместо всего этого одну строчку, которая при этом и работала бы быстрее:


                                              mSegments[segment.getClustId()] << segment;
                                                –2
                                                Ну вот уже что-то :) но при всем уважении на хипе здесь ничего создаваться не будет, все на стеке.
                                                Если QHash не содержит ключа он создаст объект по дефолтному конструктору, что в нашем случае собственно и нужно. Хорошо поправлю, но не думаю что это существенно повлияет на результат. Потому что я проводил подобный эксперимент на Kotlin-е, делал сначала проверку ключа, потом подкладывал — на больших тестах разница была порядка 40-50ms.
                                                  +1
                                                  Тут речь была не про QHash а про QList, он будет внутри создавать элементы на куче.
                                                  0
                                                  на хипе здесь ничего создаваться не будет, все на стеке.
                                                  "QList will allocate its items on the heap unless sizeof(T) <= sizeof(void*)"
                                                  документация | сорцы
                                                    –2
                                                    Согласен, но это детали реализации QHash и QList, я говорил об объектах которые мы явно создаем в коде.
                                                      0
                                                      Изначально неправильно используется API коллекций, об этом пишут в документации. Я лишь показываю почему там так написано.
                                                    +1

                                                    Ну я исправил только этот момент и не стал смотреть дальше. Думаю, там есть ещё моменты в подобном ключе. Извините, но я не поверю, что правильно написанный плюсовый код медленнее, чем всё остальное.

                                                    0
                                                    QList<DcfSegment> list;
                                                    list << segment;
                                                    mSegments[segment.getClustId()] = list;
                                                    

                                                    QList использует implicit sharing, поэтому фактического копирования коллекции в данном случае не будет. По эффективности этот код аналогичен коду на java.
                                                      –1

                                                      Не писал под Qt, поэтому не знал этого нюанса. Спасибо за то, что просветили. Однако, интересно же, получается, Qt нарушает подход разделения функциональности. Список должен хранить. Если мне надо расшарить его я создам shared_ptr. А так, получается, нарушение основы плюсов — не платить за то, что тебе не нужно.

                                                        +2
                                                        Список и хранит. Поведение отличается от использования shared_ptr. Если Вы используете shared_ptr — то работаете всегда с одним и тем же экземпляром. А в Qt implicit sharing — это отложенное копирование. При копирование увеличивается внутренний счетчик. Если надо изменить объект на который «ссылается» несколько других переменных, то создается его копия, в нее вносятся изменения и эта переменная уже работает со своим собственным экземпляром.
                                                          0

                                                          Всё ещё выглядит как функциональность, которой не должно быть в обычном списке. Видимо, так работают все QT-ые контейнеры? Выглядит как попытка сделать что-то вроде Java в плюсах — накладные расходы, о которых не просит пользователь, в надежде что он не выстрелит себе в ногу.

                                                            0

                                                            Не только контейнеры. Думаю в Qt много найдется вещей которые можно посчитать, как то о чем не просит пользователь, но это их право. Qt это не просто библиотека, это фреймворк, практически полностью самодостаточная система. При работе с Qt можно забыть о стандартной библиотеке и пользоваться только тем что предоставляет Qt. И них свой взгляд на управление ресурсами — подразумевается, что все по максимуму создается в кучи, а за удаление отвечает родитель.
                                                            Является ли это попыткой сделать "Java в плюсах" — не знаю, не знаком с Java, больше похоже на успешный кросс платформенный вариант C++ Builder. Это если уж искать какие-то аналогии. Но, думаю, лучше рассматривать Qt как самостоятельный фреймворк, со своими правилами и хорошими техниками.

                                                +2
                                                Ваще не понял почему статью заминусовали. По-моему очень интересно. Автору респект и плюсик в карму!
                                                  –3
                                                  Спасибо!

                                                  Думаю тут дело в том, что выбор языка программирования это вопрос достаточно интимный, сродни выбору жены :), а при сравнении всем не угодишь, вот последователи разных языковых школ и размахались «минусовками». Ваш, коммент тоже, наверное, заминусуют :)
                                                    +5
                                                    Дело не в том что вы всем не угодили, а в том что это очередной нубо бенчмарк языков, в котором сравниваются даже не языки во многом а реализацию библиотек и IO. Лишь одна замена потоковго чтения файла в плюсах на чтение файла из памяти уже гарантирует огромный прирост производительности. Если в бенче java обгоняет C++ то вероятность того что код написан криво огромна (что в принципе так и есть судя по исходникам).
                                                      –1
                                                      В обзоре не было реализации на чистом C++, везде четко было прописано Qt/C++. Кроме голословных утверждений о «кривизне» кода дело не идет.
                                                        +1
                                                        А они не голословные выше вам уже показали пример вашей кривизны, а также вы в упор не видите что потоковое чтение из файла в С++, никогда не было быстрым, и тут не важно чистый С++ или Qt\C++ вы написали не оптимальный код и при этом говорите что в проседании скорости виноват язык, дело конечно ваше во что верить, но и удивляться тому что вас минусуют не стоит, как и прикрываться тем что вы «не угодили».
                                                          –1
                                                          Насчет «не угодил», это, конечно же, была шутка, а прикрываться мне не от чего собственно.
                                                          «Вашей кривизны» звучит как-то двусмысленно, будем считать, что это относится к коду :) я так же согласился что это косяк, но боюсь, что существенно на производительность это не повлияет (но надо будет проверить).
                                                          В Qt/C++ получились результаты такими какими получились, не вижу смысла там что-то менять, какая библиотека ввода — такой и результат.
                                                          Если кто-то напишет хорошую реализация на C++ можно добавить еще и ее для сравнения. Но меня больше интересовали языки с JVM.
                                                  +4
                                                  C# (MSVC2015) — вошел в обзор только потому, что мне довелось написать на нем немалое количество строк, и никаких преимуществ по сравнению с Java я в нем не обнаружил.

                                                  Вы видимо хеловорды писали.


                                                  В сишарпе есть:


                                                  • свойства
                                                  • нулабилити
                                                  • екстеншн функции
                                                  • async/await
                                                  • имутабельность
                                                  • удобная вариантность <in/out T>

                                                  Интересно, как Вы сравнивали?

                                                    0
                                                    Забыл про вывод типов
                                                      0
                                                      Тоже хорошая штука.
                                                      –4
                                                      Я его особо не сравнивал, он у меня отсеялся на стадии «кросплатформенность», хотя вон тут пишут про core.net, надо будет попробовать. Как я уже написал в статье мне он был больше интересен в аспекте производительности.
                                                      Из перечисленного Вами списка кое-чем пользовался: свойства, async/await, вариативностью. Еще там достаточно удобно форматировать строки $"".
                                                        +2

                                                        Вы пишите:


                                                        никаких преимуществ по сравнению с Java я в нем не обнаружил.

                                                        и тут же, в коментарии, вы пишите:


                                                        кое-чем пользовался: свойства, async/await, вариативностью.

                                                        отсюда вопрос — где правда? Как можно пользоваться свойствами и не заметить этого?

                                                          –4
                                                          Ну разве я где-то написал что не заметил свойства?
                                                          Правда в том, что считать преимуществом, и это уже достаточно субъективно. Безусловно в C# есть свои приятные плюшки, но я не занимался их детальным сравнением в статье, а написал свои общие впечатления о C# в сравнении с Java. Ведь, как известно, на вкус и цвет товарищей нет, кому-то нравится C#, кому-то Java, кому-то Basic…
                                                            +2

                                                            Ну Вы же пишите что:


                                                            никаких преимуществ по сравнению с Java я в нем не обнаружил

                                                            Я вам написал целый список преимуществ в сравнении с джава, вы говорите — да ими пользовался — я не понимаю логики. Вы не считаете это преимуществами?

                                                              –4
                                                              Хорошо, давайте так, я для себя вынес взвешенную оценку C# и в результате сумма его преимуществ и недостатков оказалось ближе к нулю или чуток отрицательной. Т.е. недостатки для меня перевесили преимущества.
                                                              Согласитесь что ваш список это тоже не абсолютная истина? Не все поголовно запишут это в преимущества. Кто-то скажет — свойства это круто! Кто-то нет. В той же Java можно реализовать часть этих фич через фреймворки если нужно.
                                                                +2
                                                                Кто-то скажет — свойства это круто! Кто-то нет

                                                                Ну теперь мне все понятно :)

                                                                  –3
                                                                  Ну вот вам, например, мнение:
                                                                  «Лично мне свойства не нравятся, и я был бы рад, если бы их поддержку убрали из Microsoft .NET Framework и сопутствующих языков программирования. Причина в том, что свойства выглядят как поля, на самом деле являясь методами.»
                                                                  Джеффри Рихтер
                                                                  ru.wikipedia.org/wiki/%D0%A1%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_C_Sharp_%D0%B8_Java#%D0%A1%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B0

                                                                  Как по мне так, например, такой достаточно типовой пример использования свойства в C#:
                                                                  public string Foo { get; set;}
                                                                  На Java можно записать просто
                                                                  public String foo;
                                                                  без накладных расходов на get; set; методы.

                                                                  Если же мы решили запихнуть в get и set какую-то более сложную логику, то нам все-равно придется добавлять приватную переменную и тогда Java пара getter/setter будет не намного хуже.
                                                                    0
                                                                    Я не знаю что на это ответить. Очевидно что у вас не хватает академической базы. Учитесь.
                                                                      –3
                                                                      Ну раз в ход пошла «академическая база» :) думаю не ошибусь если предположу что речь про:
                                                                      public String foo;

                                                                      Да, да, всех нас учили что нельзя шарить поле класса, только через методы доступа.
                                                                      А вы когда-нибудь задумывались почему так нужно делать?
                                                                      Основной аргумент как раз «академический», дескать нарушение инкапсуляции данных.
                                                                      А что разве тупые геттеры/сеттеры, которые только возвращают и только присваивают его не нарушают?
                                                                      В конце концов всем надоел этот шаблонный совершенно бессмысленный код и придумали свойства, чтобы это выглядело похожим просто на переменную.
                                                                      И тут я не могу не признать резонность довода Джеффри Рихтер. Смотришь в код, на первый взгляд вроде бы выглядит как обычное присваивание, а потом идешь в сеттер свойства и мать чесная, там «Война и мир», кода вагон и маленькая тележка.
                                                                      В более современных языках придумали «абстрактные атрибуты»:
                                                                      Kotlin, Scala:
                                                                      val foo: String
                                                                      Да, здесь компилятором будут сгенерированы get и set, но по мне это ничем не хуже дедовского:
                                                                      public String foo;

                                                                      P.S. Насчет того, что учиться всегда полезно и никогда не поздно, готов полностью согласиться, очевидно вам тоже не повредит :)
                                                                        +3
                                                                        нарушение инкапсуляции данных. А что разве тупые геттеры/сеттеры, которые только возвращают и только присваивают его не нарушают?

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

                                                                        Это всё выливается в то, что при изменении логики аксессоров даже не нужно перекомпилировать клиентские сборки, не говоря уже о необходимости грепать по исходникам клиента, чтобы воткнуть обёртку в каждом месте использования.

                                                                        без накладных расходов на get; set; методы.
                                                                        Методы могут инлайниться компилятором.
                                                                          –1
                                                                          Если нужен абстрактный атрибут или предполагается переопределение в наследниках, тогда да, не вариант.
                                                                          0
                                                                          В более современных языках придумали «абстрактные атрибуты»:
                                                                          Kotlin, Scala:
                                                                          val foo: String
                                                                          Да, здесь компилятором будут сгенерированы get и set, но по мне это ничем не хуже дедовского:
                                                                          public String foo;

                                                                          хуже, там приватное поле, и аксессоры (в вашем примере только геттер)
                                                                            –2
                                                                            очепятка :)
                                                                            var foo: String

                                                                            Если высока вероятность что в будущем придется изменить логику геттеров-сеттеров (т.е. отказаться от сгенерированного компилятором кода и явно написать код для get/set), тогда действительно хуже.
                                                          0
                                                          LINQ забыли ещё. Тоже классная штука.
                                                          +17
                                                          Мда… Мне ещё не приходилось писать столько отрицательных комментариев, к статье с вроде как правильной изначальной идеей — такого уникально низкого уровня реализации я давно не видел.

                                                          Для начала сразу же повеселила фраза «Т.е. маленькая програмулька, которая печатает в консоль тупую строчку и должна занимать от силы 3-4Кб весит мегабайты!» Ну так оно и весит мегабайты на практически всех языках, кроме разве что чистого C++. В той же Java это будет более 100 мегабайт (мы же будем по честному считать, включая рантайм, не так ли?). Причём эта фраза была в статье не просто так, а на её основание из тестирование убрали как раз самые интересные и перспективные языки.

                                                          На фоне предыдущего пункта меня сильно поразило наличие в тестирование C++/Qt, т.к. как раз Qt и является примером очень жирной библиотеки — тут было явно что-то не то. Но когда я увидел размер программы на Qt в 37 КБ, то всё стало на свои слова — автор похоже ещё и не особо разбирается в разнице между статической и динамической линковкой…

                                                          Так же слегка шокировали слова «обычные язык, без откровений» по отношению к Scala. И это про язык, который принёс полноценное функциональное программирование и метапрограммирование в мир JVM.

                                                          После всего этого на результаты тестов уже можно было и не смотреть особо… Гораздо интереснее было взглянуть на исходники. И в первую очередь на вариант с C++. Собственно как и ожидалось, там был классический «java стиль», тот самый, который не позволяет писать быстродействующее ПО на C++. Если же решить эту простейшую задачку на нормальном современном C++ (и для начала это будет Boost, а не Qt), то она будет и в разы быстрее и в разы меньше кода.

                                                          В итоге статье крайне не понравилась огромным числом ляпов, не говоря уже о смешных итоговых результатах.
                                                            +1

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

                                                              –1
                                                              Хабр уже не торт? :)
                                                              –6
                                                              Мда… Мне ещё не приходилось писать столько отрицательных комментариев, к статье с вроде как правильной изначальной идеей — такого уникально низкого уровня реализации я давно не видел.

                                                              Ну это Ваша, абсолютно субъективная точка зрения совершенно ничем не подкрепленная. На это можно ответить только что-нибудь типа «я давно не видел комментария с таким высоким уровнем предвзятости и фанатизма».

                                                              Для начала сразу же повеселила фраза

                                                              Ну ладно хоть развеселило, но по мне так это грустно.
                                                              Во-первых, JVM бывают разные, есть очень маленькие.
                                                              Во-вторых, в JVM логика программы четко отделена от рантайма языка.
                                                              В-третьих, JVM портирован почти везде, так что можно считать его частью системы.

                                                              Раз уж это моя статья позвольте мне и решать кого записывать в перспективные. Напишите свою — с удовольствием почитаю.

                                                              На фоне предыдущего пункта меня сильно поразило наличие в тестирование C++/Qt, т.к. как раз Qt и является примером очень жирной библиотеки — тут было явно что-то не то.

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

                                                              Но когда я увидел размер программы на Qt в 37 КБ, то всё стало на свои слова — автор похоже ещё и не особо разбирается в разнице между статической и динамической линковкой…

                                                              А мне кажется что Вы слегка забываетесь и переходите на личности. Как я уже писал в Qt я использовал дефолтный профиль Release ничего не меняя. И Qt, естественно, использовал динамическую линковку, это нормально и правильно.

                                                              Так же слегка шокировали слова «обычные язык, без откровений» по отношению к Scala. И это про язык, который принёс полноценное функциональное программирование и метапрограммирование в мир JVM.

                                                              За функциональное программирование в статье ничего не было. Мне как-то Haskell-а вполне хватает.

                                                              Собственно как и ожидалось, там был классический «java стиль»

                                                              Да нет там никакого «Java стиля» обычный Qt-шный код.

                                                              Если же решить эту простейшую задачку на нормальном современном C++ (и для начала это будет Boost, а не Qt),

                                                              Код в студию, пожалуйста, только не в С-style.
                                                                +5
                                                                Раз уж это моя статья позвольте мне и решать кого записывать в перспективные.

                                                                Это немного не так работает.


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

                                                                  –2
                                                                  Это я к тому что в статье я написал так как посчитал нужным и не собираюсь ее менять, а в коментах само собой можно пообщаться.
                                                                  +2
                                                                  Во-первых, JVM бывают разные, есть очень маленькие.

                                                                  Меньше получаемого в Rust/D/Nim исполняемого файла под той же платформой? )

                                                                  В-третьих, JVM портирован почти везде, так что можно считать его частью системы.

                                                                  Похоже кто-то тут путает кроссплатформенность (имеется не только у JVM, а много где, включая и Rust/D/Nim) и предустановленный в данной ОС рантайм. Я что-то не слышал про предустановленный рантайм Java на Windows или OSX или Linux…

                                                                  Раз уж это моя статья позвольте мне и решать кого записывать в перспективные. Напишите свою — с удовольствием почитаю.

                                                                  Выбирать критерии отбора языков — это безусловно авторское дело. Однако, даже если использовать для этого такой странный по нынешним временам (если конечно речь не про МК) параметр, как размер получаемого дистрибутива, то всё равно это надо делать честно (учитывая весь рантайм). Именно это один из главных недостатков статьи, просто бросающийся в глаза своей некорректностью.

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

                                                                  Ха, совсем неудивительна симпатия Java-программиста к Qt. Только вот надо понимать, что это совсем не путь развития современного C++. Qt родилась в 90-ые (как раз одновременно с Java) и вся её архитектура из тех времён. Сейчас мир C++ уже далеко ушёл от этого в совсем другую сторону и данный Java-стиль является откровенным legacy. Конечно авторы Qt понемногу пытаются исправить эту ситуацию, но пока выходит очень слабо.

                                                                  Да нет там никакого «Java стиля» обычный Qt-шный код.

                                                                  )))

                                                                  Код в студию, пожалуйста, только не в С-style.

                                                                  Накидал сейчас для развлечения на нормальном C++ (с Boost'ом вместо Qt) программку с полностью аналогичной функциональностью. Значит получился один файл исходников из 70 строк/2,4 КБ, причём 1/3 файла занимают подключения заголовочных файлов и пространств имён. Исполняемый файл при полной (включая стандартную библиотеку языка, т.е. такой exe можно спокойно распространять везде в одиночку) статической линковке на 64-ёх битной Windows занимает 1 МБ. Время работы в 1,5 раза меньше, чем у приведённого в статье Java кода, что в общем то и ожидалось изначально.
                                                                    0
                                                                    Жаль akornilov вам не сможет ответить. А вы не смотрели примеры для котлина?
                                                                      –3
                                                                      Да почему же не смогу? :) Отвечаю.
                                                                      Отрадно что человек сел и написал код, все лучше чем слюной брызгать :)
                                                                      Ежели он его еще и опубликует и он окажется адекватным, я добавлю его в тесты и будет у нас полный комплект: современный C++ :)

                                                                      P.S. Вероятно, товарищ начитался Скотта Майерса, раз уж про «современность» древнего C++ заговорил :)
                                                                        0
                                                                        «современность» древнего C++

                                                                        Это о чём?

                                                                          +2
                                                                          Новые стандарты выходят каждые 3 года и использование новых стандартов и значит писать на современном С++.
                                                                          Ваш кэп.
                                                                          +1
                                                                          Только посмотрел так сказать для общего развития. С самим этим языком я раньше дел не имел, так что ни запускать, ни проверять уровень кода особой возможности не имею.

                                                                          Кстати, как раз благодаря просмотру кода на разных языках неожиданно (изначально я этого не заметил) оказалось, что автор статьи ещё и смухлевал немного — код разный (принципиально, а не из-за особенности языка) на разных языках. Детали опишу в другом комментарии (ниже).
                                                                          0
                                                                          Раньше в MacOS точно был встроенный рантайм Java, в новых возможно есть.
                                                                            0
                                                                            Да и в Линухе open-jdk, обычно, при установке в качестве зависимостей затягивается.
                                                                            +3
                                                                            Значит получился один файл исходников из 70 строк/2,4 КБ, причём 1/3 файла занимают подключения заголовочных файлов и пространств имён.

                                                                            Зачем описывать словами, когда можно просто показать код?
                                                                              0
                                                                              Потому что в обсуждаемой статье приведены именно эти метрики, в качестве параметров сравнения реализаций на разных языках.
                                                                                0
                                                                                Но код вы не покажете?) Интересно было бы сравнить подходы с авторскими.
                                                                                  0
                                                                                  См. конец этого habrahabr.ru/post/345100/#comment_10580696 комментария. Правда хабр слегка испортил там переносы строк, но думаю можно разобраться. )))
                                                                              –4
                                                                              Меньше получаемого в Rust/D/Nim исполняемого файла под той же платформой? )

                                                                              Исполняемый файл будет больше чем jar, но зато в нем будут все «кишки» языка :) если прибавить рантайм Java то он будет весить больше.
                                                                              Вам самому-то не надоело это муслоить? :) Вроде бы очевидные вещи.
                                                                              Совершенно не хочется пересказывать ту часть статьи другими словами — кратко «жирные» бинари на мой взгляд это не эстетично, думаю тут есть простор для оптимизации, не более того. А вышеупомянутые языки отсеялись по многим другим факторам, в частности:

                                                                              Похоже кто-то тут путает кроссплатформенность (имеется не только у JVM, а много где, включая и Rust/D/Nim) и предустановленный в данной ОС рантайм.


                                                                              А похоже кто-то очень любит поумничать :) ну да ладно все мы тут не без греха :)
                                                                              Думаю что JVM портирован на большее количество платформ чем тот же Nim и Rust — это кроссплатформенность. Да и со стабильностью в JVM все будет почетче.

                                                                              Сейчас мир C++ уже далеко ушёл от этого в совсем другую сторону и данный Java-стиль является откровенным legacy

                                                                              Спорное утверждение, дизайн проверенный временем доказал свое право на существование.

                                                                              Накидал сейчас для развлечения на нормальном C++

                                                                              Отлично, код в студию! :)
                                                                                +4
                                                                                Исполняемый файл будет больше чем jar, но зато в нем будут все «кишки» языка :) если прибавить рантайм Java то он будет весить больше.
                                                                                Вам самому-то не надоело это муслоить? :) Вроде бы очевидные вещи.


                                                                                Если это действительно очевидные вещи, то тогда солидный кусок обсуждаемой статьи надо бы выкинуть… )))

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

                                                                                Это уже не инженерные аргументы, а какие-то личные фобии.

                                                                                Думаю что JVM портирован на большее количество платформ чем тот же Nim и Rust — это кроссплатформенность. Да и со стабильностью в JVM все будет почетче.

                                                                                Вообще то Nim компилируется в C++ (который априори более кроссплатформенный, чем любые обсуждаемые тут языки). А что касается Rust'а, то например это второй язык (после C++), который имеет возможность написания кода для платформы WebAssembly (будущее нагруженного web'a), что является недостижимым для JVM в данный момент.

                                                                                Спорное утверждение, дизайн проверенный временем доказал свое право на существование.

                                                                                Любители Кобола говорили также… )))

                                                                                Отлично, код в студию! :)

                                                                                Сейчас будет, но перед этим хочу заметить, что из-за создания своего варианта, я более внимательно посмотрел на представленные и заметил откровенные махинации. Странно что никто больше их не заметил. А именно, у класса DcfSegment (именно его экземпляры создаются миллионами в тесте) в Java реализации имеется функция getLength(), которая вычисляет длину сегмента при своём вызове (т.е. никогда в данном тесте) на базе значений конечных точек. В тоже время аналогичная функция из класса DcfSegment в C++ реализации возвращает значение поля mLength (которого вообще нет в Java реализации), которое вычисляется в конструкторе класса. Т.е. в C++ варианте не только имеем лишнее поле, но и дополнительные тяжёлые вычисления при каждом конструирование такого объекта. И это называется тестом производительности? Скорее похоже на откровенную махинацию…

                                                                                Ну а что касается варианта на современном C++, то выкладывать весь проектик на какие-то ресурсы мне лень, так что кину исходник прямо в этом комментарии (обрезав инклуды с неймспейсами, чтобы покомпактнее было):
                                                                                код
                                                                                constexpr double R=5000.0;
                                                                                
                                                                                struct position{
                                                                                	double lat;
                                                                                	double lon;
                                                                                };
                                                                                double distance(const position& p1, const position& p2)
                                                                                {
                                                                                    const double sin_lat=sin((p2.lat-p1.lat)*M_PI/360.0);
                                                                                    const double sin_lon=sin((p2.lon-p1.lon)*M_PI/360.0);
                                                                                    const double a=sin_lat*sin_lat+cos(p1.lat*M_PI/180.0)*cos(p2.lat*M_PI/180.0)*sin_lon*sin_lon;
                                                                                    return 2.0*atan2(sqrt(a), sqrt(1.0-a));
                                                                                }
                                                                                struct segment{
                                                                                	position begin;
                                                                                	position end;
                                                                                };
                                                                                unordered_map<string, list<segment>> segments;
                                                                                
                                                                                void on_new_segment(const segment& s, const string& id)
                                                                                {
                                                                                	static position p=s.begin;
                                                                                	if(distance(p, s.begin)<R||distance(p, s.end)<R) segments[id].push_back(s);
                                                                                }
                                                                                
                                                                                void on_error(const string& s) {wcout<<"Invalid DCF line: "<<s<<endl;}
                                                                                
                                                                                int main(int argc, char *argv[])
                                                                                {
                                                                                	auto_cpu_timer timer;
                                                                                	if(argc<2) return 1;
                                                                                	error_code ec;
                                                                                	for(directory_iterator i(argv[1], ec), e; i!=e; i++){
                                                                                		if(!is_regular_file(i->status())||i->path().extension()!=".dcf") continue;
                                                                                		wcout<<"Processing '"<<i->path().filename()<<"'..."<<endl;
                                                                                		mapped_file_source file(i->path());
                                                                                		double lat1, lon1, lat2, lon2;
                                                                                		string id;
                                                                                		parse(file.data(), file.data()+file.size(),
                                                                                			*(("SEG:">>double_[ref(lat1)=_1]>>':'>>double_[ref(lon1)=_1]>>':'>>double_[ref(lat2)=_1]>>':'>>double_[ref(lon2)=_1]>>':'>>
                                                                                			*("ClustID:">>(+(char_-eol-':'))[([&](auto& s){id={begin(s), end(s)};})]>>':'|+(char_-eol-':')>>':')>>eol)
                                                                                			[([&]{on_new_segment(segment{{lat1, lon1}, {lat2, lon2}}, id);})]|
                                                                                			("SEG:">>+(char_-eol))[([&](auto& s){on_error({begin(s), end(s)});})]>>eol|
                                                                                			+(char_-eol)>>eol));
                                                                                	}
                                                                                	wcout<<"Found "<<segments.size()<<" segments"<<endl;
                                                                                }
                                                                                

                                                                                  –3
                                                                                  Если это действительно очевидные вещи, то тогда солидный кусок обсуждаемой статьи надо бы выкинуть… )))

                                                                                  Размеры файлов и рантаймов вещи очевидные, а вот выводы которые я из них делаю это совсем другое, так что ничего выкидывать не будем :)

                                                                                  Это уже не инженерные аргументы, а какие-то личные фобии.

                                                                                  Недостаток оптимизации по размеру файла вполне себе аргумент, не знал что это фобия :)

                                                                                  Вообще то Nim компилируется в C++

                                                                                  Даже если он и компилируется в C++ давайте не будем забывать о жирном рантайме с кучей системных вызовов, без портирования их на новую платформу вы этот код не перенесете.

                                                                                  Любители Кобола говорили также…

                                                                                  Мало ли кто так говорил, от этого мысль не становиться хуже.

                                                                                  Сейчас будет, но перед этим хочу заметить, что из-за создания своего варианта, я более внимательно посмотрел на представленные и заметил откровенные махинации.

                                                                                  О, вот за то что обнаружили эту багу респект вам и уважуха! :) вот что значит когда от чесания языком люди переходят к делу. Это действительно существенное замечание.
                                                                                  Только попросил бы вас впредь быть поосторожнее с терминологией и избегать навешивания ярлыков типа «махинация». Это была большая небрежность с моей стороны, признаю, но в конце концов я именно для этого и выложил исходники чтобы все могли посмотреть и указать на ошибки.

                                                                                  Исправил и сразу прогнал тест на Debian-е: Java идет прямо вровень со Scala. Погоняю побольше, обновлю результаты.

                                                                                  Сейчас будет, но перед этим хочу заметить, что из-за создания своего варианта, я более внимательно посмотрел на представленные и заметил откровенные махинации.

                                                                                  Да и не надо утруждаться :) все равно это не годится. Смысл был в том чтобы на всех языках иметь одинаковую структуру приложения и классов. Чтобы затраты на создание и уничтожение классов тоже учитывались. Но за старания спасибо :)
                                                                                    +4
                                                                                    Недостаток оптимизации по размеру файла вполне себе аргумент, не знал что это фобия :)

                                                                                    Если сравнивать статически скомпонованные нативные исполняемые файлы, то да, это нормально. К примеру если для решения одной и той же задачи статически скомпонованное приложение на C++ занимает 1 МБ, а на C++/Qt 7 MB, то вполне могут возникнуть вопросы об оптимизации Qt по данному вопросу. Однако если начинать сравнивать ещё и динамическую компоновку, причём беря в расчёт исключительно размер исполняемого файла (и наплевать, что рядом с ним валяется dll в 100 раз большего размера), то это уже становится чем-то из области психиатрии…

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

                                                                                    И статья и исходный код отлично гармонируют между собой по наличию ошибок. Однако если относительно исходного кода вы их признаёте, то относительно самой статьи почему-то аналогичных выводов нет…

                                                                                    Да и не надо утруждаться :) все равно это не годится. Смысл был в том чтобы на всех языках иметь одинаковую структуру приложения и классов. Чтобы затраты на создание и уничтожение классов тоже учитывались. Но за старания спасибо :)

                                                                                    Хы, это же C++, язык основной концепций которого является нулевая цена абстракций. Можно навернуть там ещё хоть 150 классов типа Perfomer и от этого не только не поменяется производительность, но и даже не поменяется сам код (с точностью до бита) — компилятор просто выкидывает все эти лишние уровни абстракции в процессе оптимизации.

                                                                                    Ну и да, в любом случае не стоит применять архитектуру приложения происходящую из языков с навязанным ООП (типа Java, C# и т.п.) к полноценным мультипарадигменным языкам. Тем более, что современный C++ всё больше уходит от ООП в сторону функциональных стилей и т.п.
                                                                                      –2
                                                                                      то это уже становится чем-то из области психиатрии…

                                                                                      Вы бы уже определились с амплуа в котором решили выступать :) если как психиатр, то могу лишь заметить, что ваши посты временами отдают маниакально депрессивным психозом :) (но, если серьезно, давайте уже заканчивать с этим флудом, лень время тратить).
                                                                                      Если все-таки как C++шник, то давайте попробуем дожевать так взволновавший вас вопрос своей мнимой некорректностью:
                                                                                      HelloWord в Qt, в дефолтном Release будет весить около 10Кб (динамическая линковка).
                                                                                      Ни в Nim-е, ни в Rust-е у вас даже близко не будет ни с динамической линковской, ни тем более в дефолтной конфигурации.
                                                                                      Т.е. очень много вспомогательного кода попадает в бинарь и, например, при любых исправлениях/обновлениях в системных функциях языка вам нужно будет перебилживать приложение.
                                                                                      Все это плохо, и это мое мнение.
                                                                                      Но, как я уже неоднократно писал, языки эти отсеялись по многим другим факторам, а совсем не только по размеру бинаря.

                                                                                      И статья и исходный код отлично гармонируют между собой по наличию ошибок. Однако если относительно исходного кода вы их признаёте, то относительно самой статьи почему-то аналогичных выводов нет…

                                                                                      Гармонируют… но разве что в вашем воображении :)
                                                                                      Все очень просто, реальные ошибки я охотно признаю, а всякие «фобии» сразу же идут в сад :)
                                                                                      Не следует упускать из виду очень простой факт: все адекватные замечания, которые здесь прозвучали, качественно не влияют на результат бенчмарков. Поэтому их ценность невелика.
                                                                                      Кроме вашего, это действительно важное замечание, моя ошибка позволила Java уйти вперед, но я это исправлю :)

                                                                                      Хы, это же C++, язык основной концепций которого является нулевая цена абстракций. Можно навернуть там ещё хоть 150 классов типа Perfomer и от этого не только не поменяется производительность, но и даже не поменяется сам код (с точностью до бита) — компилятор просто выкидывает все эти лишние уровни абстракции в процессе оптимизации.

                                                                                      Верите в добрый и могущественный Компилятор? Который вас всегда поймет, исправит все ошибки и сгенерирует самый современный и самый быстрый код на свете? :)
                                                                                      А в Деда Мороза верите? :)

                                                                                      Классы в C++ это вполне реальные, а не эфемерные сущности, они создаются, удаляются, для них вызываются конструкторы/деструкторы/методы. На все это тратится вполне конкретное машинное время, и компилятор далеко не всегда сможет выполнить эффективную оптимизацию.
                                                                                      Когда классы уже скомпилированы и положены, например, в динамическую библиотеку никакой оптимизации при использовании этой библиотеки (во время компиляции приложения) в вашем приложении уже не будет.
                                                                                      Если классы в статической библиотеке, то в общем случае тоже, разве что вы не пользуетесь компилятором от Intel с включенным IPO.

                                                                                      Ну и да, в любом случае не стоит применять архитектуру приложения происходящую из языков с навязанным ООП (типа Java, C# и т.п.) к полноценным мультипарадигменным языкам.

                                                                                      Я думаю что не стоит всерьез обсуждать «архитектуру» тестовых примеров. Понятно, что поставленную задачу можно решить гораздо проще. Фишка в том, что задача, которую они решают на самом деле фейковая. Нам интересно другое, насколько быстро они с ней справятся. Но тем не менее мне, все же, хотелось чтобы это хоть от части походило на реальное приложение.

                                                                                      Тем более, что современный C++ всё больше уходит от ООП в сторону функциональных стилей и т.п.

                                                                                      Мир все время куда-то движется, это не новость. Но никогда нельзя заранее сказать какие технологии приживутся, а какие отправятся в мусорный бак.
                                                                                        +5
                                                                                        HelloWord в Qt, в дефолтном Release будет весить около 10Кб (динамическая линковка).
                                                                                        Ни в Nim-е, ни в Rust-е у вас даже близко не будет ни с динамической линковской, ни тем более в дефолтной конфигурации.

                                                                                        Ну а теперь посмотрим на реальность… Для примера возьмём скомпилированные для windows 64 бита приложения «hello world»:

                                                                                        C++ static: 832 KБ (exe) + 0 KБ (dll) = 832 KБ
                                                                                        C++ dynamic: 16,5 KБ (exe) + 1510,5 KБ (dll) = 1527 KБ
                                                                                        C++/Qt static: 4109 KБ (exe) + 0 KБ (dll) = 4109 KБ
                                                                                        C++/Qt dynamic: 17 KБ (exe) + 7378 KБ (dll) = 7395 KБ
                                                                                        D static: 565 KБ (exe) + 0 KБ (dll) = 565 KБ
                                                                                        Rust static: 2305 KБ (exe) + 0 KБ (dll) = 2305 KБ
                                                                                        Java dynamic: 0,4 КБ (class) + 158418,6 КБ (jre) = 158419 КБ

                                                                                        Я думаю из этих данных вполне очевидно преимущество статической линковки над динамической (конечно при условии, что у нас в итоговом приложение один exe файл), а так же реальная жирность Java и Qt решения.

                                                                                        Т.е. очень много вспомогательного кода попадает в бинарь и, например, при любых исправлениях/обновлениях в системных функциях языка вам нужно будет перебилживать приложение.
                                                                                        Все это плохо, и это мое мнение.

                                                                                        Вот бредовость этого мнения тут и обсуждается. Оно неверно потому, что даже если уж и принимать в расчёт занимаемое на диске место (хотя в наше время больших дисков и быстрого интернета это всё давно стало неактуальным), то это должен быть размер дистрибутива приложения, а не размер исполняемого файла.

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

                                                                                        Никаких других внятных причин я в статье не увидел.

                                                                                        Классы в C++ это вполне реальные, а не эфемерные сущности, они создаются, удаляются, для них вызываются конструкторы/деструкторы/методы. На все это тратится вполне конкретное машинное время, и компилятор далеко не всегда сможет выполнить эффективную оптимизацию.
                                                                                        Когда классы уже скомпилированы и положены, например, в динамическую библиотеку никакой оптимизации при использовании этой библиотеки (во время компиляции приложения) в вашем приложении уже не будет.

                                                                                        Мы обсуждаем не абстрактный код в вакууме, а вполне конкретный тестовый пример. И моё конкретное утверждение о том, что если добавить в мою реализацию этого теста никчемные классы dcf_file и perfomer (остальные классы у меня присутствуют аналогично решению из статьи), то время исполнения теста не изменится. Есть желание оспорить это утверждение? )))

                                                                                        Если классы в статической библиотеке, то в общем случае тоже, разве что вы не пользуетесь компилятором от Intel с включенным IPO.

                                                                                        Вообще то это доступно во всех известных компилятора уже несколько десятилетий. ))) Только в остальных это называется LTO.

                                                                                          –3
                                                                                          Я думаю из этих данных вполне очевидно преимущество статической линковки над динамической

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

                                                                                          то это должен быть размер дистрибутива приложения, а не размер исполняемого файла.

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

                                                                                          Я предпочитаю в бинаре приложения иметь логику в чистом виде с минимально необходимыми примесями из рантайма.
                                                                                          В вашем примере в Java самый «чистый» бинарь. Такой подход позволяет свободно менять рантайм языка без перекомпиляции приложения.
                                                                                          Неужели Rust-у реально нужно 2305KБ кода чтобы напечатать в консоль строчку? :)

                                                                                          Никаких других внятных причин я в статье не увидел.

                                                                                          Вот в этом и дело, что много пустых споров рождаются на ровном месте, когда «слышат звон, да не знают где он» :)

                                                                                          Nim, Rust:
                                                                                          — жирные бинари (смесь логики и рантайма)
                                                                                          — кросплатформенность
                                                                                          — стабильность рантайма

                                                                                          Rust:
                                                                                          — объектно-ориентирование программирование не поддерживается (да-да, есть альтернативы, я в курсе)

                                                                                          Num:
                                                                                          — нет полноценной поддержки интерфейсов

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

                                                                                          Мы обсуждаем не абстрактный код в вакууме, а вполне конкретный тестовый пример.

                                                                                          А… ну ладно тогда, а то вы тут было впали в какую-то блаженную эйфорию, 150 классов и т.д. :)

                                                                                          Есть желание оспорить это утверждение? )))

                                                                                          Глупо спорить, тут надо проверять. Но мне, естественно, лень будет гонять два варианта, поэтому в релиз может войти только версия с полным набором классов.
                                                                                            +2
                                                                                            Этот азбучный момент в статье, естественно, не затрагивался, но если кратко то динамическая компоновка должна использоваться всегда когда можно, а статическая только в редких специфических случаях.

                                                                                            О, очередное шедевральное высказывание в дополнение к статье… Конечно же зачем нам статическая компоновка, если в ней нет ни замедления работы, ни раздувания дистрибутива, и главное в ней нельзя насладится такой очаровательной вещью, характерной для динамической компоновки, как dll hell.

                                                                                            Такой подход позволяет свободно менять рантайм языка без перекомпиляции приложения.

                                                                                            Осталось только уточнить одну «мелочь»: кому и зачем это вообще надо? )))

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

                                                                                            Что-то не увидел описания причин выбывания языка D.

                                                                                            Что касается Rust'а, то ему действительно можно предъявить определённые претензии, являющиеся следствием молодости (т.е. процесса активной разработки и не до конца установившимися концепциями) языка. Однако говорить о недостаточной кроссплатформенности Rust довольно смешно, т.к. там в роли бэкенда работает llvm (предлагаю посмотреть на список доступных платформ).

                                                                                            А… ну ладно тогда, а то вы тут было впали в какую-то блаженную эйфорию, 150 классов и т.д. :)
                                                                                            150 классов типа perfromer точно так же никак и один такой класса нисколько не изменят производительность данного теста.

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

                                                                                            Ну кому-то возможно и надо проверять, а кому-то достаточно знаний о работе компиляторов C++… )))
                                                                                              –4
                                                                                              О, очередное шедевральное высказывание в дополнение к статье… Конечно же зачем нам статическая компоновка, если в ней нет ни замедления работы, ни раздувания дистрибутива, и главное в ней нельзя насладится такой очаровательной вещью, характерной для динамической компоновки, как dll hell.

                                                                                              Динамическая или статическая компоновка это всего лишь инструмент в арсенале разработчика и им нужно уметь пользоваться.
                                                                                              «dll hell» это следствие неразумного использования динамического связывания и было возможно только в бестолково спроектированных системах. Т.е. это проблема системы, а не самой технологии связывания. Модульность (или пакеты) с зависимостями на определенные версии других модулей/пакетов прекрасно работает.
                                                                                              Я вижу у вас возникает много вопросов на эту тему… В статье речь идет о сравнении ЯП, а не об тонкостях использования того или иного связывания. Это оффтоп, предлагаю вам все-таки воспользоваться гуглом или почитать специальную литературу.

                                                                                              Осталось только уточнить одну «мелочь»: кому и зачем это вообще надо? )))

                                                                                              А если подумать? :)
                                                                                              В первую очередь, конечно же, пользователям приложений.
                                                                                              Зачем им его перестраивать при выходе новой версии Java?
                                                                                              Скомпилированный бинарь будет прекрасно работать на новой версии JVM, а может быть еще и быстрее если разработчики ее оптимизировали. Или вообще на другой JVM и все это без перекомпиляции.
                                                                                              Или зачем пользователем приложения на C++ его перекомпилировать (и потом не все же приложения open source), если создатели C++, например, взяли и поменяли имплементацию unordered_map (исправили баги, оптимизировали).

                                                                                              Что-то не увидел описания причин выбывания языка D.

                                                                                              Да все те же:
                                                                                              — жирные бинари (смесь логики и рантайма)
                                                                                              — кросплатформенность
                                                                                              — стабильность рантайма

                                                                                              Тем не менее в D меня заинтересовала возможность компиляции в LLVM: github.com/ldc-developers/ldc
                                                                                              Но, к сожалению, эта ветка развивается не очень активно, и у меня полезли какие-то странные баги при запуске скомпилированного бинаря, например под Linux на Windows и наоборот. В общем до стабильной работы там похоже должны пройти еще десятилетия.

                                                                                              Однако говорить о недостаточной кроссплатформенности Rust довольно смешно, т.к. там в роли бэкенда работает llvm (предлагаю посмотреть на список доступных платформ).

                                                                                              Мы вроде проходили уже это?
                                                                                              Совсем не важно во что эти языки умеют компилироваться в C/C++ или LLVM. В их случае важнее на сколько платформ портирован их «жирный» рантайм.
                                                                                                +3
                                                                                                Воу лол
                                                                                                Или зачем пользователем приложения на C++ его перекомпилировать (и потом не все же приложения open source), если создатели C++, например, взяли и поменяли имплементацию unordered_map (исправили баги, оптимизировали).

                                                                                                Это как бы шаблон, и он не крутится в рантайме как и вся библиотека stl в принципе. Ну и да реализация stl зависит от производителя компиля и только, создатели С++ никак не могут повлиять на имплементацию, только на интерфейс.
                                                                                                Забавно читать, что вы считаете динамическую линковку лучше статической, для разных задач разные требования. Если бы динамическая линковка была бы всегда лучше то статическая вымерла бы, а получается либо мир программирования неправ либо вы не достаточно компетентны в этом вопросе.
                                                                                                  –4
                                                                                                  создатели С++ никак не могут повлиять на имплементацию, только на интерфейс.

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

                                                                                                  Забавно читать, что вы считаете динамическую линковку лучше статической, для разных задач разные требования.

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

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

                                                                                                  достаточно компетентны в этом вопросе.

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

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

                                                                                                    Не ваши ли слова?
                                                                                                    если кратко то динамическая компоновка должна использоваться всегда когда можно, а статическая только в редких специфических случаях.

                                                                                                    Дело в том что статическая линковка это не спецефичный случай, если мы рассматриваем С++ то это даже более желательный способ линковки.
                                                                                                    Достаточно, если вы не будете передергивать мои ответы в свою пользу.

                                                                                                    Возможно, в плане вашего отношения к линковке вас неправильно поняли конечно, но в плане С++ вы точно являетесь не компетентным (шаблоны в рантайме мда)
                                                                                                      –4
                                                                                                      Повторяю в рантайме впринципе не может быть шаблонов stl и как следстви никакой речи о бинарной совместимости и быть не может.

                                                                                                      При чем здесь шаблоны? Вы сами начали о них говорить, «ни к селу ни к городу» :)
                                                                                                      Я говорил о рантайме C++ в целом.
                                                                                                      Вы утверждаете что он целиком статический?
                                                                                                      Если да, то вы сами недостаточно компетентны чтобы судить об этом.
                                                                                                      Если нет, то почему, по вашему мнению, динамическая часть не может быть изменена с сохранением бинарной совместимости?

                                                                                                      Не ваши ли слова?

                                                                                                      Мои. А вы видите разницу между «лучше» и «должна использоваться»?

                                                                                                      Дело в том что статическая линковка это не спецефичный случай, если мы рассматриваем С++ то это даже более желательный способ линковки.

                                                                                                      Нет. Способ линковки не связан с языком как таковым. Тот же gcc линкует по умолчанию динамически, пока вы не добавите специальный ключ. И делать это нужно в очень редких случаях.

                                                                                                      С++ вы точно являетесь не компетентным (шаблоны в рантайме мда)

                                                                                                      :))) боюсь что это у вас явные проблемы с компетенцией.
                                                                                                      P.S. Давайте уже без этих детских «дурак — сам дурак». Если есть, что написать по делу пишите, а свои субъективные оценки оставьте при себе.
                                                                                                        +2
                                                                                                        При чем здесь шаблоны? Вы сами начали о них говорить, «ни к селу ни к городу» :)

                                                                                                        Эм…
                                                                                                        Или зачем пользователем приложения на C++ его перекомпилировать (и потом не все же приложения open source), если создатели C++, например, взяли и поменяли имплементацию unordered_map (исправили баги, оптимизировали

                                                                                                        В рантайме есть не только шаблоны

                                                                                                        Вы точно уверены что это я начал?
                                                                                                        Если нет, то почему, по вашему мнению, динамическая часть не может быть изменена с сохранением бинарной совместимости?

                                                                                                        Я говорил исключительно про шаблоны, а это практически весь stl.
                                                                                                        Мои. А вы видите разницу между «лучше» и «должна использоваться»?
                                                                                                        А чем ещё может мотивироваться использование её если это может быть не лучшее решение?
                                                                                                        Тот же gcc линкует по умолчанию динамически, пока вы не добавите специальный ключ.
                                                                                                        Неужели? А я вот всё время думал что тип линковки зависит не от компилятора а от того каким образом была собрана библиотека. А оно вон как оказывается без специального ключа gcc динамическую библиотеку не сможет подключить.
                                                                                                        Если есть, что написать по делу пишите, а свои субъективные оценки оставьте при себе.

                                                                                                        Ды какие уж субъективные когда вы раз за разом утверждаете про шаблоны в рантайме.
                                                                                                          –5
                                                                                                          Вы точно уверены что это я начал?

                                                                                                          В диалоге с вами я уже ни в чем не уверен :) вы или вправду на «своей волне» и вещаете о чем-то своем или нарочно, пардон, дурака валяете :)

                                                                                                          Давайте попробуем синхронизироваться (если у вас конечно нет цели просто пофлудить :) )
                                                                                                          Я говорил исключительно про шаблоны, а это практически весь stl.

                                                                                                          А зачем вы говорите про шаблоны когда речь совсем о другом? Это вероятно что-то личное? Любите их очень? :)
                                                                                                          Я попытался донести до вас (точнее даже не до вас, но вы тоже решили поучаствовать в обсуждении) очень простую мысль (внимание): динамическую часть рантайма (или любой другой динамической библиотеки) всегда можно поменять сохранив при этом бинарную совместимость.
                                                                                                          Надеюсь, вы согласны с этим простым посылом?

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

                                                                                                          А чем ещё может мотивироваться использование её если это может быть не лучшее решение?

                                                                                                          Необходимостью в каждом конкретном случае, или как вы сами и написали:
                                                                                                          для разных задач разные требования.

                                                                                                          Это не «лучше»-«хуже», это когда вам нужно забить гвоздь вы используете молоток, когда закрутить шуруп отвертку.

                                                                                                          Неужели? А я вот всё время думал что тип линковки зависит не от компилятора а от того каким образом была собрана библиотека. А оно вон как оказывается без специального ключа gcc динамическую библиотеку не сможет подключить.

                                                                                                          Сам призвал не выносить оценок, но… :) ладно будем считать что вы просто забавы ради «включили дурака» :)
                                                                                                          Мы ведь с вами за рантайм терли? Так как вы еще его статически влинкуете? По дефолту в gcc он будет в динамике естественно:
                                                                                                          -static-libstdc++
                                                                                                          gcc.gnu.org/onlinedocs/gcc/Link-Options.html
                                                                                                          When the g++ program is used to link a C++ program, it normally automatically links against libstdc++. If libstdc++ is available as a shared library, and the -static option is not used, then this links against the shared version of libstdc++. That is normally fine. However, it is sometimes useful to freeze the version of libstdc++ used by the program without going all the way to a fully static link. The -static-libstdc++ option directs the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically.

                                                                                                          Ды какие уж субъективные когда вы раз за разом утверждаете про шаблоны в рантайме.

                                                                                                          Вы давайте прекращайте мне всякую отсебятину навешивать :) если вы заблудились в трех соснах не нужно кидаться обвинениями в чужой некомпетентности. Разберитесь сперва о чем вам говорят потом уже судите.
                                                                                                            0
                                                                                                            -static-libstdc++
                                                                                                            А так вы только про рантайм тогда ок, я то думал вы в принципе про любые библиотеки.
                                                                                                            динамическую часть рантайма (или любой другой динамической библиотеки) всегда можно поменять сохранив при этом бинарную совместимость.
                                                                                                            В большинстве случаев да.
                                                                                                            Разберитесь сперва о чем вам говорят потом уже судите.

                                                                                                            Честно говоря я не знаю как иначе можно интерпретировать эти фразы
                                                                                                            Или зачем пользователем приложения на C++ его перекомпилировать (и потом не все же приложения open source), если создатели C++, например, взяли и поменяли имплементацию unordered_map (исправили баги, оптимизировали

                                                                                                            В рантайме есть не только шаблоны

                                                                                                            может вы их прокомментируете? Или всё также упорно продолжите утверждать что это я начал про шаблоны говорить.
                                                                                                              –2
                                                                                                              может вы их прокомментируете? Или всё также упорно продолжите утверждать что это я начал про шаблоны говорить.

                                                                                                              В моем изначальном посте я говорил от том, что динамический рантайм как в Java так и в C++ может быть изменен с сохранением бинарной совместимости, так?
                                                                                                              Это основная мысль.
                                                                                                              И вы с ней в итоге согласились:
                                                                                                              В большинстве случаев да.


                                                                                                              Вы справедливо заметили, что unordered_map это неудачный пример т.к. он построен на шаблонах.
                                                                                                              Я с вами согласился и написал:
                                                                                                              В рантайме есть не только шаблоны

                                                                                                              Т.е. рантайм языка не исчерпывается одними шаблонами, и моя изначальная мысль все равно верна несмотря на неудачный пример.

                                                                                                              Но вас же почему-то начало клинить на шаблонах, и дальше разговор потерял всякий смысл.
                                                                                                                +1
                                                                                                                Я с вами согласился и написал:

                                                                                                                Только это тоже не очень корректное высказывание, потому что в рантайме шаблонов нет. Есть только мономорфизированные представления, а это совсем другая история.
                                                                                                                  0
                                                                                                                  А было бы интересно почитать про применение Котлиновских корутин в внутри Спрингового приклада на джаве?
                                                                                                                    –1
                                                                                                                    Высказывание получилось двусмысленным из-за двух возможных значений «рантайм».
                                                                                                                    1) «Рантайм» как библиотека языка обеспечивающая его работу во время выполнения программы. Именно ее я имел ввиду, т.е. саму библиотеку языка в которой есть не только шаблоны. Наверное чтобы не путаться лучше назвать ее стандартной библиотекой С/C++ или просто библиотекой языка.
                                                                                                                    2) «Рантайм» как скомпилированный код который выполняется. В нем, естественно, шаблонов уже не будет.
                                                                                                      0

                                                                                                      Ну, технически, никто не мешает std::unordered_map'у быть типобезопасной прокси-обёрткой поверх реализации хешмапы, где void* на void* и void* погоняет.


                                                                                                      Увы (на самом деле не увы), такие реализации мне неизвестны, да и они будут заведомо медленнее за счёт меньших возможностей для инлайнинга и меньшей прозрачности для компилятора.

                                                                                                      0
                                                                                                      Динамическая или статическая компоновка это всего лишь инструмент в арсенале разработчика и им нужно уметь пользоваться.
                                                                                                      «dll hell» это следствие неразумного использования динамического связывания и было возможно только в бестолково спроектированных системах. Т.е. это проблема системы, а не самой технологии связывания. Модульность (или пакеты) с зависимостями на определенные версии других модулей/пакетов прекрасно работает.

                                                                                                      И что же это интересно за толково созданные системы, в которых нормально работает модульность? Надеюсь речь не про Линух, который не раз дох у меня полностью от банального обновления…

                                                                                                      Я вижу у вас возникает много вопросов на эту тему… В статье речь идет о сравнении ЯП, а не об тонкостях использования того или иного связывания. Это оффтоп, предлагаю вам все-таки воспользоваться гуглом или почитать специальную литературу.

                                                                                                      В статье на основание не верного представления автора о вопросах компоновки (чего только стоит сравнение размеров исполняемого файла при разных компоновках) делаются вполне однозначные выводы о выборе языков программирования…

                                                                                                      В первую очередь, конечно же, пользователям приложений. Зачем им его перестраивать при выходе новой версии Java? Скомпилированный бинарь будет прекрасно работать на новой версии JVM, а может быть еще и быстрее если разработчики ее оптимизировали. Или вообще на другой JVM и все это без перекомпиляции.

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

                                                                                                      Или зачем пользователем приложения на C++ его перекомпилировать (и потом не все же приложения open source), если создатели C++, например, взяли и поменяли имплементацию unordered_map (исправили баги, оптимизировали).

                                                                                                      Для C++ это вообще не работает, т.к. там большая часть кода (включая unordered_map) является шаблонами.

                                                                                                      Да все те же:
                                                                                                      — жирные бинари (смесь логики и рантайма)
                                                                                                      — кросплатформенность
                                                                                                      — стабильность рантайма

                                                                                                      Хм, что за глупости? Рантайм там даже меньше чем у C++ выходит. И со стабильностью тоже всё хорошо — язык уже устоялся, в отличие от Rust.

                                                                                                      Тем не менее в D меня заинтересовала возможность компиляции в LLVM: github.com/ldc-developers/ldc

                                                                                                      Собственно там и gcc есть gdcproject.org )))

                                                                                                      Но, к сожалению, эта ветка развивается не очень активно, и у меня полезли какие-то странные баги при запуске скомпилированного бинаря, например под Linux на Windows и наоборот. В общем до стабильной работы там похоже должны пройти еще десятилетия.

                                                                                                      Это всё какие-то эксперименты, официальным решением для D является компилятор dmd. И у него со стабильностью всё отлично.
                                                                                                        0
                                                                                                        Infinity hot flow!
                                                                                                        –3
                                                                                                        И что же это интересно за толково созданные системы, в которых нормально работает модульность? Надеюсь речь не про Линух, который не раз дох у меня полностью от банального обновления…

                                                                                                        Ну вы, наверное, каким-то не кошерными дистрибутивами Linux пользуетесь :)
                                                                                                        Попробуйте Debian Stable, там все хорошо.
                                                                                                        Да и последние версии Windows весьма стабильны, несмотря на повсеместное использование динамических библиотек.

                                                                                                        В статье на основание не верного представления автора о вопросах компоновки (чего только стоит сравнение размеров исполняемого файла при разных компоновках) делаются вполне однозначные выводы о выборе языков программирования…

                                                                                                        Начинаем ходит кругами :)
                                                                                                        Мои представления о компоновке правильные, а если они у вас другие или просто не достает знаний в этом вопросе это ваши проблемы.
                                                                                                        Я уже несколько раз описывал вам причины выбывании части языков из обзора. Вы же все с типом компоновки никак не разберетесь. Давайте может вы уже закончите свои увлекательные эксперименты, а пока оставим эту тему в покое? :)

                                                                                                        Для C++ это вообще не работает, т.к. там большая часть кода (включая unordered_map) является шаблонами.

                                                                                                        Верно, но в рантайме очень много и другого кода, который не построен на шаблонах.

                                                                                                        Хм, что за глупости? Рантайм там даже меньше чем у C++ выходит. И со стабильностью тоже всё хорошо — язык уже устоялся, в отличие от Rust.

                                                                                                        Слушайте, ну уже не в первый раз призываю вас воздерживаться от личных выпадов. Для меня тоже 90% из того что вы пишите сплошная глупость, но я ведь об этом не говорю вслух? :)
                                                                                                        Иначе наша беседа, у которой и так технический уровень крайне низкий (обсуждаем совершенно базовые вещи — на уровне собеседования со студентом), рискует скатиться в банальную никому не нужную ругань :)

                                                                                                        А как вы проверяли стабильность рантайма в D?
                                                                                                        Проводилось ли стресс тестирование?
                                                                                                        Какие подсистемы языка проверялись?
                                                                                                        Или так же умозрительно, руководствуясь, «своими знаниями о работе компилятора»? :)

                                                                                                        Может быть рантайм у D и меньше чем у C++, но опять же львиная его часть пихается в бинарь, и динамическая линковка (в отличии от C++) не помогает. Бинари «жирные» — т.е. та же смесь логики программы и рантайма.

                                                                                                        Это всё какие-то эксперименты

                                                                                                        Эксперименты обязательно нужны даже если вы проводите небольшую исследовательскую работу.

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

                                                                                                        Для начала разгребите «завалы» в своей голове, а потом уже выносите суждения о чужой :)
                                                                                                        Но если серьезно, обычные пользователи даже не узнают об этом, просто нажмут кнопочку «Обновить Java» и будут продолжать радоваться работе приложения. И это правильно. Но вот разработчик должен четко представлять себе как это все устроено и работает.
                                                                                                          +2
                                                                                                          Ну вы, наверное, каким-то не кошерными дистрибутивами Linux пользуетесь :) Попробуйте Debian Stable, там все хорошо.

                                                                                                          Вот как раз с такими и игрался. Советую попробовать не обновлять подобный дистрибутив 1-2 года и потом запустить обновление…

                                                                                                          Да и последние версии Windows весьма стабильны, несмотря на повсеместное использование динамических библиотек.

                                                                                                          В Windows как раз не особо употребляется совместное использование динамических библиотек. В системый каталог кладётся только их малое число, а большинство устанавливается в каталог приложения. Так что под Windows у каждого приложения используется своя версия (и на одном компьютере их может быть множество). Хотя и там изредка бывают проблемы из этой области (обычно когда сомнительное ПО прописывает себя в path), но гораздо реже… Только вот это следствие не умной системы зависимостей, а наоборот уход от неё. Точно так же как и на OSX.

                                                                                                          Начинаем ходит кругами :)
                                                                                                          Мои представления о компоновке правильные, а если они у вас другие или просто не достает знаний в этом вопросе это ваши проблемы.
                                                                                                          Я уже несколько раз описывал вам причины выбывании части языков из обзора. Вы же все с типом компоновки никак не разберетесь. Давайте может вы уже закончите свои увлекательные эксперименты, а пока оставим эту тему в покое? :)

                                                                                                          Вот что меня действительно поражает, так это ваше полное игнорирование оценок статьи, а так же этой беседы в комментариях — у вменяемого человека хотя бы из-за них возможно закрались бы какие-то сомнения в собственно правоте. Но у вас ни малейших не появилось. Но вы правы в одном: действительно пора заканчивать — мне уже наскучило стучаться в эту стену…
                                                                                                            –1
                                                                                                            Вот как раз с такими и игрался. Советую попробовать не обновлять подобный дистрибутив 1-2 года и потом запустить обновление…

                                                                                                            Ну раз с «такими» значит много каких-то вариантов пробовали и видимо непродолжительное время.
                                                                                                            Например, в Ubuntu такое действительно возможно, особенно при переходе на новый релиз каждые пол года, относительно спокойно можно сидеть только на LTS. Ведь Ubuntu основан на ветке Testing репозитория Debian.
                                                                                                            Если же вы выбрали в Debian ветку Stable, то уверяю вас, можете совершенно спокойно обновляться хоть через 2 года, хоть через 10.

                                                                                                            Просто в Linux софт развивается очень активно, а квалификация авторов различна, и нужны серьезные административные меры чтобы сохранять систему стабильной. Хороший дистрибутив — хорошая стабильность, плохой — такая и стабильность.
                                                                                                            А сама по себе система модульности здесь не причем.

                                                                                                            В Windows как раз не особо употребляется совместное использование динамических библиотек. В системый каталог кладётся только их малое число,

                                                                                                            Ну это как сказать :) загляните в Windows/System32 и в SysWOW64 на 64-х битной системе, думаю несколько тысяч наберется :)

                                                                                                            Кстати, забавно, что в 64-х битной версии Windows 64-х битные dll-шки лежат в System32, а 32-х битные в SysWOW64 :)

                                                                                                            а большинство устанавливается в каталог приложения. Так что под Windows у каждого приложения используется своя версия (и на одном компьютере их может быть множество).

                                                                                                            Я не думаю, что это проявление какой-то сверхмудрости Windows систем, это скорее рудимент, который тянется из древних времен.

                                                                                                            Вот что меня действительно поражает, так это ваше полное игнорирование оценок статьи

                                                                                                            Так и пробивает вас на психиатрические термины, про вменяемость вон ввинтили теперь :) вы, наверное, все-таки психиатр… лечащий по фотографии :)

                                                                                                            Если бы я преследовал цель набрать «плюсики» и пропиариться, я бы, наверное, написал что-нибудь другое, так чтобы наверняка всем понравилось :)
                                                                                                            Но я проводил это небольшое исследование для себя, получил ответы на свои вопросы, сделал выводы и просто решил любезно поделиться результатом. Возможно кому-то это будет полезно, возможно нет, для меня это не существенно.
                                                                                                            В статье действительно много субъективных оценок, которые можно принимать или нет, но они основаны на моем личном опыте, а не взяты с потолка.
                                                                                                            У всех ораторов разный опыт, свое мнение, свое видение, да и голова у всех работает немного по разному, сердиться на это глупо.
                                                                                                            В обсуждении я честно пытался разъяснить мотивы тех или иных выводов в статье, если видел что спор затеян не ради спора, а действительно присутствует некоторое недопонимание.
                                                                                                            Однако результаты тестов вполне проверяемые цифры и исходники доступны, поэтому дискуссии на эту тему лишены смысла.
                                                                                                            Что касается оценок, то если мы говорим о рейтинге сообщений в обсуждении, то тут я с интересом наблюдал «стадный эффект» в полный рост :) Если бы я даже просто написал, что дескать земля вращается вокруг солнца все равно стали бы яростно минусовать :)
                                                                                                            Если мы говорим об оценках статьи, то на момент написание этого поста мы имеем 17 положительных оценок и 41 отрицательную, итог -24. Общее число просмотров статьи 6,3k (конечно нельзя утверждать, что ее просмотрело именно такое количество людей и тем не менее), получается процент серьезно недовольных около 0.38%, меньше процента :)))
                                                                                                          0
                                                                                                          И что же это интересно за толково созданные системы, в которых нормально работает модульность? Надеюсь речь не про Линух, который не раз дох у меня полностью от банального обновления…

                                                                                                          Таки проблема скорее в дистрибутиве, чем в модульности самой по себе. Gentoo Linux, УМВР на протяжении лет уже так 15.
                                                                                                    0
                                                                                                    Оно неверно потому, что даже если уж и принимать в расчёт занимаемое на диске место (хотя в наше время больших дисков и быстрого интернета это всё давно стало неактуальным), то это должен быть размер дистрибутива приложения, а не размер исполняемого файла.

                                                                                                    Интересно, как размер дистрибутива считать в случае линуксов с репозиториями, когда всякие кути или openjdk подтягиваются по зависимостям, но один раз.

                                                                                                    Но это так, мысли вслух, так-то я с вами согласен.
                                                                                                      –4
                                                                                                      В Qt можно посмотреть список загруженных библиотек и сложить их размер.
                                                                                                      А в Java смотреть какие jar-ы подгрузились.
                                                                                                      Только зачем? :)
                                                                                                        +2
                                                                                                        Размеры бинарников вы же зачем-то сравниваете.
                                                                                                          –3
                                                                                                          Да вроде не сравнивал нигде, а размеры получившихся бинарников действительно привел в статье.

                                                                                                          Это дальше уже некоторые энтузиасты увлеклись бессмысленными сравнениями каких-то дистрибутивов.
                                                                                                          Потом вдруг сделали из своих же сравнений странный вывод «о преимуществе статической линковки на динамической» :)
                                                                                                          Еще один товарищ уже шаблоны к этой теме примеряет, градус абсурда все крепчает :)
                                                                                                          Каких еще откровений ждать? :)
                                                                                                          Мне уж самому стало интересно до чего еще додумаются? :)
                                                                                                            +1
                                                                                                            Мда уж, вы мастер переводить стрелки. Сморозили глупость а потом оп и вроде бы и не вы.
                                                                                                              –3
                                                                                                              Ну все сообщения на виду, предоставьте делать выводы тем кто захочет всю эту лабуду читать :) кто тут и что «сморозил».
                                                                                                              Могу только сказать, что вы «мастер» прицепляться к каким-то несущественным мелочам и в упор не замечать сути обсуждения.
                                                                                                    +2
                                                                                                    Верите в добрый и могущественный Компилятор? Который вас всегда поймет, исправит все ошибки и сгенерирует самый современный и самый быстрый код на свете? :)

                                                                                                    По части производительности верю. На мой взгляд то, что компилятор способен продраться через все эти шаблоны и сгенерировать такой же по эффективности код, как если бы я всё это ручками делал — лучшая иллюстрация.
                                                                                                      –3
                                                                                                      Ну для оптимизации шаблонов у компилятора как раз очень много возможностей — тут все будет происходить на этапе компиляции.
                                                                                                      В нашем случае шаблонов не было и речь шла о разных единицах компиляции.
                                                                                        0
                                                                                        Я как то в качестве эксперимента ужал jre (на Windows) до примерно 13 мегабайт, удалив все неиспользуемые классы и dll. Но понятное дело что на таком урезаном jre кроме этой программы едва ли бы что запустилось. Собственно делал для того что бы можно было запустить мою игру на компе без Java и размер дистрибутива не растаращивался в 10 раз.
                                                                                        0
                                                                                        Внимательно прочел статью и все комментарии. ИМХО одна из основных ошибок автора, что он в одной статье соединил оценку дизайна ЯП и оценку эффективности реализаций ЯП. Из того, что return@forEach выглядит непривычно, не следует, что это будет медленно работать. ИМХО стоило разбить статью на две части. (Первую сделать больше, чем сейчас). Тогда бы и ответы были бы конкретнее по каждой из частей. А так критика сосредоточилась в основном на эффективности. Тут ИМХО критикам возразить сложно: хорошо известно много методик оценок эффективности. Все они включают разнообразные тесты, а тут возникает впечатление, что получены результаты только по I/O разных реализаций разных языков. Думаю, что если автор возьмет задачу с полным перебором без I/O, то лидеры ЯП могут оказаться другими. Думаю, что и критики, если решат задачу автора и получат принципиально другие результаты по лидерам, окажутся гораздо убедительнее. Еще думаю, что минусы за статью и комментарии никого ни в чем убедить не могут.
                                                                                          +1

                                                                                          Подскажите, а как Вы запускали приложения? Я тут ради интереса произвел запуск приложения на Scala тремя способами:


                                                                                          • из консоли sbt командой run
                                                                                          • scala — jar файл для scala (scala test.jar)
                                                                                          • Java — jar файл включающий библиотеки скалы, который может выполнятся только с java (java -jar test.jar)

                                                                                          И получил три разных варианта. Самый быстрый — из консоли sbt. Первый примерно тоже самое, что и Qt, а со второго запуска, отработал почти вдовое быстрее. Два других работали в двое медленнее, чем на Qt. Причем это только показатель замеров программы, реально было еще дольше.

                                                                                            0
                                                                                            Запускал из консоли: java…
                                                                                            Если sbt консоль работает под java и грузит классы в эту же JVM, возможно, и будет некоторый прирост производительности.

                                                                                          Only users with full accounts can post comments. Log in, please.