В преддверии Joker 2016 мы накатали пост про Java Performance, который вызвал бурю эмоций у читателей. Дабы вбросить топлива в вентилятор и попытаться все-таки прийти к какому-то единому решению, мы решили привлечь экспертов из разных «лагерей»:
- Дмитрий Нестерук. Эксперт по .NET, С++ и инструментам разработки, автор курсов по технологиям и математике, квант.
- Андрей Паньгин. Ведущий программист компании Одноклассники, специализирующийся на высоконагруженных бэкендах. Знает JVM как свои пять пальцев, поскольку ранее на протяжении нескольких лет разрабатывал виртуальную машину HotSpot в Sun Microsystems и Oracle. Любит ассемблер и низкоуровневое системное программирование.
- Владимир Ситников. Десять лет работает над производительностью и масштабируемостью NetCracker OSS — ПО, используемого операторами связи для автоматизации процессов управления сетью и сетевым оборудованием. Увлекается вопросами производительности Java и Oracle Database.
- Олег Краснов. CTO компании SEMrush и адепт ANSI C.
Андрей Паньгин
— Java и С++, какой сейчас, по-вашему, язык наиболее востребованный? Оба из них уже совершеннолетние, однако кто более зрелый и отточенный?
— Прежде всего, я не считаю, что между этими языками существует какая-либо конкуренция. У каждого из них есть своя ниша, и они прекрасно сосуществуют вместе. Традиционно популярность Java несколько выше. Java платформа привлекает своим мощным инструментарием для отладки и сопровождения приложений. Однако и значимость С++ сложно переоценить. Несмотря на то, что это язык с большущей историей, он и сейчас продолжает активно развиваться: только разработчики успели привыкнуть к C++11, как вышел стандарт С++14 с множеством новых интересных фич.
— Что языки могут дать в мире высоконагруженных серверов? Имеет ли смысл разрабатывать отдельные модули системы на разных языках, затачивая их под конкретные задачи? Если бы могли (захотели или просто была бы возможность), стали бы использовать С++ для решения задач или же делали все только на одном языке?
— Под высоконагруженными серверами каждый понимает что-то своё. Для одних это тысячи сетевых запросов в секунду, для других — параллельные вычисления над большими объёмами данных. Для разных задач лучше подходят разные инструменты. У нас (в Одноклассниках) есть модули, написанные на С++, в частности, связанные с обработкой изображений и видео — там нужны SIMD вычисления и максимально эффективное использование процессора. Впрочем, для большинства наших систем производительности Java хватает. Более того, фрагменты кода, ранее разработанные на C и вызываемые через JNI, мы постепенно переписали на Java, в результате чего даже выиграли в производительности, поскольку избавились от лишних копирований и накладных расходов JNI.
— Использование Unsafe в Java, оправдано или нет? Почему бы тогда не использовать С++?
— У меня есть целый доклад на тему того, почему мы используем Unsafe. Существует ряд сценариев, где без Unsafe пока не обойтись, в частности, для работы с off-heap и взаимодействия с нативным кодом.
Если бы мы захотели написать приложение целиком на C++, нам бы пришлось реализовывать заново все наши общие фреймворки и протоколы: для сбора статистики, для мониторинга, для коммуникации между серверами и т. д. А так — у нас есть лишь маленькая часть кода с Unsafe, отвечающая за низкоуровневые операции, зато всю остальную разработку мы ведём на привычной Java, придерживаясь лучших паттернов написания простого и понятного кода. Гораздо удобнее, когда вся экосистема разрабатывается на единой платформе.
— Какие наиболее частые проблемы производительности бывают при разработке Enterprise-систем и возможные способы решения?
— Редко, когда мы упираемся в производительность самой Java платформы. Обычно проблемы можно решить либо заменой алгоритма, либо масштабированием, то есть наращиванием железа. Чаще всего узким местом оказывается пропускная способность сети или дисковый ввод-вывод. Но если говорить о JVM, то главную или даже единственную проблему производительности нам иногда доставляет сборщик мусора, потому как паузы дольше 500мс в наших случаях зачастую критичны. Поэтому мы стараемся не делать Heap чрезмерно большим: максимум 50 гигабайт, но чаще и того меньше: от 4 до 8 гигабайт на приложение. Большие объёмы стараемся выносить за пределы хипа: сделали даже фреймворк для создания больших высоконагруженных кешей. Дополнительное преимущество такого кеша по сравнению с хиповым — персистентность, то есть возможность перезапуска приложения без потери данных. Это достигается за счёт использования разделяемой памяти: сразу после запуска приложение отображает объект разделяемой памяти в адресное пространство процесса, и кеш со всеми данными становится моментально доступен.
— Что вы можете сказать по поводу скорого выхода JDK 9 и его главной фичи — модульности?
— Про модульность было много разговоров, дата релиза даже несколько раз переносилась, чтобы эту модульность наконец доделать. Но при этом среди моих знакомых я не знаю ни одного Java разработчика, кому эта фича была бы действительно нужна. Я считаю, лучше бы пораньше выпустили JDK 9 — разработчики были бы только благодарны. Нам, например, модульность скорее навредит, чем поможет: ведь один из побочных эффектов — то, что Unsafe теперь будет спрятан глубоко внутри, и без специальных ключиков недоступен. Зато в JDK 9 ожидаются куда более приятные нововведения, ради которых новую версию стоит хотя бы попробовать: улучшения в G1, Compact Strings, VarHandles и др.
— Если очень грубо посмотреть, то разница между C++ и Java — в прослойке runtime, которая, помимо прочего, выполняет всевозможные оптимизации. Что предпочтительнее: использование архитектурных особенностей машины вручную (С++), либо лучше положиться на динамические оптимизации JVM? Если говорить совсем про конкретные вещи, то лучше автоматическая сборка мусора или ручное управление?
— Адаптивная компиляция и автоматическое управление памятью — как раз сильные стороны Java. В этом виртуальная машина преуспела и превзошла статические компиляторы. Но главное даже не это. Мы выбираем JVM за те гарантии безопасности, что она нам даёт. В первую очередь — защиту от фатальных ошибок из-за неправильной работы с памятью. Искать проблемы, связанные с указателями или выходом за границы массива, в неуправляемом коде на порядок сложнее. И стоимость исправления таких ошибок с лихвой перекрывает выгоду от того небольшого преимущества в скорости, что даёт прямой доступ к памяти. Как говорилось выше, мы порой используем Unsafe, и в этих случаях мы автоматически подвергаем себя тем же рискам, что и в C++. Да, нам иногда приходится разбираться в крашдампах JVM, и это занятие не из приятных. Именно поэтому мы всё же предпочитаем чистую Java, а неуправляемый код используем лишь в случаях крайней необходимости.
Также у меня будет доклад на Joker как раз на тему: «Мифы и факты о производительности Java».
Дмитрий Нестерук
— Java и С++, по вашему мнению, какой сейчас язык наиболее востребованный? Оба из них уже совершеннолетние, однако кто более зрелый и отточенный?
— Если говорить о востребованности, то тут все очевидно: Java, конечно, более востребована, чем другие языки. C++ занимает свою нишу в трех основных дисциплинах (game dev, финансы и embedded), ну и плюс является основным языком для HPC и scientific computing. Поэтому если придерживаться шкурных интересов, то Java конечно безопаснее как навык, если только вы не идете целенаправленно в одну из этих областей.
Что касается зрелости, то тут все сложно и нужно сначала разбивать на фичи языка, способности компилятора и особенности стандартных библиотек.
Начнем с первого — с языков. И там и там есть проблемы. С Java проблема в том, что язык не развивается так стремительно, как его ближайший конкурент, в результате чего фичи приходят очень медленно и не так, как хочется. Тут примечательно, что C# моложе, но в нем первом появились лямбды, также технология LINQ (Language Integrated Query — это такие удобные механизмы обхода и выборки наборов данных), да и изначальные решения в основе C# (то есть поддержка свойств и делегатов) тоже были выполнены грамотно и удачно.
Что касается C++, то тут основная проблема — это 100% совместимость С++ с языком С, что автоматически означает огромный багаж никому не нужных языковых фич. С другой стороны, стагнация С++ в 2000-е годы тоже популярности языку не прибавила, т.к. разработчиков нужно постоянно подкармливать новыми фичами. Сейчас ситуация лучше — в С++ есть и лямбды (кстати, более экспрессивны, чем в C#/Java), вывод типов для переменных и даже возвращаемых из функции значений, в общем язык как-то эволюционирует.
Это что касается языков. Теперь насчет компиляторов. Тут, во-первых, сравнение не совсем корректно, т.к. JVM — это JIT, то есть идея о том, что можно взять байт-код и превратить его в идеальное такое представление для текущего процессора, со всеми оптимизациями, которые применимы. Это звучит хорошо в теории — я не знаю как это на Java, но в .NET мире такой подход, по сравнению с оптимизациями С++ компилятора, конечно, он не делает практически ничего. Если вы делаете математику или, я так скажу: если вы, допустим, покупаете математическую .NET библиотеку в сети, то это будет всего лишь обертка вокруг С++.
Да, и касательно С++ компилятора: я для вычислительных задач использую Intel C++, то есть компилятор, который поставляет собственно производитель процессоров. В этом есть огромное количество минусов: языковых фич меньше, чем в MSVC, куча несуразных ошибок по которым приходится обращаться в саппорт, но едим мы этот кактус по одной простой причине: оптимизации. Intel'овский компилятор генерит самый эффективный код. Конечно, не кодом единым: тут у нас вся мощь Intel Parallel Studio идет в ход, это и Threading Building Blocks для паралеллизации (кстати, аналог Microsoft Parallel Patterns Library), и Intel Math Kernel Library, которую даже, если ты не используешь напрямую, ты используешь ее косвенно через MATLAB и прочие. Тут нужно пояснить, что библиотека вроде MKL уже оптимизирована ребятами из Intel: тут и векторизация, и параллелизация, и даже кластерная параллелизация через MPI (например для FFT) сделана «из коробки» — то есть, бери и пользуйся. Ну и конечно стоит упомянуть про средства профиляции, которые тоже часть IPS. Это очень мощный инструментарий, он, по сути, ставит себе цель помочь разработчику оптимизировать код в плане производительности, ну и корректности тоже — там профиляция памяти тоже есть, так что утечки и все подобное легко найти.
Ну и наконец про «либы» — тут все просто, Java выигрывает, в С++ все плохо. Я не буду даже говорить про то что сам интерфейс C++ Standard Library немножко безумен, но проблема мне видится не только в том, что все «легаси», а в том, что просто очень мало фич! У нас вот только-только появились такие вещи как поддержка файловой системы и худо-бедно поддержка потоков какая-то. И то, вот есть у меня строка, хочу ее побить на подстроки по пробелу — этого в стандартной библиотеке нет, то есть я должен брать стороннюю библиотеку (ну благо есть такая штука как Boost, там много полезного). Но развитие действительно тормозит. Многие компании, например Electronic Arts, они пишут свои реализации STL потому что их не устраивает стандартная. Ну и, в кулуарах, многие признаются что нам по сути нужна новая, с нуля, библиотека, некий STL2, хотя корректнее, конечно, было бы назвать ее Standard Library 2 или как-то так.
Есть еще масса проблем, например, отсутствие основного пакетного менеджера, а также, даже если бы он был, как библиотеки-то шарить? В Java или .NET можно просто бинарники раздавать, а в С++ по сути нужно шарить сорцы. Вот эту проблему пока никто толком не решил, и это тоже тормозит развитие т.к. иногда берешь чужую либу, а потом тратишь полчаса просто, чтобы она у тебя заработала.
— Как в целом чувствуют себя языки в Enterprise, например, в банковской сфере? Например, в HFT (High-Frequency-Trading) мире большие нагрузки и высокие требования к надежности. Также финансовая индустрия достаточно консервативна. Как это сказывается на выборе той или иной технологии?
— Enterprise — это одна такая гребенка большая, под которую сейчас идет любая корпоративная разработка. Глобально — это, конечно, C# и Java, и остальные языки где-то на периферии. Вот касательно банковской сферы — тут все несколько более интересно, и особенно интересно, что местами появляется С++, ну и есть некоторые конторы вроде Bloomberg'а, которые вообще на С++ полностью, но это мне кажется аномалия. Вообще, если сейчас получать MFE, то есть магистра по финансовой инженерии, то там в основном С++ и используется, хотя сейчас популярные такие языки как Python и R, ну и MATLAB тоже остается актуален.
Что касается HFT, это тоже такая спорная тема, но да, она в основном тяготеет к С++, а даже к C, использованию всяких FPGA, где и системный С присутствует, или люди на всяких HDL языках пишут. Когда важна скорость, производительность, то тут native code как-то ближе, хотя аргумент, что де «Java тормозит», мне кажется уже неактуален. Тут просто еще ручное управление памятью иногда людям нужно, все боятся большого злостного GC, который придет и остановит все потоки именно в тот момент, когда вам нужно будет совершить какую-то сделку.
В quant finance «плюсы» остались скорее из каких-то консервативных соображений, потому что финмат, в отличие от обычной разработки софта, он рассматривает программирование как навык сродни знанию английского языка, а не как нечто системообразующее. Соответственно, люди просто учат С++ и не мучаются, хотя сейчас для анализа Python и R как-то более популярны даже. Но «плюсов» в инвестбанках вагон.
— Для разработки ПО для встроенных устройств, какой язык лучше подходит, на ваш взгляд? Насколько эти языки позволяют писать портативный код?
— Вообще, тема embedded слишком широка. Для многих embedded — это всякие Rasperry Pi или Arduino, для меня — это FPGA, для кого-то еще что-то. Но если обобщать, то embedded это конечно в основном С или С++, если говорить о прикладном уровне. Конечно, для FPGA разработки я использую или VHDL напрямую или пишу MATLAB, который после конверсии VHDL выбрасывает — суть остается та же.
Конкретно про FPGA, поскольку это единственная тема, в которой я хоть что-то понимаю, могу сказать что языки, да и сам подход разработки — это хорошая иллюстрация того, как вообще вся технология может застрять намного хуже, чем С++ где-то в старых моделях, языках и вообще. С этой технологией очень сложно работать и ты начинаешь по сути или использовать всякие генераторы вроде MATLAB или писать что-то свое. То есть, для людей, которые работают чисто на системном уровне, перекладывание битов в ручную — это нормальное явление, но мне как человеку, который хочет, например, моделировать набор бизнес-правил в «железе», совсем не нравится такой подход, и языка не хватает, чтобы на высоком уровне объяснить, что же мне надо.
А говорить про Java и embedded я просто не квалифицирован.
— Если очень грубо посмотреть, то разница между C++ и Java — в прослойке runtime, которая, помимо прочего, выполняет всевозможные оптимизации. Что предпочтительнее: использование архитектурных особенностей машины вручную (С++), либо лучше положиться на динамические оптимизации JVM?
— Ну я, кажется, уже этот вопрос затронул, но тут все на любителя. Вот взять меня, я на практике использую все уровни параллелизации, то бишь SIMD, OpenMP, MPI и это не говоря про всякую специфику вроде аппаратных ускорителей. SIMD оптимизации есть какие-то в Java, сейчас вон и .NET медленно подтягивается, но по сути С++ все еще рулит в плане автоматических оптимизаций, и не будем забывать что в С++ можно вручную забивать ассемблерные блоки. Я понимаю, что сейчас ассемблер никто не знает и многие-то и С++ в глаза не видели, но суть в том, что когда дело касается чисто вычислений, то есть математики, и хочется побыстрее, то почему бы и нет?
Я не особо верю в динамические оптимизации вот почему: если у вас простой цикл, в нем допустим массив суммируется — это да, это можно распознать, распараллелить там. Проблема в том, если вы, например, втащили в цикл какую-то зависимость извне, что тогда делать? В OpenMP у нас разметка соответствующая, а динамический оптимизатор такие задачи не сможет решать, никогда. Поэтому кто-то, например, посмотрит на CUDA и скажет, что это модель абсолютно нереальная, зачем мне все алгоритмы переписывать, да еще учиться чему-то? А как по мне, то это неизбежно, т.к. оптимизаторы работают очень хорошо на понятных, простых вещах, делают всякие инлайнинги, но все что performance-critical можно написать и руками, написать в native code и не мучаться.
— Насколько динамична экосистема Java и C++? Насколько часто выходят обновления, релизы, стандарты? Насколько живы языки (насколько много языковых фич появляется)?
— Ну, я думаю можно сказать, что «плюсы» бессмертны, в отличии от Java как языка, где появились многие новые языки с интересными фичами — это и Scala и Kotlin и другие. Другое дело, что язык и платформа это разные вещи. Java как язык многих не устраивает, собственно поэтому и новые языки. Но как платформа — там все прекрасно, судя по всему, опять же, есть преимущества даже по сравнению с ближайшим конкурентом (например в плане GC). Но как язык — предостаточно оснований для претензий.
Про С++ я тут должен высказаться, наверное. Конечно, после того, как комьюнити лет этак 13 в свое время вообще ничего не делало, новые стандарты и новые фичи библиотеки — это, конечно, хорошо, прекрасно, я бы даже сказал, по сравнению с полной апатией. В С++11 произошло многое, очень много реально полезных подвижек, я теперь пишу совсем другой С++ нежели ранее. В С++14 все еще немного доулучшали, но вот в С++17 снова разочаровали весь мир — то есть, те фичи которые всех ждали, их не будет. Основная фича, которую все хотели, и хотят в общем-то, это модули. Просто сейчас С++ компилируется очень медленно, точнее первичная компиляция, т.к. инкрементальность-то у него, если судить по MSVC, просто супер, но сборка например либы «с нуля» — это удовольствие ниже среднего. Ну и вот модули должны решить эту проблему, но никто не знает когда.
Опять же, в С++ такая проблема, что самых базовых вещей нет в стандартной библиотеке. И это новичка, которому нужно перевести строку, допустим, в нижний регистр или побить по токенам, просто приведет в ступор. Сторонних библиотек, конечно, много, но сама юзабельность библиотек это тоже вопрос. Языки у которых есть метаданные — ты видишь там функцию и знаешь как ее использовать, даже документация появится в комплишне. А в С++ у тебя может быть шаблонный аргумент типа Func, то бишь функция, а сигнатуру функции ты можешь не понять, даже если залезешь в сорцы. И непонятно что с этим, собственно, делать.
В общем, если резюмировать, я бы сказал, что оба языка как бы живы, и все зависит от того, что вам собственно надо. В целом, можно продуктивно писать и на том и на том. Касательно либ, тут плюсы проигрывают, это всем ясно, причем удивительно, т.к. язык вроде старее, намного, а библиотеки ну, они даже если есть, то из мира С и не особо юзабельны, или их просто нет и нужно искать где-то извне, скачивать, компилировать, и только потом использовать.
Олег Краснов
— Почему С?
— Когда я пришёл в компанию SEMrush, значительных наработок серверной логики на других языках не было. На тот момент я преимущественно программировал на С и решил разрабатывать продукт именно на этом языке. Я верил в свои силы. =)
Для меня С — это простой и удобный язык. При достаточном умении и знании библиотек, он прекрасно подходит для прототипирования разработок на уровне скриптового языка.
У нас, в компании SEMrush, среди языков программирования серверной части распределение примерно следующее: 1/3 — это С и С++, 1/3 — скриптовые, 1/3 — Java.
— Java и С, какой сейчас по-вашему язык наиболее востребованный? Оба из них уже совершеннолетние, однако кто более зрелый и отточенный?
— Мой опыт говорит о том, что на языке С стоит разрабатывать вещи, которые относятся к производительным задачам. Например, это работа с сокетами, мультиплексирование данных, высоконагруженные многопоточные приложения, где можно и нужно максимально полно управлять ресурсами компьютера.
В компании SEMrush нет явного разделения языков программирования по зонам их применения. Если нужно начать новый продукт, то выбор того или иного языка зависит от профессионализма человека, который начинает разработку архитектуры и программирование. А также от того, насколько он коммуникабелен и способен донести до коллег идеи, которые хочет воплотить.
Довольно частые задачи для нас — это сбор и обработка данных. Среди причин, почему, например, мы не используем Java во всех продуктах, то, что у нас в плане сущностей нет дикого наследования. Глубина его, в силу специфики нашей работы, в вертикальной плоскости меньше, чем в горизонтальной. То есть большое количество данных скорее будет передаваться между независимыми сущностями, чем между родителями и потомками.
— Имеет ли смысл разрабатывать отдельные модули системы на разных языках, затачивая их под конкретные задачи?
— Я считаю, что имеет. В этом плане у нас очень хорошо всё устроено. Разработку ведут небольшие группы по 5-6 человек, каждая из которых работает над своим продуктом, а взаимодействие между ними осуществляется через API. И пользовательский интерфейс, и сервисы между собой должны «хорошо» взаимодействовать. Это осуществляется, например, при помощи таких форматов данных, как JSON и Binary-JSON. Поэтому да, можно использовать разные языки для написания целой системы.
У нас есть наша собственная БД, написанная на С, и крупных проблем с ее работой не наблюдалось. Когда я занимался разработкой архитектуры этой базы, не было готовых адекватных средств, которые бы подошли. Данная БД работает на обыкновенных файлах и, с учетом этого, достаточно надежна. Если исключить из рассмотрения все меры по обеспечению её бесперебойной работы (резервирование, кластеризация), то даже «отвалившийся» диск (неполадки в оборудовании или непредвиденные технические причины) не нанесёт большого вреда, будет потеряно не более 8.5% данных. То есть вероятность того, что пользователи пострадают, дополнительно снижена на уровне бизнес-логики. Но в целом система построена таким образом, что данные не теряются. Все очень надежно.
Мы как-то проводили тесты по максимальной утилизации производительности «железа» с 12 дисками. Если использовался RAID5, то скорость чтения/записи была примерно 2.5х скорости одного винчестера. Но наша система использует 12 дисков раздельно на уровне бизнес-логики, это позволяет нам добиться 11-кратного роста скорости за счёт того, что каждый поток работает со своим диском.
— Как в целом чувствуют себя языки в Enterprise?
— У нас есть крупные продукты. Например, один из них обходит сеть Интернет и создает базу ссылающихся друг на друга страниц сайтов. Ядро написано на С, что позволяет утилизировать «железо», практически на все 100%. В этом продукте задействовано более 150 серверов, но такой подход позволяет быть уверенным в том, что мы не переплачиваем за серверный парк, а нас, как вы понимаете, заботит финансовая эффективность. Отдельно отмечу, что благодаря agile процессам разработки, у нас есть время как на доставку новых возможностей пользователю, так и на оттачивание производительности каждого продукта.
— Какие наиболее частые проблемы производительности бывают при разработке Enterprise-систем и возможные способы решения?
— Если честно, особых проблем не могу даже припомнить. Если вдруг не хватает мощности, то использование ассемблера, специальных библиотек и усилий высококлассных программистов позволяет очень быстро решить проблему. Но в 99% случаев у нас с производительными решениями проблем нет.
У меня нет предубеждений по поводу Java, но она более требовательна к ресурсам. Да, с её помощью очень удобно решать задачи со сложной многоуровневой бизнес-логикой, строить взаимосвязанные системы. Однако такого рода задачи, как сетевые взаимодействия, многопоточное программирование или большие бинарные данные, на мой взгляд, больше подходят для С. На Java это тоже можно сделать, однако я бы выбрал С.
— Какая по-вашему должна быть «идеальная» БД? Стоит ли заморачиваться с производительностью приложений, если вся мощь системы нивелируется транзакциями к БД и как это можно исправить?
— Идеальная БД не универсальна. Она делается для определённого приложения и должна хорошо соответствовать его бизнес-логике. Да, ее сложнее спроектировать и проще воспользоваться готовыми решениями, но такой подход позволяет «драматически» увеличить производительность.
— Сейчас очень модно работать с большими данными, для задач обработки больших массивов, что лучше подходит — Java или С++?
— Большие данные — это Святой Грааль для программистов, и для каждого они выглядят по-разному. Для кого-то это петабайты, а для кого-то — экзабайты. На начальном этапе обработки таких данных существуют большие требования к уровню железа. Поэтому наиболее эффективно для их первичной обработки использовать язык С.
— Насколько динамична экосистема Java и C++? Насколько часто выходят обновления, релизы, стандарты? Насколько живы языки (насколько много языковых фич появляется)?
— У нас используется стандарт С99, и с тех пор ничего нового, скорее улучшения компилятора более важны. Усложнение языка не всегда хорошо, на мой взгляд. У последних стандартов С++ — С++14 и С++17 (draft) наблюдается такое количество новых фич, что не ясно, имеет ли смысл использовать большинство из них. Я понимаю, что программистам нравится развитие языка. Однако особенности и удобства нужно правильно использовать. Гонка за фичами как самоцель неэффективна и часто вредит основной идее продукта.
Периодически я наблюдаю использование С++ как С с классами или даже как С без классов с некоторыми контейнерами С++. Это нерационально. Получается каша. Если планируется использование С++, следует внимательно изучить его особенности и использовать их наиболее полноценно.
Владимир Ситников
— Что языки могут дать в мире высоконагруженных серверов? Имеет ли смысл разрабатывать отдельные модули системы на разных языках, затачивая их под конкретные задачи? Если бы могли (захотели или просто была бы возможность), стали бы использовать С++ для решения задач или же делали все только на одном языке?
— В мире энтерпрайз приложений подобное разделение встретишь не часто. Интересный фактор — это поддержка приложения. Если в приложении используются 10 разных языков и, по сути, 10 разных экосистем, то поддерживать такое очень сложно. В итоге, если программу пишет одна компания, а разворачивает, использует и поддерживает другая, то крайне важно сохранять универсальность и простоту сопровождения. Здесь даже использование двух разных языков уже может сильно повышать порог вхождения для поддержки. Второй немаловажный фактор — удобство анализа проблем. Например, если java программа решила прочитать и сохранить многогигабайтный файл в памяти, то без проблем можно узнать какой файл, почему и т.п. В случае C++ подобный анализ сделать гораздо сложнее. В итоге, для энтерпрайз разработки java выступает не только удобной платформой для разработки, но и во многих случаях обеспечивает приемлемую производительность.
— Использование Unsafe в Java, оправдано или нет? Почему бы тогда не использовать С++?
— Наивно считать, что Unsafe в Java нужен (используется) для того, чтобы выделять и освобождать память в обход сборщика мусора. От хорошей жизни unsafe java коде существует много объектов. Например, в OpenJDK java.util.HashMap использует промежуточные Map.Entry объекты, которые не хранят сами данные, а хранят лишь ссылки на ключ и значение. Такая реализация не только увеличивает накладные расходы на хранение, но и замедляет работу, т.к. обращение к памяти в случайном порядке всегда сложнее и медленнее, чем последовательное обращение. В силу семантики языка, во многих случаях javac и JIT-компилятор вынуждены оставлять этот ворох мелких объектов.
Если же посмотреть на C++, то там хэш-таблицы реализованы без лишних entry объектов. Данные хранятся в памяти компактнее, и значение хранится рядом с ключом. С++ позволяет быть ближе к железу.
Что же делать java программистам? Переходить на тёмную сторону Unsafe, off-heap и иже с ним? В первую очередь, нужно провести измерения, и убедиться в том, что проблема для вашего случая реально существует. Большинство типичных java приложений вполне сносно работают с простыми HashMap под капотом.
Если вы «профессионал на закрытом треке», то можете попробовать эдакое (Unsafe, VarHandlers, memory mapped files, и т.д.). Если для вас проблема действительно важна, то стоит участвовать в обсуждениях JEP 169: Value Objects — там ведётся дискуссия о том, как сгладить проблему лишних объектов в Java без ущерба надёжности кода и скорости разработки.
— Какие наиболее частые проблемы производительности бывают при разработке Enterprise-систем и возможные способы решения?
— Типичные проблемы производительности как правило вызваны не самими языком, а то как разные приложения взаимодействуют между собой. Например, это медленные SQL-запросы. Т.е. неэффективная работа с БД. Если система выполняет тысячи запросов, то производительность зависит не от языка, а от используемых алгоритмов. «Правильное» ТЗ и полнота нефункциональных требований позволяют решить многие потенциальные проблемы. Эта проблемы возникает не только при использовании БД, но она не решается сама собой при переходе к микросервисам. И при неправильной гранулярности API этих микросервисов у нас на ровном месте может возникнуть 1000 обращений и скорость работы будет определяться не скоростью языков, а количеством и качеством этих обращений.
— Что вы можете сказать по поводу скорого выхода JDK 9 и его главной фичи — модульности? Это попытка решить определенные сложности, с которыми сталкиваются разработчики на Java?
— При использовании Java одной и неудобных ситуаций является долгий запуск приложения. Например, при запуске серверного приложения контейнеру может потребоваться 30 и более секунд, зависит от железа и количества загружаемых библиотек.
А почему Java-машина каждый раз при запуске заново компилирует все классы приложения? Почему она не может переиспользовать уже недавно сгенерированный машинный код? Состав .class файлов может обновиться и JVM не имеет никаких гарантий по поводу состава классов приложения. Модульность в JDK9, на первый взгляд, программисту ничего не даёт, а на второй взгляд оказывается, что она даёт очень много самой java-машине. Java-машина может использовать более смелые предположения о том, какой код может выполняться, и таким образом модульность открывает возможность ускорения времени запуска.
Более прозаическая польза от модульности – уменьшение размера дистрибутива java-машин. Вряд ли разработчики стройными рядами пойдут создавать свои сборки JVM ради экономии нескольких мегабайт, но в ряде случаев возможность будет весьма кстати.
— Если очень грубо посмотреть, то разница между C++ и Java — в прослойке runtime, которая, помимо прочего, выполняет всевозможные оптимизации?
— Одна из ключевых возможностей Java — возможность раздельной компиляции кода без потери производительности для конечного приложения. Например, java-библиотека может работать с интерфейсом Iterator. Да, при компиляции библиотеки в байткод там будут «виртуальные» вызовы (invokeinterface). Но это не мешает получать хорошую производительность, если по факту используется одна и та же реализация Iterator в конкретном месте нашей программы. JIT-компилятор видит, какие по факту объекты используются, и он генерирует машинный код без лишних поисков «а где у переданного объекта реализован метод hasNext». В результате программист пишет удобный код на интерфейсах, а при выполнении весь итератор превращается в один-единственный регистр процессора, хранящий «текущую позицию».
Если же говорить про C++, то, если библиотеку скомпилировали и библиотека выполняет виртуальный вызов, то всё, у пользователя нет шансов сделать вызов не виртуальным.
В целом, один из самых действенных способов оптимизации — исключать лишние действия. Для того чтобы C++ библиотеки «видели» особенности их использования, программистам C++ приходится делать разнообразные приседания (clang LLVM, всегда компилировать все библиотеки вместе с кодом приложения и т.п.).
На чьей вы стороне?
Комментарии (142)
Siemargl
30.08.2016 18:37-4То есть из четырех экспертов никто не оценил Java, как быструю. Скорее, как достаточную и удовлетворяющую. Это вполне себе показательно.
robert_ayrapetyan
30.08.2016 18:52-3А по-моему наоборот, миф о быстродействии Java упорно сквозил в тексте… Вообще маркетологи Java в этом плане постарались на славу.
DistortNeo
30.08.2016 18:57+7Я не считаю это большой проблемой. Интерпретируемые языки ещё более медленные, тем не менее, они активно используются в серверном программировании.
Дело в том, что стоимость разработки ПО на Java ниже, чем на C++. Пока выгодно увеличивать мощность серверов, а не платить втридорога за быстрый код, ситуация будет именно такой.
Scf
30.08.2016 19:01+1Просто качественный код на С/С++ почти всегда быстрее качественного кода на Java. Но и недооценивать джавовый оптимизатор не нужно — разница частенько измеряется в единицах процентов.
DistortNeo
30.08.2016 19:09+2От задачи зависит. Обработку изображений, когда она является узким местом, разумнее писать не на Java, а на C++ с использованием SIMD (или даже GPU или Phi), т.к. разница по скорости — разы и даже десятки раз.
А вот для прототипирования хороши будут и MatLab, и Python.
azsx
30.08.2016 18:4450 гигабайт, но чаще и того меньше: от 4 до 8 гигабайт на приложение.
И всё таки я не могу понять этот момент. Язык не может гарантированно быстро работать с оперативной памятью. Сегодня, можно подключать данные в памяти обходными путями. В девятой версии, возможно так не получится.
Как такой язык может быть лучшим выбором для серверного ПО?Scf
30.08.2016 19:04+3Java позволяет писать качественные приложения быстро. И Java позволяет при приложении некоторых усилий писать быстрые приложения. За это ее и любят.
robert_ayrapetyan
30.08.2016 19:23+3Давайте похоливарим. Любой программист на хабре, не пользующийся Visual Studio и vim, на вопрос «что у вас на машине жрет 100500 гигабайтов памяти и столько же процессора» ответит — моя любимая IDE на Java.
Все enterprise-Java системы — неповоротливые монстры, запускающиеся по 5-10 минут, и потом так же медленно жующие данные (привет «любой Hadoop-зоопарк из Java приложений, Druid и т.д.).
При всем при этом, вокруг Java создан устойчивый миф о „быстродействии“, настолько распространенный, что даже данная статья стала возможной (сравнение C и Java пфф..)azsx
30.08.2016 19:43+1Давайте похоливарим.
Даже прочитав разные мнения в стартпосте можно понять, что холивара не будет. Андрей Паньгин не парится, если приложение на ноде потребляет больше 8 гб., то пора думать о второй ноде. Его устраивает такая производительность! Владимир Ситников не парится, если он видит проблемы со скоростью работы приложения (алгоритма), то он внимательно разбирается в сути проблемы и часто оказывается, что приложение делает тысячи sql запросов. При этом java программисты (которых кстати много) не при чем, это им ТЗ дали неверное. Кстати, dba программиста, который еще на этапе тестирования такого «серверного» приложения должен приходить и ругаться (мол, что вы базу так грузите, и что с того что база тестовая, вы что потом такое в продакшен выпустите) видимо нет совсем.
И только Олег Краснов жалеет, что мало открытого рабочего кода на С, который можно просто скопировать, мало. И еще не хватает ему С иногда требуется ассемблер. Он java для своих «высокопроизводительных» задач не рассматривает совсем.
Labunsky
30.08.2016 19:52+1А вы посмотрите на любого другого «монстра» из миров других языков. По большему счету, все утверждения можно будет просто перенести, сменив названия на нужные. В языке ли дело?
webkumo
30.08.2016 20:37+15> что у вас на машине жрет 100500 гигабайтов памяти и столько же процессора
вы удивитесь, но это у меня это хром + фаерфокс.robert_ayrapetyan
30.08.2016 20:59-18Это все утечки в Java-скриптах, натыканных на странице )
Bringoff
31.08.2016 09:09+5Еще остались люди, путающие Java и JavaScript?
robert_ayrapetyan
31.08.2016 16:39+2Вообще-то это была шутка и игра-слов ) Было очень странно обнаружить столько «тугих» пользователей хабра в одном месте…
isotoxin
01.09.2016 00:39Просто они воспользовались удобным случаем продемонстрировать вам свое интеллектуальное превосходство. (если что, это сарказм на тему быстренько заминусовать тех кто «сел в лужу»)
chabapok
31.08.2016 11:07+1Из того, что IDE делают на java и они тормозят и жрут память, не следует, что виновата именно java. Там просто много функционала различного, вот и тормозит, и память жрет. Всякие проверки синтаксиса, проверки грамматики и тд… В vim этого всего нет. Если сделать vim на java — он тоже тормозить не будет, просто это никому ненадо.
iCpu
01.09.2016 07:31А в Студии?
chabapok
01.09.2016 15:41Не имею ни малейшего понятия. Могу лишь предположить, что если студия тоже тормозит, то, вероятно, там то же самое — виноват не шарп.
Вообще, мы когда-то в другой эпохе (помоему даже до Януковича ;) ) пробовали как-то сравнивать шарп с жавой. Скорость шарпа была где-то на уровне жавовского С1 из java6. Но сейчас расклады наверняка другие.iCpu
01.09.2016 18:25Так вот, 2015 студия, открыт проект cocos2d-x-3.6, 15 случайных файлов. Потребляет 350Мб + 6 несколько процессов IntelliSense, которые, хоть и умеют вырастать до неприличия, всё-таки обычно ведут себя скромно — по 100Мб — да и могут быть убиты без непоправимого вреда здоровью (в смысле, сокращены до 1 процесса, тогда анализ и разукрашивание кода немного замедлятся). Итого чуть более 700 Мб, который со временем скукоживается в 450.
Для сравнения, напомню, IDEA на 32-битных убунтах просто не существует. NetBeans сравнить не могу за не имением живого экземпляра оного.
Что до скорости шарпов, напомню, есть такая игра, Terraria зовётся. На шарпах написана. С производительностью там порядок. А Minecraft в своей Story mode переехал с Явы на луа, так как даже он оказался более портируемым и производительным. Хотя, дело, наверное, в пристрастиях студии и изначальном говнокоде автора.chabapok
01.09.2016 20:31NetBeans жрет примерно 400-500мб. Насчет IDEA. У них весьма непонятная политика компании — под каждый чих выделять отдельный процесс с отдельной jvm. Отсюда и потребляемая память. Видимо, они себе память понакупали — и жируют. С 2гигами работает печальненько, 4гига — можно жить. У меня на работе 4гига и 64 система. Полет нормальный, ff или хром все равно жрут больше.
iCpu
01.09.2016 20:54+2Ну, хром… Я, конечно, вспоминаю старую оперу со скупой слезой сожаления, но разве современный интернет способен НЕ выжирать всю память?
IDEA правда странная, но таки щито поделать? В конце концов, никто не без греха, те же бобы значительно уступают в мощи рефакторинга и анализатора как идее в жабе, так и студии в плюсах. Студия в полной сборке тащит под 50Гб хабара, включая виртуальные машины десятки, хрени, андроида, вместе со всеми сдк, ндк и тп. Спасибо, что ставится тихо, глючит не сильно, да и не тормозит почти. А вим нужен выбражалам. Нет, я не против вима, я против выбражал.
А закончу я старым еврейским анекдотом. Выходит Иисус в толпу и говорит: Таки кто без греха, пусть бросит в меня камень! Ай, мама, ну больно же! Сколько я просил не приходить и не мешать мне работать?!
Так и тут, только любимые инструменты мы знаем настолько хорошо, чтобы отбить у окружающих желание их использовать.
vt4a2h
01.09.2016 21:192-4ГБ памяти — у вас там что, телефон для программирования? Вообще оперативки на машинах разработчика уже давно-давно меньше 16ГБ быть не должно. И остальные комплектующие должны быть нормальными, в том числе и SSD уже давно стандарт де-факто. Зачем вообще работать там, где вам даже не могут обеспечить рабочее места?
Думаю, что на нормальном железе IDEA летает просто.
PS Сам я на плюсах пишу, и использую QtCreator в качестве IDE, т.ч. проблем с оперативкой или скоростью работы IDE никогда не испытывал :)iCpu
01.09.2016 22:01Скажи, что мне ещё и с сокета AM2 переезжать пора, да? И что DDR2 уже не торт? И что GeForce 8500 GT уже не подходит для куд-CUDA? Что IDE ушёл навсегда, и бухгалтерия не должна хранить отчёты на дискетах?
Ну же, скажи, что закон Мура не собирается остановиться!
А если серьёзно, программисты придумывают способы понизить производительность программ гораздо быстрее, чем учёные — повысить. Надо бы быть ответственнее.
PS Сам я на плюсах пишу, и использую QtCreator в качестве IDE, т.ч. проблем с оперативкой или скоростью работы IDE никогда не испытывал :)
chabapok
01.09.2016 22:26А зачем? Чем позже заапгрейдишься — тем больше денег сэкономишь. Если компа хватает — это ок, и апгрейдить его ненадо.
Самое главное — это не чтобы хотя бы 2 монитора было, а с 4 гигами пока еще можно нормально жить.
DistortNeo
06.09.2016 10:30Что до скорости шарпов, напомню, есть такая игра, Terraria зовётся
Смотрите более серьёзные игры: Cities Skyline, например.
Написана также на C#, работает под Mono (в т.ч. и под Windows) — никаких проблем с производительностью нет и плюс к портируемости.
qw1
08.09.2016 13:43Minecraft в своей Story mode переехал с Явы на луа
Minecraft Story mode это интерактивная новелла от TellTale? Логично, что для адвентюр, квестов и новелл выбирают Lua или python. Но при чём здесь первоначальный Minecraft, который на java?
asdf87
01.09.2016 17:47Там виноваты COM и 32-битность самой VS, т. е. 3,5Гб должно хватить всем: и студийному GUI, и Roslyn'у, и Resharper'у, и прочим плагинам студии, что живут в том же процессе.
alist
31.08.2016 12:51+5По вашему, программисты на Хабре — сплошные ретрограды. У современного человека 90% памяти на компе сжирают мутные процессы под названием Chrome Helper, Slack и прочие поделия на основе Electron. 300 мегабайт за вкладку с HTML — норма.
Java при всей ее любви к памяти не способна угнаться за Blink, и любимая IDE соседствует с маленьким и скромным хипстерским музыкальным плеером или приложением для заметок.
azsx
30.08.2016 19:28-7Java позволяет писать качественные приложения быстро.
На других языках пишут некачественные приложения и медленно?
И Java позволяет при приложении некоторых усилий писать быстрые приложения.
С оперативной памятью работают с помощью внешней библиотеки! Вот это я понимаю «некоторые усилия».
Хотя большого значение мои «непонимания» не имеют, раз java используется и программистов, а не только менеджеров, всё устраивает — то так тому и быть.
Мне любопытно. Не секрет, что многие гос. сайты и сервисы в РФ активно используют java. Не возможен ли такой час Х, когда компания oracle будет судиться с подрядными организациями создающими данные сайты за «9 строчек кода», например. Дело может и не выиграют, но по судам затаскают. Или волноваться необходимо только google для других компаний и частных лиц такой проблемы нет?struvv
30.08.2016 21:08Не возможен ли такой час Х, когда компания oracle будет судиться с подрядными организациями создающими данные сайты за «9 строчек кода», например
Если не разрабатывать альтернативные реализации JVM, которые не позволяют запустить код, который по стандарту должен работать(т.е. сделать заведомо несовместимую JVM, разбив цельную экосистему на две разрозненные части), то почти наверняка нет(шанс где-то в тех же цифрах, что и шанс падения метеорита на Москву)
lany
30.08.2016 21:31+3С оперативной памятью работают с помощью внешней библиотеки
Не путайте, не "работают", а конкретно apangin работает. У них там такие адовые нагрузки, что без этого нельзя. Мало в мире Java-систем, которым приходится обрабатывать больше данных, чем Одноклассникам. Я думаю, в топ-10 они вполне могут входить. Потому и ухищрения такие. Большинству это не нужно.
fogone
31.08.2016 10:21Так же хочется добавить, что из коробки java тоже умеет работать с памятью без всяких приседаний. У этого решения есть свои особенности, но даже если не брать в расчет, что почти любые инструкции java это работа с памятью и принять версию, что имеется ввиду работа с сырой памятью, говорить, что java для этого нужна отдельная либа — неверно.
lany
31.08.2016 11:41Там довольно извратное управление памятью, чтобы это было фичей общего назначения. Одного взгляда на код reserveMemory должно хватить, чтобы вызвать рвотный эффект.
Тонкость в том, что стандартная библиотека не позволяет явно деаллоцировать память. В противном случае могли бы утечь указатели на деаллоцированную память, что нормальная Java всё же позволить не может. Поэтому деаллокация полагается на стандартный GC, который соберёт ваши хиповые DirectByteBuffer'ы и через PhantomReference (это такой finalize на стероидах) уже освободит off-heap-память. Трудность в том, что у вас в хипе может быть полно места и GC может и не вызываться, а off-heap-память при этом закончится. Отсюда такие странные приседания в reserveMemory.
В общем, DirectByteBuffer надо использовать осторожно и только на ограниченном круге задач. Часто безопаснее ограничиться memory-mapped-файлами, которые могут спокойно выгружаться из памяти.
fogone
31.08.2016 12:07Понимаю, именно по-этому я написал об «особенностях». Но всё же говорить, что инструмента нет, тоже неверно.
cybernomix
30.08.2016 19:32+6Все эти холивары бессмысленны, вопрос лежит в плоскости выше.
Более того, я бы отметил, что Java удивительна еще своей скоростью при тех требованиях что на нее возложены.
Когда вам надо сверхбезопасную среду, по памяти, по вычислениям, кроссплатформенную. Вы не хотите вникать в энтропию проблем которые роятся вокруг разнородных платформ — вы «лиса и хотите фыр-фыр» ©. Если у вас бизнес-задача, где приоритетом является максимальная и параноидальная детерминированность процесса — и цена ошибки выше цены скорости ее выполнения (банки, крупные предприятия) — то очевидно, что Java умеющая правиальную финансовую математику, дотошные проверки, самопроверки, огромную иерархию объектов с тестированием, самотестированием, с аспектными срезами — это ваш выбор.
И ясно что даже если вы сами все это напишите на C++ (что вряд ли) — то получите ту же скорость (а в силу отсутствия у вас сил и скиллов на кв.метр — скорее всего и хуже).
Или простой ответ: вам надо доехать в танке с подушками безопасности и катапультирующейся титановой капсулой на самый крайний момент — ваш выбор Java. Вы едете угрюмо по скорости, но весьма комфортно и спите спокойно, даже за рулем. Или вы хотите просто переехать высокоскоростную магистраль на скейте? Чтобы доставить пиццу? — возможно ваш выбор C++
DistortNeo
30.08.2016 20:18+3Понятное дело, что сравнивать Java и C++ нельзя. А вот холивар Java vs C# был бы более интересен, особенно учитывая то, что глядя на код, не всегда легко понять, на каком языке он написан.
Я работаю преимущественно в науке, а не в продакшене. При этом мне больше нравится C#, потому что
1. Скорость эволюции C# как языка выше, чем у консервативной Java. Те же лямбды в Java появились только через 6 лет после C#. А мегаудобного для сетевых приложений асинхронного программирования в Java пока ещё нет.
2. Удобная визуальная среда для разработки GUI приложений в отличие от зоопарка GUI-библиотек в Java. А за счёт Mono — ещё и кросс-платформенная.
3. Удобная и быстрая IDE, бесплатная для некоммерческого использования.
4. Лёгкость подключения кода из нативных библиотек.
При этом я понимаю, что инфраструктура Java в целом более богата и свободна. Но пока она не нужна — .NET устраивает.mythmaker
30.08.2016 23:17+5- scala
- javafx+scene builder
- IntelliJ IDEA
- JNR
DistortNeo
30.08.2016 23:36-41. Не пробовал — я немного ксенофоб.
2. Ну где ж оно раньше было?
3. Один раз попробовал, но не IDEA, а CLion (ядро то же самое). По сравнению с MSVS оказался неповоротливыми и тормозящим монстром (для Core i7 с PCI-E SSD это непозволительно). Удобство написания кода играет далеко не последнюю роль при выборе языка программирования.
4. Не слышал, спасибо.
Получается, что принициальных различий нет, а выбор языка — дело вкуса. Выбирал по удобству IDE. Менять одно на другое точно такое же смысла не вижу.lany
31.08.2016 11:56+2Насколько мне известно, IDEA и CLion — весьма разные вещи, у них кодовая база слабо пересекается, так исторически сложилось. IDEA на голову выше, про CLion ребята из JetBrains сами говорили, что он далёк от того, чтобы его называть "классной IDE".
Ситуация с MSVS, как я понимаю, сейчас как раз обратная. JetBrains всё сложнее впиливать новые фичи в решарпер, то и дело возникают костыли и подводные камни. 32-битность ещё постоянно бьёт в темечко. Не случайно они разрабатывают Rider — UI IDEA на джаве, а внутри сервисом крутится ядро из решарпера. Было б удобнее всё иметь на Java, но больно много крутого кода в решарпере на C# уже написано, который переписать на Java просто нереально, поэтому такая химера возникла. При этом несмотря на химерность, JetBrains вкладывается в это решение, потому что в перспективе идеевский фронтэнд лучше, чем MSVS.
DistortNeo
31.08.2016 13:23Я с удовольствием попробую Rider и оценю его возможности, но только когда он выйдет. Решарпером не пользуюсь — мне с ним оказалось некомфортно. Очень надеюсь, что в Rider не будет проблем с производительностью.
Правда, у меня есть ещё одно требование: возможность работы и одновременной отладки C#/Java/Scala и C++ кода в одной IDE. Так что IDEA отпадает совсем, остаётся Eclipse против MSVS. Функционал последней побогаче будет.
cybernomix
31.08.2016 00:12-1Уж и Java то прощаем сквозь закрытые пальцы ее пропритеарные щупальца Oracle, но хотя бы нет вендор-лока на ОСь, но с C# вы на поводке .NET и MS, а это уже никак не может быть правильным, особенно в Sci-деве. Не знаю, что у вас за наука, но в научных кругах я слышал тягу к более академичным вариантам. Ну хотя бы Python. Хотя быстрым его не назовешь. Но наука традиционно не тороплива.
DistortNeo
31.08.2016 00:39+2Так и C# — это просто язык. Вендор-лок распространяется на ряд библиотек и технологий, но не сам рантайм, исходники которого выложены в открытый доступ.
Для обмена кода в научной среде удобно использовать лаконичные скриптовые языки: Python, Matlab. Правда, использование Matlab я осуждаю, т.к. это проприетарный продукт с высокой стоимостью лицензии.
Но для себя и заказчиков все равно приходится реализовывать алгоритмы на C/C++, иногда даже с использованием CUDA, потому что Python — это только прототипирование, для реальных применений он не годится.
jbaruch
31.08.2016 18:36+8Холивар Java vs C# будет в следующем эпизоде Разбора Полётов (не в ближайшем, который завтра, а в том, который после него). На секундочку Саша Гольдштейн vs Лёша Шипилёв.
Dark_Daiver
30.08.2016 20:24+1>сверхбезопасную среду, по памяти, по вычислениям
А в чем выражается безопасность по вычислениям?DistortNeo
30.08.2016 20:33Скорее, в чём выражается сверхбезопасность, а не просто безопасность?
Рискну предположить, что безопасность по вычислениям заключается в отсутствии неявных преобразований типов, которые могут привести к потере точности или неоднозначному поведению, а также отсутствии прямого доступа к содержимому переменных: например, вычисление abs(float) можно делать просто сбрасывая старший бит в битовом представлении числа.pohab
30.08.2016 21:09+2>например, вычисление abs(float) можно делать просто сбрасывая старший бит в битовом представлении числа.
JVM так и делает. Про .Net не в курсе.DistortNeo
30.08.2016 22:37JVM так и делает. Про .Net не в курсе.
И правильно делает. Эта реализация архитектурно-зависимая, и вполне вероятно, что на других платформах нужно считать как max(x, -x).
Но когда этим начинает заниматься пользователь — это сразу снижает переносимость когда.
Dark_Daiver
31.08.2016 08:22>Скорее, в чём выражается сверхбезопасность, а не просто безопасность?
Точно =)
Т.е. сверхбезопасность заключается в запрете неявного каста из типа большей точности в тип с меньшей?
Если честно, то я думал об отлове в рантайме всяких 1.0/0.0, sqrt(-10.0) и т.д.DistortNeo
31.08.2016 10:06Если честно, то я думал об отлове в рантайме всяких 1.0/0.0, sqrt(-10.0) и т.д.
А эта штука вообще идёт параллельно и определяется не языком, а режимом работы FPU.pohab
31.08.2016 19:06А эта штука вообще идёт параллельно и определяется не языком, а режимом работы FPU.
Это как раз определяется языком, а FPU уже адаптируют к требованиям языка.
Пример из JavaDistortNeo
31.08.2016 20:06Тем не менее, мне ничто не мешает в процессе работы программы эти исключения взять и включить с помощью платформо-зависимых вызовов. Недокументированная возможность и грязный хак? Возможно. Не знаю, как JVM, но .NET, где логика работы с FP точно такая же, абсолютно корректно обрабатывает эти исключения.
В продакшене такое, конечно, не стоит использовать, а вот для отладки математических алгоритмов для точной локализации проблемного места — почему бы и нет?
asdf87
31.08.2016 10:25+3Извените, но если вы хотите именно «сверхбезопасность» по вычислениям, работе с ресурсами (и памятью в частности) и работе с многопоточностью, то вам однозначно стоит посмотреть в сторону Rust, а не Java. Там эта сверхбезопасность будет на порядок выше. Хотя и надо признаться, что язык еще молодой и разработка на нем будет медленнее раза в 2-3 в силу отсутствия продвинутого туллинга. Но что не сделаешь ради сверхбезопасности? Не так ли?
ishevchuk
30.08.2016 19:47+3СЗОТ.
Не про Java и не C++.
Конечно, для FPGA разработки я использую или VHDL напрямую или пишу MATLAB, который после конверсии VHDL выбрасывает — суть остается та же.
Дмитрий, mezastel, два года назад Вы спрашивали про парсер FIX'a в FPGA и очень хотели не писать на VHDL этот парсер.
В итоге, Вы использовали MATLAB для парсинга или начали «перекладывать битики» с помощью «старого языка» VHDL?
BalinTomsk
30.08.2016 20:47+1----Опять же, в С++ такая проблема, что самых базовых вещей нет в стандартной библиотеке. И это новичка, которому нужно перевести строку, допустим, в нижний регистр или побить по токенам, просто приведет в ступор.
Или я что-то не понимаю?
http://en.cppreference.com/w/cpp/string/byte/tolowerFil
30.08.2016 22:52+1Это для одного символа. Для всей строки не так просто:
std::transform(s.begin(), s.end(), s.begin(), std::tolower);
mezastel
30.08.2016 23:35Для одного символа — да, есть. Для строки — извольте писать сами или boost::to_lower(_copy), причем все это глобальные функции, то есть чтобы найти ее, нужно знать что она вообще существует.
ittakir
31.08.2016 07:14И что, даже русский UTF-8 правильно сконвертирует?
DistortNeo
31.08.2016 08:20Нет, не сконвертирует. Нужно сначала перевести строку из UTF-8 во внутреннюю single-byte кодировку (wchar_t). Кстати, в Java и C# точно такая же ситуация.
barker
31.08.2016 10:52+4Нужно сначала перевести строку из UTF-8 во внутреннюю single-byte кодировку (wchar_t). Кстати, в Java и C# точно такая же ситуация.
Какая такая же? Куда надо в Java и C# что-то переводить из String, чтобы сделать tolower?DistortNeo
31.08.2016 11:10Какая такая же? Куда надо в Java и C# что-то переводить из String, чтобы сделать tolower?
Сначала конвертируем из UTF-8 byte array в string, затем делаем операции над строкой, затем делаем обратное преобразование.
И в C#, и в Java, и в C++ (wstring) символьный тип имеет фиксированный размер (16 бит). Так что можно считать, что внутреннее представление строк — это UTF-16 с игнорированием суррогатных пар.
Да, выше написал неточно: не single-byte, конечно.barker
31.08.2016 11:53+2Не, ну это-то всё правильно. Но обычно строки здесь внутри приложения обрабатываются всё же в виде «строки», которая скрывает реализацию (по сути это wchar/UCS2 какой-нибудь, да). И в байты/обратно (это в том числе о utf-8 или о любой другой кодировке) переводится только в момент ввода-вывода. Т.е. чтобы приходилось в Java байты переводить в string, потом делать операции строковые, а потом сразу обратно в байты — я с ходу затрудняюсь припомнить такой случай в своей практике.
upd Вот на C++ такое случалось, но и то, в «современном» C++ это тоже некомильфо как-то (современный — это после 00х).DistortNeo
31.08.2016 13:47Да, преобразование строки в конкретной кодировке из байтового представления во внутреннее представление и обратно обычно делают всякие StreamReader-ы и StreamWriter-ы. В C++ же потоки не поддерживают автоматическую конвертацию, её приходится делать вручную.
В некоторых случаях и в Java, например, при вычислении SHA256 хеша от строки, строку приходится переводить в байтовое представление конкретной кодировки (обычно UTF-8).
Моё же недовольство заключалось в близком расположении to_lower и UTF-8. Функция to_lower преобразовывает символы (wchar_t), а UTF-8 — это способ хранения этих символов.
lany
31.08.2016 12:03+1Ну почему же с игнорированием? Библиотечные функции (то же
String.toLowerCase()
) не игнорируют суррогатные пары, а корректно их обрабатывают.
Хочу заметить, что внутреннее представление строк в Java не специфицировано. Специфицирован тип
char
(это действительно UTF-16 символ). А строка — это просто строка, вас не должно волновать как она хранится. Нигде не сказано, что это наборchar
или что-то в этом духе. Более того, в Java-9 внутреннее представление строк действительно изменится (будет Latin-1, если все символы Latin-1 и UTF-16 в противном случае). Но опять же вы не должны на это закладываться.DistortNeo
31.08.2016 14:03Да, мне действительно все равно, какое там внутреннее представление.
А что касается суррогатных пар — в Java строки снаружи выглядят как массивы UTF-16 значений, а не массивы символов юникода. Если мы не хотим отказываться от корректной обработки суррогатных пар, то имеем проблему отсутствия произвольного посимвольного доступа при наличии символов с кодами выше 0x10000. Как следствие
— операции toLower и им подобные могут применяться только к строке целиком. Впрочем, и в C#, и в C++ нюансы работы со строками такие же.lany
01.09.2016 02:49+2Ещё раз — не выглядят строки как массивы. Строки выглядят как объекты с набором методов. Посимвольный доступ есть, хотя и может не такой удобный:
StringBuilder sb = new StringBuilder(); myString.codePoints().map(Character::toLowerCase).forEach(sb::appendCodePoint);
Тут все суррогатные пары корректно обработаются. Нет случайного посимвольного доступа, но он обычно и не нужен.
DistortNeo
01.09.2016 03:18Массив имеет индексатор [] и длину length, строка — charAt (в C# — индексатор []) и тоже длину length. Семантически — массив (произвольный доступ по индексу + длина). Но это моё субъективное мнение.
А так да: строка преобразовывается из внутреннего представления в UCS4, обрабатывается, затем преобразуется из UCS4 во внутреннее представление.
Точно такие же действия пришлось бы делать при обработке строк на C++: пробразовать строку из std::string (UTF8) или std::wstring (UTF16) в u32string или использовать потоки.
Отличие заключается в том, что в Java все эти преобразования делаются средствами стандартной библиотеки, а вот для C++ нужно искать сторонние библиотеки, либо писать велосипед.
Кстати, в .NET поддержка суррогатных пар значительно более слабая — нет методов для извлечения кодпоинтов кроме явного преобразования строки в формат UTF32 (int[]) string.toLower.
Alexey2005
30.08.2016 21:15+2C++ сильно подводит среда сборки. В случае Java просто делаем git clone и начинаем работать, а в случае C++ нужно ещё вычислить, какие зависимости нужны проекту и подтянуть их через apt-get, а то и собрать. Почему, ну вот почему нельзя было встроить в среду сборки менеджер зависимостей, чтоб оно подтягивало и собирало их самостоятельно?!
Hronom
30.08.2016 22:39+3Полностью солидарен с Alexey2005
Почему Java лучше:
1. Maven
2. IntelliJ IDEA
3. Интеграция Maven в IntelliJ IDEA
4. Дух опенсорса в проектах которые можно быстро клонировать, открыть в IDE, внести изменения, откомпилировать, запустить
cs0ip
30.08.2016 23:44Знающие люди, поясните за модули в Java. Владимир Ситников предполагает, что это поможет избежать перекомпиляции кода при каждом запуске и позволит собирать более компактные jvm с урезанной стандартной библиотекой. Но ведь для этих целей модули вообще не нужны. Проверить изменения jar-ника можно по «inode + дата изменения + размер» или по хешу в крайнем случае. Модули ведь не дают больше гарантий, чем такая простая проверка? А что касается стандартной библиотеки, можно один большой jar разбить на 50 маленьких и при старте просто проверять наличие/отсутствие файлов по списку. Такая проверка, опять же, ничего не стоит. Получается, что потратили 5 лет (или не знаю, сколько, но много), усложнили жизнь некоторым разработчикам, но зачем?
DistortNeo
30.08.2016 23:56+1Знающие люди, поясните за модули в Java
Речь про модули для C++. Чтобы вместо кучи .h, .cpp, .lib, makefile и прочей муры был один файл, который подключил как jar — и всё работает.cs0ip
31.08.2016 00:01+1Но он ведь конкретно про .class-файлы говорит, поэтому мне кажется, что .h, .lib и пр. тут не при чем.
DistortNeo
31.08.2016 00:30+1Точно, спутал — про модули в C++ первый автор писал.
А про Java же всё понятно написано — кэширование скомпилированного JIT кода.cs0ip
31.08.2016 02:00Ну так в своем первом комментарии я говорю, что для кэширования скомпилированного JIT кода модули вообще не нужны.
webkumo
31.08.2016 12:55Во-первых — вы уверены, что все системы гарантируют наличие и изменение указанных данных? Более-менее гарантирующая проверка — вычисление хеша вряд ли даст экономию времени загрузки.
Во-вторых в java мире принято закладываться (спасибо maven-central!), что библиотека не будет изменена в пределах одной версии. Т.е. изменили библиотеку — измените версию. Нестабильные версии принято отличать по суффиксу -SNAPSHOT (они могут меняться без изменения версии).
По поводу «разбить один большой jar ...» — модульность специально разрабатывали, чтобы можно было удобно управлять этим самым «разбиением».
Т.е. если сильно захочется организовать поставку с jre — можно будет удобно управлять тем, что в неё войдёт.
PS имхо одна из ультимативных фич модульности — возможность скрывать от «пакостливых ручек» классы, которые не должны быть доступны. Т.е. сейчас, например, можно от package private классов отнаследоваться — достаточно создать в своём модуле такой же пакет, модульность должна порезать эту возможность.
Trans00
30.08.2016 23:58+4Сравним молоток и отвертку. И то и другое можно держать в руках. При желании отверткой можно забить гвоздь, а молотком если очень надо можно вкрутить саморез.
Ну вот примерно так же. Java медленнее супероптимизированного кода на плюсах. И никогда не сравнится с ним по скорости. Вот только никому не нужна супероптимизация на уровне всего проекта. Деление сдвигами, паддинг данных, прочие милые шалости. Обычно это нужно в редких сильнонагруженных отрезках кода.
Если критически важно быстродействие вы берете С и пишете что-то простое, но очень быстрое, если нужно навертеть спагетти из бизнес требований в стиле «здесь играем, здесь рыба, а вот этого клиента мы очень любим и даже на рыбе с ним играем», то вы берете инструмент, который позволит следующему за вами программисту не сойти с ума, разбираясь, что как и почему работает.
В итоге выходит, что из трех надо выбрать два:
— сложная бизнес логика,
— максимальное быстродействие,
— сохранение рассудка и желания жить к концу дняmezastel
31.08.2016 11:22На самом деле, при наличии достаточного опыта, навертеть спагетти из бизнес требований можно и на С++. То есть, разработчик с достаточным количеством опыта, может писать любую сложную бизнес-логику и вообще делать все тот же массовый кровавый энтерпрайз. Опять же, хороший пример это Bloomberg, у которых вся платформа на С++. И ничего, живут как-то.
lany
31.08.2016 12:06+1Разумеется, C и даже ассемблер — это не предел. Если действительно "критически важно быстродействие", нормальные люди берут VHDL и зашивают алгоритм в железо. Им смешно читать всякое "у меня супербыстро, потому что Си".
lpre
31.08.2016 07:35-1Андрей Паньгин: Редко, когда мы упираемся в производительность самой Java платформы. Обычно проблемы можно решить либо заменой алгоритма, либо масштабированием, то есть наращиванием железа. Чаще всего узким местом оказывается пропускная способность сети или дисковый ввод-вывод.
Вот как раз масштабированием и изощренными алгоритмами и решаются проблемы с упором в производительность. А вы говорите — «редко»…
lpre
31.08.2016 07:42-1Мы выбираем JVM за те гарантии безопасности, что она нам даёт. В первую очередь — защиту от фатальных ошибок из-за неправильной работы с памятью. Искать проблемы, связанные с указателями или выходом за границы массива, в неуправляемом коде на порядок сложнее.
В конечном итоге все упирается в квалификацию и дисциплину разработчиков. Java с её «гарантиями безопасности» позволяет достичь результата, используя менее квалифицированных программистов. Экономически это выгодно, конечно.struvv
31.08.2016 08:42+5Тут скорее так- при одной и той же квалификации в обоих языках выгоднее использовать язык, на котором делать продукт можно быстрее(включая выполнение всех требований по скорости, памяти и кроссплатформенности, которые есть у данного продукта).
А так java — это всего лишь инструмент, как и с++. Нет такого расового деления — разработчик java/разработчик c++.
Но все любят делить на A и B. Усугубляет это тот факт, что обычно люди склонны сильно недооценивать сложность работы специалистов в не знакомой ими досконально технологии из-за вот этого эффекта. Можно сказать, что и среди разработчиков распространён расизм и илитаризм, только языковой, не имеющий под собой никаких оснований, кроме когнитивных искажений. В рамках каждой экосистемы есть огромные айсберги компетенций и пресловутый GC, гарантии безопасности и Стандарт это только вершина, не разумно судить именно по нейlpre
31.08.2016 10:17-1
Это практически одно и то же, но «вид сбоку».Java с её «гарантиями безопасности» позволяет достичь результата, используя менее квалифицированных программистов
при одной и той же квалификации в обоих языках выгоднее использовать язык, на котором делать продукт можно быстрее (включая выполнение всех требований)
К тому же, есть нюанс в определениях «одинаковая квалификация» и «выполнение всех требований». Исходя из нашего опыта, для написания безопасного (с точки зрения работы с памятью и другими ресурсами) кода на C++ в среднем нужна более высокая квалификация, чем для кода на Java.
Нет такого расового деления — разработчик java/разработчик c++.
На самом деле, такле разделение есть. У нас есть как те, так и другие, и мы не будем Java программистам ставить задачи с разработкой на C++, и наоборот. Да они и сами не возьмутся без крайней необходимости.
lpre
31.08.2016 07:47Что предпочтительнее: использование архитектурных особенностей машины вручную (С++), либо лучше положиться на динамические оптимизации JVM?
… но не сильнее «ручной» настройки компилятора C++ :-) В лучшем для JIT случае — он так же силен (что вряд ли).
— Адаптивная компиляция и автоматическое управление памятью — как раз сильные стороны Java.struvv
31.08.2016 08:14+2Сильно зависит от проекта. Если проект разрабатывает 30 человек и в нём ТЗ на 1000 листов и всё это с спринтами в 2 недели, в которые вряд-ли можно впихнуть профилирование и оптимизацию, то ручная оптимизация всего проекта вряд-ли возможна. А JIT работает всегда.
Если это какое нибудь скоростное хранилище на C99, то тогда можно добиться максимальной производительности путём настроек оптимизаций.lpre
31.08.2016 08:31-1Автоматическая оптимизация C++ компиляторов тоже «всегда работает» для всего проекта любого размера.
Возможность настроить (оптимизировать) компиляцию отдельных частей проекта (причем при необходимости — по-разному для разных частей) — это «бонус», которого нет в JIT.struvv
31.08.2016 08:44-1JIT оптимизация работает лучше, чем автоматическая статическая оптимизация(она точно также есть и у java), но в некоторых случаях хуже, чем ручная.
Siemargl
31.08.2016 08:54Голословное утверждение. Не видел ни одного примера, чтобы на вычислительных задачах Java выиграла у релизной сборки С++. На реальных задачах — сеть, СУБД, это уже не так заметно.
Но если представить выставление параметра -O3 ручной оптимизацией, то утверждение становится верным =)
Dark_Daiver
31.08.2016 09:13На самом деле, очень бы хотелось увидеть, пример реальной вычислительной задачи где адекватно написанный С++ с -О2/-О3 проигрывает Java + JIT. Только задача должна быть действительно реальной, т.е. не тестирование аллокаций тысяч malloc(sizeof(int)) и тому подобное. И чтобы JIT не вырезал тестируемый код как неиспользованный.
Для ясности — я не то чтобы пытаюсь доказать что С++ быстрее Java, меня больше волнует, почему в С++ не впиливают JIT если он эффективней чем статические оптимизации.DistortNeo
31.08.2016 10:32+3Вы не о том спорите. Принципиальная разница между JIT и статической компиляцией — первая работает во время выполнения программы и потому сильно ограничена во времени. То, на что статический компилятор может потратить минуты, JIT должен успеть за секунду.
Особенно сильно разница видна в задачах обработки изображений:
1. Использование векторных инструкций, которое возможно в C++, но невозможно в Java. Современные компиляторы (как статические, так и некоторые JIT) умные и могут векторизовать простой код, но для сложных задач все равно приходится использовать платформо-зависимые intrinsics, которые дают ускорение в разы по сравнению с обычным кодом.
2. Прямой доступ к памяти без проверок и обёрток в C++ будет быстрее, чем в Java.
3. Статическая шаблонизация в C++ генерирует эффективный код, альтернатива в виде generics, разрешаемых в рантайме, имеет совершенно другое предназначение.
Небольшой момент: не знаю, как в C++, но из generics в C# таки можно выжать максимум производительности, если в качестве шаблонных параметров использовать только структуры — в этом случае JIT будет генерировать статические конструкции.Dark_Daiver
31.08.2016 17:40Ну я как бы про все это в курсе.
Еще бы добавил, что в С++ есть возможность создавать сложные value types (классы/структуры), что положительно отражается на кэше процессора.
Просто выше проскочило высказывание о том, что JIT дает более эффективный код чем статические оптимизации, и мне стало интересно.DistortNeo
31.08.2016 17:51+2> Еще бы добавил, что в С++ есть возможность создавать сложные value types (классы/структуры), что положительно отражается на кэше процессора.
Если рассматривать JIT в целом, а не только к Java, то в .NET тоже есть возможность создавать value type. И работа с ними тоже получается эффективной.
Scf
31.08.2016 18:39+1Вообще дает, в некоторых случаях. Разумеется, не на специально оптимизированном коде, а на коде общего назначения. Примеры:
- Java умеет оптимизировать код "оптимистично" — например, вместо проверки на null вставить SEH, который при вылете сгенерит правильный NullPointerException. И приведет к перекомпиляции этого куска кода уже с проверкой. Либо заменять виртуальный вызов на прямой, даже если в приложении существуют два разных класса-потомка.
- выделение памяти в джаве не требует синхронизации и работает намного быстрее сишных аллокаторов
lpre
31.08.2016 22:59+2В C++ можно минимизировать явное динамическое выделение памяти в пользу автоматического создания объектов на стеке, которое и работает намного быстрее любого аллокатора и без блокировок, и к тому же безопаснее. Например, нет указателей, которые нужно было бы проверять, ресурсы выделяются/удаляются в exception-safe режиме (RAII). Причем в C++ такой подход считается не специальной оптимизацией, а обычным рекоммендуемым подходом. Вряд ли JIT смог бы здесь что-либо улучшить.
Scf
01.09.2016 12:18Если вы про выделение памяти на стеке, то это далеко не универсальный подход… а) стековый объект нужно выделять явно б) компилятор (насколько я знаю) не умеет оптимизировать new в стековый объект и в) стековый объект имеет фиксированный скоуп и время жизни, что часто полезно, но ограничивает область применения
lpre
01.09.2016 13:56+1Я и не говорил об универсальности. Я сказал, что «можно минимизировать явное динамическое выделение памяти» (те самые new/delete или malloc/free).
a) наоборот: память под стековый объект выделяется неявно (автоматически), и так же неявно (автоматически) освобождается. Программисту ничего не нужно для этого делать (ни «new», ни «delete»), кроме соответствующего объявления переменной без указателей и ссылок, и (опционально) инициализации (если default инициализация не устраивает).
Вы, вероятно, «явное объявление переменной» назвали «явным выделением», однако это не одно и то же. Например, «явно объявленная» переменная типа «указатель» не означает, что соответствующий объект будет действительно выделен — вам в дополнение к объявлению еще и явное выделение нужно сделать (используя «new»), а затем и явное освобождение («delete»). А вот при «явном объявлении» стековой переменной (не указателя и не ссылки) память будет автоматически (==неявно) выделена и освобождена.
б) Этого и не требуется. «new»/«delete» — это тот самое явное динамическое управление ресурсами, использование которого следует минимизировать.
в) Да, время жизни ограничено текущим блоком. Но при грамотном использовании это существенно улучшает код сразу в нескольких направлениях: простота, безопасность, производительность. Причем до такой степени, что аргументы в пользу JIT типа «оптимизация проверки на null и быстрое выделение памяти без синхронизаций» становятся бессмысленными: в C++ можно с легкостью писать код, в котором эти улучшения «встроены генетически».Scf
01.09.2016 15:26Мы говорим об одном и том же. Локальные объекты — вещь полезная, но не панацея. К примеру, возьмите любую нетривиальную программу на С++ и замените глобальный operator new/delete на аллокатор им. Александреску (который с константным временем выделения-освобождения памяти) — разница в производительности будет существенной.
lpre
01.09.2016 16:42+1Никто и не говорит о панацее. Иначе new/delete выбросили бы из стандарта, чего точно никогда не произойдет.
замените глобальный operator new/delete на...
Переопределение операторов new/delete ничего не даст, т.к. смысл в отказе от их явного использования. Так что это не сработает.
Следует изначально стараться писать код с минимумом new/delete, либо подвергнуть его рефакторингу.
По-поводу замены всех операторов new: да, в реальной большой программе полностью сделать это не получится.
Однако даже минимизация их использования уже приведет к указанным бонусам (простота, безопасность, производительность).
Хотя время жизни «автоматических» переменных и ограничено текущим блоком, большинство таких блоков вложены в другие (причем многократно, вплоть до функции main на самом верху, где время их жизни равно времени работы программы). Стековая переменная, созданная на одном уровне, гарантированно существует для всех своих «потомков» (вложенных блоков или синхронно вызванных функций/методов), которые могут безопасно использовать её. Так что область использования таких переменных может быть намного больше, чем может показаться на первый взгляд.
struvv
01.09.2016 08:46+3Вычислительные задачи это один из многих классов задач — в любом случае это написание кода на максимально близкого к asm. В этой области JIT и не конкурирует, т.к. гарантии в runtime не совпадают, чтобы сравнивать эффективность работы компиляторов. Если нам нужно именно дробить числа, то мы берём
ASIC,FPGA,GPUCPU и родной компилятор FORTRAN/Си/C++ к нему и начинаем усиленно дробить числа.
А вот в рамках родной для Java ООП, SOLID, etc — т.е. кода общего назначения компилятор JIT показывает очень хорошие результаты.
Сравнение компиляторов сложно завершить выводом, выше я сделал, что является ошибкой, я понял, что мы сравниваем совершенно разные вещи, хоть и называем их одинаковыми словами.
Например предположим я пишу правильный с точки зрения ООП/Solid код, который работает скажем с изображениями. Я не использую никаких оптимизаций лично и вообще не знаю конкретную архитектуру процессора. В идеальном мире я полагаюсь на абстрактное железо, а как оно там внутри работает мне должно быть не интересно(речь не о любопытстве) ибо инкапсуляция.
-При этом я говорю о том, что в данном случае компилятор занимается оптимизацией, а не я занимаюсь оптимизацией. Вот именно по этой характеристике я субъективно считаю javac,hotspot лучше, чем gcc.
-Но если именно я занимаюсь оптимизацией, а компилятор лишь призван не мешать/иногда помогать, то тогда лучшие результаты будут на С. Но при этом я называю это словами — я делаю лучшую оптимизацию, а не компилятор делает лучшу.оптимизациюDark_Daiver
01.09.2016 23:05>Вычислительные задачи это один из многих классов задач — в любом случае это написание кода на максимально близкого к asm.
Не совсем. Дело в том, что между случаем когда надо написать сверхоптимизированный код и случаем когда надо как можно быстрее написать прототип алгоритма, есть огромное количество промежуточных случаев когда нужен достаточно быстрый и при этом легко расширяемый/читаемый/абстрактный код. Ведь достаточно сложные алгоритмы, как и «обычный» код, так же нужно развивать, в них нужно фиксить баги и т.д. А в делать это с кодом который сильно заоптимизирован вручную довольно трудно.
Тут то на сцену выходит С++ с его zero cost abstraction.
И оптимизациями (разворачивание циклов, инлайн? девиртуализация, RVO, etc) занимается компилятор. И весьма неплохо.
lpre
31.08.2016 10:43Это только если делать программы для использования на широком спектре железа. Тогда да, JIT может динамически подстроить программу под тип и количество CPU и т.д. В принципе, это могло бы дать Java некоторое преимущество (хотя и это спорно) на, к примеру, зоопарке десктопов, если бы не чрезмерная требовательность к ресурсам.
Однако все опрошенные эксперты говорили об «интерпрайзе». Это значит — свои серверы, или по крайней мере — с исзвестной архитектурой. Статическая компиляция своего C++ кода с настройками под конкретную архитектуру сервера + перекомпиляция некоторых из используемых библиотк (делается 1 раз для каждой версии библиотеки) убивает указанное преимущество JIT.mezastel
31.08.2016 11:29Да, для серверов с известной архитектурой так и делается: оптимизации соответствуют тому процессору, который во всех нодах кластера. Плюс к этому, если сервера вообще ваши физически, вы можете в них втыкать всякие ускорители, и не важно взяли вы Xeon Phi или Tesla, это все равно программируется на С/С++.
lpre
31.08.2016 08:10-2Владимир Ситников: Если же говорить про C++, то, если библиотеку скомпилировали и библиотека выполняет виртуальный вызов, то всё, у пользователя нет шансов сделать вызов не виртуальным.
О какой оптимизации речь? Производительности разработчика? Так вопрос был о рантайме.
В целом, один из самых действенных способов оптимизации — исключать лишние действия. Для того чтобы C++ библиотеки «видели» особенности их использования, программистам C++ приходится делать разнообразные приседания
Вообще-то, описанная как недостаток (да еще с точки зрения оптимизации в рантайме) особенность C++ дает прирост производительности по сравнению с Java. Причем как с точки зрения скорости начальной заргрузки программы, так и «рабочей» производительности.
firegurafiku
31.08.2016 10:26+1[HFT в основном тяготеет к] использованию всяких FPGA, где и системный С присутствует…
Думаю, не следует переводить System C таким образом: это, всё-таки, имя собственное.
elmirius
31.08.2016 10:26«И то, вот есть у меня строка, хочу ее побить на подстроки по пробелу — этого в стандартной библиотеке нет, то есть я должен брать стороннюю библиотеку (ну благо есть такая штука как Boost, там много полезного).»
Дальше не читал. Это как подключать для использования одной функции swap.
Jogger
31.08.2016 10:26+1>Прежде всего, я не считаю, что между этими языками существует какая-либо конкуренция. У каждого из них есть своя ниша, и они прекрасно сосуществуют вместе.
Мне кажется дальше можно уже не читать. Холивар на этом исчерпан.
superyateam
31.08.2016 10:26-2наивный спор: Java vs. C++. Хорошо спорить, когда знаешь, что от результата спора ничего не зависит.
я предлагаю другой спор: Java vs. Javascript. Здесь на карту ставится карьера Java-программистов. Почему? Потому что, начальнику отдела разработки в какой-то момент покажется более дешевым переписать весь бэкенд на Node.js. Потом ему приходит в голову другая мысль: давайте использовать AWS Lambdas для реализации микросервисной архитектуры. Вы все еще продолжаете спор? Возможно, вы даже выиграете, но работу вам придется сменить, потому что компании джава-программисты больше не нужны. Хорошо когда в компании 10-30 программистов, но что делать, если 200-1000? У простого программиста практически нет шансов достучаться до большого начальства — просто в один прекрасный день приходит письмо, что теперь компания использует javascript, и после этого можно только и спорить о том, что лучше C++ или Java на хабре.
Хорошо было бы, если спор Java vs. C++ был действительно актуальным…SirEdvin
31.08.2016 13:25+3"Потому что, начальнику отдела разработки в какой-то момент покажется более дешевым переписать весь бэкенд на Node.js. "
А потом разработчиков увезут в комнатки с белыми стенками.
asdf87
31.08.2016 15:09Ну зачем же так сразу? В крайнем случае место работы всегда можно сменить на более адекватное.
Cryvage
01.09.2016 05:22+1То есть начальник отдела разработки ВДРУГ решает переписать все, что уже есть и работает, на другом языке, при этом попутно уволив проверенную годами команду из 1000 человек, и наняв одномоментно 1000 новых разработчиков? Он, либо безумен, либо работает на конкурентов.
superyateam
02.09.2016 01:46Вы будете смеяться, но примерно так и есть. Я конечно утрировал «немного», но процесс примерно следующий: есть общий тренд, который развивается уже не один год, о переходе на подписочную модель. Чтобы реализовать такую модель и не прогореть, приложение нужно строить на принципах SaaS, Multitenancy и прочее. Дальше начинается чистая математика: открываем Amazon Calculator (я говорю Amazon, как один из наиболее популярных вариантов) и смотрим сколько стоит, например EC2 vs. Lamdba (если не нравится AWS, то к примеру Azure WebApps vs Azure Functions). Если финансовые гении компании после месяцев сидения за калькулятором приходятся к выводу о том, что лямбды намного дешевле, то дальше дело техники.
Выясняется, что js в лямбдах работает быстрее. Выясняется, что поддерживать js-лямбды проще, чем джавовские.
Добавляем в смесь еще кучу других модных тенденций (как насчет микросервисных архитектур или подхода Serverless) и получаем неутешительный вывод. Ваш сервер написанный на яве начинается быстренько дробиться в микросервисы и переписываться на Node.js.
Вой поднимается до небес, но поделать с этим уже ничего нельзя. Бизнес есть бизнес. А ваша карьера программиста продолжается уже в другой компании.
p.s. Никто не будет никого увольнять и нанимать заново. Переучивать — запросто.fogone
02.09.2016 10:50Это какая-то дикая фантазия или вы действительно такое в жизни встречали? Больше похоже на первое.
superyateam
02.09.2016 21:47Прямо сейчас это происходит в моей компании (SF Bay Area) и судя по рассказам друзей в других компаниях тенденции схожие.
struvv
02.09.2016 21:42Node- 1Gb heap, дальше 100% GC, неопределённое поведение после ошибки(спасибо партии за это, раньше был тупо краш всего приложения), внезапные утечки памяти хрен пойми где, в исходные код npm модулей, полезных для бизнеса, лучше не смотреть во избежание необратимого повреждения психики. Для своих задач нода работает нормально, но я бы не доверил приложению на ней ни одну копейку.
И микросервисы очень весёлая штука — особенно при отладке.
Maccimo
01.09.2016 07:57Перечитал комментарий пару раз, но так и не смог понять, в каком месте карьера Java-программистов «ставится на карту».
Это что, единственный работодатель в городе, где такая карьера возможна?
iCpu
01.09.2016 08:45Наивный спор: Java vs. Javascript. Хорошо спорить, когда знаешь, что от результата спора ничего не зависит.
я предлагаю другой спор: Кофе против Чая. Здесь на карту ставится карьера Кофеманов. Почему? Потому что, начальнику отдела разработки в какой-то момент покажется более дешевым пересадить на хороший Чай. Потом ему приходит в голову другая мысль: давайте использовать «принцессу Канди» для реализации снабжения сотрудников кофеином. Вы все еще продолжаете спор? Возможно, вы даже выиграете, но работу вам придется сменить, потому что компании Кофеманы больше не нужны. Хорошо когда в компании 10-30 Кофеманов, но что делать, если 200-1000? У простого Кофемана практически нет шансов достучаться до большого начальства — просто в один прекрасный день приходит письмо, что теперь компания использует чай «Майский», и после этого можно только и спорить о том, что лучше Java vs. Javascript на хабре в комментах.
Хорошо было бы, если спор Java vs. Javascript был действительно актуальным…
vt4a2h
31.08.2016 10:40C++ занимает свою нишу в трех основных дисциплинах (game dev, финансы и embedded)
mezastel, на самом деле есть еще одна ниша, где C++ обосновался довольно плотно. Это VFX (visual effects) софт, который включает в себя почти весь софт по пост-продакшен обработке изображений (в том числе и софт для трекинга элементов изображений, VR и прочее). Традиционно, программа на C++, GUI на QWidgets/QML, скриптинг на Python. Есть даже стандарт, который версии регламентирует (http://www.vfxplatform.com/). Так что еще и вся киноидустрия «сидит» на C++ :)mezastel
31.08.2016 11:10Не знал. Но вообще логично. В плане image processing все конечно в основном на С++ (ну и CUDA местами). У Adobe весь софт на плюсах написан.
Dark_Daiver
31.08.2016 17:43Строго говоря, еще можно добавить всякий сложный scientific computing для продакшена: компьютерное зрение, трехмерное сканирование, машинное обучение и т.д.
potan
31.08.2016 22:00-1Эх, почитаю я когда-нибудь холивар «Scala vs Rust»?
vt4a2h
01.09.2016 16:19+1Надеюсь, что этого не случится, т.к. сравнивать Scala и Rust еще более глупо чем Java и C++, т.к. они вот уж совсем разные и для разного. Я имею ввиду не разумно сравнивать, исходя из задачи, а именно холиварить.
beTrue
01.09.2016 17:09-3По сабжу, С++ вместе с Boost в достаточной степени кросс платформенный, т.е. разбираться в WinAPI или Posix API не обязательно (оставим это ценителям чистого С), не обязательно, но желательно иметь представление о «системколлах» и что за ними, в независимости от используемого языка (имхо, все разработчики С++ это знают, а Java программисты могут не волноваться).
Тот же Boost уже 100500 лет имеет умные указатели, и они давно уже в STL, но можно и руками рулить памятью, здесь управление памятью не может быть критерием оценки.
Отсутствие библиотек в С++ сомнительно, нет, их просто не до большого, а вот фреймворков действительно мало, но нельзя сказать что их нет совсем (ACE, TAO, CIAO), более того, солидный и ответственный производитель всегда зарелизит вам либы для своего продукта под С++, ведь этого требует индустрия, проверьте сами, от ИИ библиотек до брокеров сообщений, всегда найдется вариант.
При этом Java это EJB и Spring + попытки решить нерешаемые этим языком вопросы: Roo, Integration, Xtext, Xtend — это всё дич, кажется что myEclipse появилась от непреодолимого желания перестать писать на Java. Java как язык — это 1/3 XML ада минимум, а в JEE гораздо больше, метапрограммирование в Java нет, если сравнивать с магией прекомпила С++.
Boost — это либы уровня паттернов программирования, MSM, Proto, Spirit, сеть, указатели, контейнеры, — небольшие библиотеки, но очень мощные, да, ошибки компил_тайма на 20 экранов, ну и что.
С++ — язык с которого стоит начинать, если нет возможности/желания начинать с С, добиться просветления в ООП, АОП (например 10-Jul-2016 AspectC++ Release 2.1, т.ч. аспекты тоже не критерий оценки, они есть и в С++), ФП и метапрограммирование, дальше по ситуации, при этом начинать со стандарта 2003 года, и постепенно двигаться в 2017.
Java — язык на котором стоит пару лет поработать, что бы встретить Scala, перейти по самые помидоры в ФР, забыть о сайд-эффектах, адовом хмл, спагетти-коде, и твердо решить для себя, что после запланированного Хаскеля, с достигнувшим критической массы ФП-бэкграундом, стоит всё же вернуться в С++.
Если коротко, то сегодня без JVM невозможно представить индустрию, язык Java всё больше старается походить на Scala, но кода меньше не становиться. С++ крут, но сегодня, будучи студентов, не за что бы не начал изучение стандарта даже 2011, тяжело для глаз (м б сказывается привычка к Scala лаконичности).
И про Одноклассников, да, они весёлые ребята, переписать всё с диеза на Java — только у нас такое возможно. Напомню про hiphop, hack и весь этот hhvm, где «брюки действительно превращаются» в С++, и Хаскель фильтрует спам.
beTrue
01.09.2016 17:32резюмируя простыми словами, можно сказать, что с большей вероятностью, сильных разработчиков можно встретить в С++ и Scala, т.к эти языки гораздо многограннее и более навороченнее, чем Java, плюс желание Java программистов ощутимо меньше изучать Scala, чем желание C++ программистов изучать Java, и дело не в рынке, а скорее в регидности ;)
п.с. Одноклассники просьба себя не сдерживать и заминусовывать, только жаба быстрее не станет.beTrue
01.09.2016 17:36как вы наверное заметили, желание после Java изучать С++ не рассматривается в принципе;)))
zip_zero
А что значит аббревиатура OS в этом контексте?
ARG89
Опечатка, OSS, конечно же.
Поправил.
ArtiomCX75
Возможно имели в виду «NetCracker OSS».
proos
тогда уж Netcracker OSS, потому что «С» большой буквой уже не пишут — ребрендинг, все дела.
zip_zero
Неожиданно захоливорили про печеньку. Бояре, ну как так…