Pull to refresh

Comments 81

Хорошая статья, спасибо.
А по поводу изменения кода в памяти и перемещения указателя: можно просто поставить брейкпоинт и в нём уже запустить Evaluation окно с отдельным кодом внутри, который подцепит все переменные и так далее.
UFO landed and left these words here
Ничего удивительного, если судить по доменной зоне и рассказам о том, что там были структуры и всякая другая магия, можно предположить, что там много сложной математики и алгоритмики именно с числами и прочим.

А тут нужны cython + numpy и сверху еще numba было бы неплохо. А чистый python сильно проигрывает :(

Ну или pypy, как предлагают ниже, но numba должна быть круче.
основные реализации python — не полноценные вм, как у java/c#, а обычные не оптимизирующие интерпретаторы. python хорош для использования библиотек (особенно написанных на c/c++), но не для их написания. И уж тем более не для арифметических задач.
Да что на него смотреть — код как код. А вот сгенерированные коды на Java и Python можно посмотреть на сайте (www.pullenti.ru/DownloadPage.aspx). А первая задача была — это чтобы сам генератор, который на .NET, перевёл сам себя в Java и также работал.

Попробуйте использовать PyPy вместо CPython, он с JIT компиляцией. На данный момент поддерживает Python до 3.5 включительно. (Легко) можно получить прирост в скорости до x10. Код переписывать не надо.

Извиняюсь, забыл указать в статье, что Python запускал в Eclipse под PyDev (подправил статью). Может, в какой другой среде это будет побыстрее.
а не логичнее ли наладить interoperability компонентов, написанных на разных языках?
Но оказался неправ — C# всего на 15-20% быстрее Java (запускал из Eclipse под Windows), а не в несколько раз, как ожидалось

вы всерьез сравниваете производительность оригинального C# кода и автогенерированного, использующего оболочки и эмулирующего C#-концепции Java-кода?
Не проще просто писать на java, которая в отличие от кое-чего запускается на нормальной серверной ОС? Виндовс-сервер это оксюморон. В тепличных условиях пусть будет +15% (лениво проверять), а через полгода шындовш уже пучит и таращит, через год минус 50% производительности
Стыдно в 2018 поливать грязью .net-платформу и не знать про .net core
Стыдно должно быть сравнивать зрелые платформы SE и EE с этим. Когда от например RedHat появится решение и саппорт, тогда и поговорим о core
Как определяется зрелость платформ? Год, пять или десять лет?

На RHEL есть поддержка .net core: пруф.
Если мерять годами, то язык brainfuck (создан в начале 90х) всегда будет более зрелым решением, чем net core. Шах и мат, микрософт. :) не вижу смысла продолжать тему сравнения зрелости net и java
UFO landed and left these words here
По вашему если что-то сделать опенсорсным, оно мгновенно и обязательно превращается в конфету? У МС есть что-то подобное java EE? Если нет, то им еще лет 10 надо сидеть молча и пилить, пилить.
UFO landed and left these words here
asp.net чтоли? фанбои, такие фанбои
UFO landed and left these words here
UFO landed and left these words here
Самый кривой софтописатель планеты выпустил Net core 2 восемь месяцев назад, и оно уже успело порвать по всем фронтам java ee с 20 летней историей и десятками независимых вендоров. Ещё и такие откровения, что java в 2018 году вдруг испортилась. Прямо как селёдка, два года назад вполне ничего было, но внезапно всё пропало. Еще про раст расскажите, как он убил java и cи.
UFO landed and left these words here
У меня, кстати, к МС претензии ко всем продуктам от кривого гипервизора до отвратительного Word-а (жизнь заставляет иногда в нем верстать). Так что опенсорсность core ничего не меняет
UFO landed and left these words here
Офисный планктон вышел в облака и использует Google Drive, не?

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

UFO landed and left these words here
Ещё очевидно, что программы не берут данные из воздуха и не складывают в воздух. А известно как в винде работают субд. Какая тормозная ntfs и тд и тп. В итоге скорость ПРОГРАММНОГО КОМПЛЕКСА под net обгоняет java только при очень непрямых руках и в get the facts
винде работают субд

Причем тут винда и субд. Например, сейчас есть в продакшене система на .netFramework, которая ходит на Oracle, который в свою очередь установлен на линуксе.
Плюс майкрософт сделала порт своего SQL Server на линукс. поэтому ограничений в .net, почти нет (ну кроме нормальных кроcплатформенных ГУИ, но я бы тут взял или QT или Electron)
Клиент на dotnet, бизнес-логика на могучем plsqlчике, третий уровень не завезли? Я тоже видел тонны подобного крапа от подрядчиков нашей конторы. К обсуждаемой теме performance оно каким боком? :)
UFO landed and left these words here
вы всерьез сравниваете производительность оригинального C# кода и автогенерированного, использующего оболочки и эмулирующего C#-концепции Java-кода

Ну да, тем более, что обёрток там не так уж много, и для несущественных для производительности объектов. А так всё идентично — классы, методы, циклы, ветвления, массивы и пр. стандартные конструкции. Хотя, может, каких-либо «блох» и можно отловить. В принципе, генерируемый код Java выложен на pullenti.ru/DownloadPage.aspx, если Вы там обнаружите навскидку какие неэффективности — буду признателен!
Еше во времена .NET 1.0 сами Microsoft такое пробовали (конвертер из Java в C#, ЕМНИП было в VS.NET 2003). Не взлетело, и уже в VS 2005 убрали. А наоборот — полагаю что даже сложнее будет.

Наверное имеется в виду J#
https://ru.m.wikipedia.org/wiki/Visual_J_Sharp


"Заявленной целью разработки Visual J# было облегчение перехода разработчиков с платформы Java на платформу .NET Framework. Однако эта цель достигнута не была" =)

Редактирование кода на лету имеет ряд ограничений: нельзя добавлять/удалять классы/внутренности классов, нельзя править генераторы и прочие методы, которые разворачиваются в машины состояний, нельзя править методы, содержащие лямбды, и многое другое. Остаётся процентов 20-30 тривиальных случаев.
Зависит от проекта. У меня таких случаев как раз 80-90% (обработка естественного языка), и весьма нетривиальных.
Код на производительность тестировался как? Сконвертированный сравнивался с исходником, или нормально переписывался с учётом особенностей целевого языка? В первом случае любой код будет медленнее исходного языка.
Нормально переписать нет никакой возможности — проекту около 7 лет, там сложные алгоритмы лингвистической обработки, морфологический анализ, выделение именованных сущностей (NER). Повторю, что использовались только «стандартные» языковые конструкции, эквивалентные в .NET и Java (от экзотики я избавился в ходе работы над конвертером). Не думаю, что можно как-то существенно оптимизировать код Java (см. результат генерации pullenti.ru/DownloadPage.aspx?file=PullentiJava.zip). Может, есть какие тонкие настройки оптимизации в самой среде Eclipse. Например, когда я начинал запускать в NetBeans, то там скорость почему-то была медленнее раза в 2. Скажем, в Visual Studio в режиме Debug скорость меньше на такие же 15-20%, чем в Release. Хорошо бы ещё проверить под Unix, но нет под рукой. Но в целом можно утверждать, что скорость примерно одинакова.
То есть в сущности это не сравнение производительности, а просто проверка того, насколько просела производительность после автоматической миграции.

Так как есть JPython, то может быть даже достаточно перегонять только в питон, для джавы написать отдельно интерфейс.

В Java тоже есть редактирование кода на лету, правда работает оно не из коробки — нужно запускать на пропатченном jvm и с java agent'ом. (Для dcevm актуально). Это всё не сложно сделать. Хотя перенос, как вы выразились, «текущей позиции», всё же не поддерживается, насколько я знаю.
dcevm.github.io бесплатная
zeroturnaround.com/software/jrebel платная, очень платная
Я пользовался обеими и для большинства случаев первого хватит. Насколько я помню, основное отличие в поддерживаемых framework'ах — т.к. при изменении кода иногда нужно учитывать работающие в приложении framework'и и дёрнуть их методы (например, добавили поле которое испольуется в DI и его нужно инициализировать, вот dcevm и jrebel посмотрять, что у вас за DI framework используется и применят его)
Но по опыту — если такая фигня начинает быть важна, значит что то не то в архитектуре приложения — поидее всю логику работы нужно уметь востанавливать по логам и быстро воспроизводить в тестах. По крайне мере мне эти штуки пригодились только на таких проектах — тестов нет, запускается очень долго, и поэтому приходиться в run time код писать :-)
P.S. давно статью по dcevm писал, может пригодиться, habr.com/post/236075
В Python отсутствуют простые типы как ValueType (насколько я понял), и даже обычные числа — это полноценные объекты (фактически как boxing в .NET).
Это ерунда. В дотнете значимые и примитивные типы — это не одно и то же. Например, string — примитивный, но ссылочный, а Decimal — значимый, но не примитивный.

Каким образом вы определяли, что обычные числа используются как объекты? Вы смотрели ассемблерный код, генерируемый JIT? Я не знаток питона, но практически уверен, что проблема производительности не в нем, а в том, что ваш генератор выдает неэффективный код.
Например, string — примитивный

Да, ладно!
var isPrimitive = "Hello World!".GetType().IsPrimitive;
Console.WriteLine(isPrimitive);
>>out -> false
С точки зрения CLR тип string вполне себе примитивный: для него есть отдельный опкод, его можно использовать в аргументах атрибутов и в константах. А свойство просто проверяет текущий тип на вхождение в некий список. Если пытаться сформулировать правило, по которому здесь определяется примитивность типа, то оно получается длинным и неуклюжим. Поэтому я подозреваю, что на самом деле причина историческая: так реализовали в первой версии, а потом не стали менять для сохранения обратной совместимости.
Если пытаться сформулировать правило, по которому здесь определяется примитивность типа, то оно получается длинным и неуклюжим

Зачем формулировать правило, которого нет в спецификации языка C#?
Даже Джон Скит, не называет string примитивным типом и полностью доверяет type.Isprimitive

I wouldn't personally call dynamic, decimal, object or string primitive types. I'd use Type.IsPrimitive for the canonical source there.


Источник
stackoverflow.com/a/47589777
Во-первых, в спецификации языка C# определения примитивности и не может быть, потому что это более низкоуровневая вещь, относящаяся ко всему CLR.

Во-вторых, именно отсутствие нормального определения побуждает к попытке сформулировать свое. В ECMA-335 я такого не нашел, всё так или иначе упирается в это самое свойство IsPrimitive, а рекурсивное определение, даже подтвержденное личным мнением Джона Скита, на мой взгляд бесполезно.

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

Какое определение больше нравится — решать вам. Но если вы знаете ситуацию, в котором текущая реализация IsPrimitive имела бы осмысленную практическую пользу — пожалуйста, поделитесь.
в спецификации языка C# определения примитивности и не может быть

Ага, а вот в спецификации VB.NET есть секция 7.3
The primitive types are identified through keywords, which are aliases for predefined types in the System namespace.

Там же, кстати, к примитивным типам относят и Decimal, Date

Для себя я определяю «примитивный» тип как нечто базовое,

Так и писали бы в первоначальном сообщении ИМХО — вопросов бы не было.

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

Haxe (https://haxe.org/), не?
Да, наверное, неточно выразился. Правильнее было бы так:
Вот бы, разрабатывая программу на одном моём любимом языке C#, сразу получать исходники на других распространённых языках программирования Java и Python

Был же вроде проект наоборот, конвертировали Андроид с Явы на Сишарп.

Если нет аналога в Java — то никак не конвертируется. Или использовать исходники пакета, если есть, для конвертации и их в Java. Увы, есть ограничения… Например, связанные с использованием GUI или некоторых Windows-возможностей (какой-нибудь реестр). Но в рамках, скажем, функционала .NET Core этих ограничений будет меньше.
А как именно вы делали конвертацию? Этого в статье не хватает.
Сначала попробовал конвертеры C# в Java из Интернета (парочку), но они выдавали некомпилируемый результат с кучей ошибок. Может, есть какие платные получше, но денег разбираться нет. Писал сам, на это ушло около 3-х месяцев, зато теперь конвертирует то, что нужно, и как нужно сразу рабочий код. Задача была добиться того, чтобы результат вообще не нужно было бы вручную как-либо корректировать. Поскольку такие генерации идут периодически при доработках исходного проекта на C#. А в этом году за месяц доделал конвертер для получения Python. Но это так — экзотика, так как реальных проектов у меня для Python нет.
Да, наверное, неточно выразился в начале статьи. Правильнее было бы так:
Вот бы, разрабатывая программу на одном моём любимом языке C#, сразу получать исходники на других распространённых языках программирования Java и Python

Месье знает толк в извращениях...


Если верно понял, Пайтон был по фану
А не хотите во что-нибудь поэкзотичнее конвертнуть?
Например Go или Rust))

«Штирлиц был извращенец, поэтому во Вращенцах ему был установлен памятник.» Могу и в Go, если там будет не памятник, а хотя бы небольшой бюстик…
«new Class() { присваивания }»

в Java — new Class() {{ присваивания }}
Надо же, не знал! Спасибо, оказывается, так можно — подправлю конвертер.
Это не то же самое. Этот вариант создаёт анонимный класс.
Не стоит править — просядет производительность.
Так делать нельзя. Это уже будет не `Class`, а некий другой, анонимный `Class`.
// Я буду обновлять комментарии перед отправкой своего.
Что тут анонимного, это блок инициализации?

Всё верно, блок инициализации в неком классе-наследнике Class,


(new Class().getClass() != new Class() {{}}.getClass()) == true

Это корректная конструкция, но делать так не рекомендуется.(пока не понимаешь, что творишь и почему этот код может сломать буквально всё)

Интересно, почитать об этом где-нибудь можно
Похвально. Но, есть такая штука как IKVM.NET. Разработка относительно недавно прекратилась, однако, позволяет запускать почти любой JVM байткод на .NET, и при том умеет не только интерпретировать, но и компилировать. Так, кстати говоря, можно из Java в C# перегонять код, при помощи декомпилятора. И даже Interop с Java есть, можно создать jar-обертку для.NET кода и использовать ее при разработке на Java, с одним ограничением — код должен исполняться в IKVM.

Лучше конечно конвертировать на уровне байт кода, а не исходного кода. Я встречал на хабре несколько таких проектов, например CIL2Java, был еще dot42 и множество других.

Тем что можно конвертировать «бинари», например, из nuget…

Интересно, мы в Swiftify занимаемся конвертером Objective-C в Swift, и я могу сказать что это непростая задача.


А какие вы использовали библиотеки для парсинга и обработки C#, Java и Python?

Да, весьма непростая задача. Никакие библиотеки не использовал (попробовал Roslyn, но сразу не взлетело, да и лень было разбираться) — писал свой парсер C# с нуля. А для java и Python парсер был не нужен. Отмечу, что сам по себе парсер в общих трудозатратах занял не так уж много времени — 10-15%, не более.
попробовал Roslyn, но сразу не взлетело, да и лень было разбираться

Извините, но написать свой парсер с нуля намного сложнее чем разобраться в Roslyn. Тем более он предоставляет не только парсер, а еще и семантический анализатор. Как проверяли корректность парсера? Ведь в C# есть препроцессорные директивы.

Кому как, мне приятнее написать самому, чем разбираться. Препроцессорные директивы активно используются — в конвертере можно задавать переменные и потом их проверять в коде, отключая те или иные ветки через препроцессорные директивы. А корректность доказывается тем (как необходимое условие), что результирующий Java\Python функционирует идентично исходному C#.
Как понимаю, исходники закрытые, это коммерческая разработка? :)
Да, жалко так вот бесплатно… К тому же что там такого интересного — в исходниках? Мне сейчас видится, что 100% конвертера сделать в общем случае затруднительно, но на конкретные проекты — вполне. Скажем, я использую только некоторое подмножество .NET (вряд ли больше 70% языка и 10% функций). Если у кого есть схожая задача конвертации, то мог бы взяться за поддержку конвертации этих проектов, небескорыстно, естественно. Судя по сайту, Вы тоже занимаетесь конвертацией. Можем обменяться идеями по скайпу (konstantin.smith), покажу через TeamViewer, как это выглядит у меня.
По поводу Java<->.NET есть такой «диназавр» IKVM.NET. Умеет бинарники в jar и наоборот. Но я так понял вам важно иметь именно исходники.
По поводу internal… У меня в голове прочно сидит такая аналогия:
C# -> сборка — Java -> пакет
internal — package private
Не совсем. Прямого аналога сборки в Java нет, я делал C# namespace — Java-пакет, а internal приходилось делать public.
Only those users with full accounts are able to leave comments. Log in, please.