Pull to refresh

Comments 55

У меня два соображения на этот счет:
1. Если тому человеку видится, как переписать тот легаси код на scala и видится, что это просто — пусть покажет пример простого переписывания какой-нибудь функции по вашему выбору на скала.
2. Со времен написания легаси кода скорее всего много воды утекло, и даже может быть сильно изменились всякие компоненты и модули. Если взглянуть на тот код по крупному, то можно поискать более совершенные фреймворки для того легаси кода, чтобы переписать его с минимальным напрягом? Иногда можно сделать новую структуру и даже лучше старой.
А по крупному — ну ведь работает же? Это самое главное! Так что вы должны настаивать, что имеете права выбора, вам же работать.
UFO just landed and posted this here
Спасибо за статью!
А можете вкратце рассказать, чего вам не хватало в стандартных решениях, почему решили запилить PyMNg?
Пожалуйста… А про собственный «форк» долго рассказывать если честно. Просто тогда pypy сильно сырой был, например у него тогда стабильный только refcounting (вместо реального GC) стоял (при циклических связях — имеем или mem-leak или тупой до ужаса delete на множественных reference). Да много чего было. А в принципе — питон о питон и есть… Думаю если появится когда желание на тот же pypy заменить — меньше чем за неделю обойдется, тестировать только дольше потом…
ну а чего, «моя» сборка как хочу, так и назову… :) сначала был просто PyMod, вторую же версию просто решили NG (next generation) обозвать…
Как ни странно, иногда язык — забота не только разработчика.

Несколько раз уже сталкивался с тем, что инвесторов или партнеров интересует платформа, и к Java относятся намного лучше, чем, например, к .Net
UFO just landed and posted this here
С инвесторами просто, Java одно из самых распространенных энтерпрайз решений, а люди вливающие бабло хотят какой-то надежности.
Такая же ситуация с linux системами в банках, в основном там всякие ред хаты встречаются, потому что они на тех.саппорте, имееются бумажечки(свидетельства и лицензии всякие) и это инвесторам сильно больше по душе, чем какой-нить gentoo.
Никакой магии.
имееются бумажечки(свидетельства и лицензии всякие)

Эти всякие бумажечки для банка чуть не лицензии стоить могут :)
наткнулся на пост, увидел твой коммент, ничего не понял, выглядит как попытка меня поправить, но неясно в чем
Хорошая статья, спасибо!
Вы бы еще опросник добавили, кто какой вариант интерпретатора пользует: cpython, stackless, pypy, etc…
Например, мне было бы интересно посмотреть, стоит ли заморачиваться и подгонять свои open source пакеты под pypy =)
это была очепятка, но я думаю все поняли под этим «CPython», да и cython в действительности superset над ним, поэтому просто поправил…
Всё-таки вы так и не ответили на исходную статью — там всё же приводятся бенчмарки для более-менее одного алгоритма, реализованного в терминах разных языков. Вы же говорите, «эту задачу можно решать лучшим способом, тогда и результат будет лучше!». Но вы не удосужились реализовать ваш другой способ на других языках и провести в таком виде тест, так что ваш результат имеет смысл не в контексте сравнения языков, а в контексте сравнения программистов ;)
А то что оригинальный тест (хоть даже и с «сахаром») рвет на PyPy ту же scala в клочья — это вы видимо пропустили…
Кто-нибудь подскажет, где мне, изучающему python, почитать о том, почему так происходит? Каковы внутренние отличия?
Чтобы уж совсем корректно «сшить» ваш тест с тестами из исходной статьи надо было бы еще добавить исполнение оригинального теста на Python2.7 на вашем железе — оно ведь все таки другое…
Или просто попробовать на scala, что я и сделал кстати (в моем случае только версии 2.10.4) — совпадение практически полное. (Я из второго питона держу только pypy.)
Добавил Scala тест. Никаких оптимизаций не делал, код практически один в один. Сразу скажу, что на максимально эффективных алгоритмах Scala немного проигрывает из-за boxing/unboxing. Оптимизацию делать не стал, т.к. в реальной жизни такого рода оптимизации делают редко. Также siev2 не имеет смысла в Scala, т.к. не существует неявного эффективного преобразования из целочисленного в булевое.

Результаты для "$ script 100000 max 1000":
  • pypy3: max — 21.24 ms, orgm — 35.82 ms, siev1 — 2.13 ms, siev2 — 1.18 ms, osie1 — 1.28 ms, osie2 — 1.23 ms
  • scala: max — 6.81 ms, orgm — 14.40 ms, siev — 1.66 ms, osie1 — 2.43 ms, osie2 — 2.26 ms
  • python3: max — 322.58 ms, orgm — 283.06 ms, siev1 — 26.48 ms, siev2 — 27.89 ms, osie1 — 30.57 ms, osie2 — 28.85 ms
Спасибо, практически ожидаемые результаты. Один вопрос — вы пробовали только несколько итераций? Если одну, но 10M?
Попробовал с 10M. Пришлось выделить больше памяти для Scala (вылетает с OutOfMemory потому что по умолчанию выделяется только 128 Mb или что-то типа того, не хочу врать), так что использовал скрипт как «scala -J-Xmx2g sexy-primes-test.scala 10000000 max»:
  • pypy3: max — 11153.52 ms, orgm — 16668.04 ms, siev1 — 482.62 ms, siev2 — 223.11 ms, osie1 — 208.16 ms, osie2 — 203.30 ms
  • scala: max — 3425.13 ms, orgm — 9491.97 ms, siev — 2149.22 ms, osie1 — 2141.02 ms, osie2 — 1612.79 ms
хм, не то чтобы очень неожиданно, но… какая у вас скала? и что за железо?
MacBook Pro: OS X Yosemite 10.10.3 (14D136), Processor: 2.3 GHz Intel Core i7, Memory: 16 GB 1600 MHz DDR3
PyPy3: Python 3.2.5 [PyPy 2.4.0 with GCC 4.2.1]
Scala: 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40)

Я перезапустил скрипты с большим количеством итераций (100 итераций), чтобы минимизировать разброс:
  • pypy3: max — 10339.21 ms, orgm — 16056.41 ms, siev1 — 430.27 ms, siev2 — 190.77 ms, osie1 — 202.00 ms, osie2 — 201.17 ms
  • scala: max — 3176.92 ms, orgm — 9100.62 ms, siev — 645.46 ms, osie1 — 671.52 ms, osie2 — 602.37 ms


Еще хочу попробовать на своем старом ноуте, есть подозрение, что операционная система может влиять тоже. Отпишусь позже.
У меня i5 2.3GHz (не ноут), pypy тот же, но скала — 2.10.4 (тест пускал на работе, там win7 x64, JVM вроде тоже 1.8)
Т.к. вот «max» на pypy3 = 5.2s, scala = 6.5s. На сите же у скала, все как и у вас в три раза медленнее pypy. Может JVM чем отличаются или на win он чуть хуже. Хотя у меня pypy на «max» в 2-а раза быстрее вашего. Мне просто порядок не понятен.
Протестировал на старом железе (Pentium T4500 @ 2.30GHz, 3Gb RAM). В целом распределение такое же для других операционных систем, но относительные величины немного разные. Из-за ограничений в скорости использовал «script 100000 max 100».

Linux Mint 17.1 (3.13.0-37-generic #64-Ubuntu SMP):
  • PyPy3: max — 49.95 ms, orgm — 92.91 ms, siev1 — 6.41 ms, siev2 — 4.81 ms, osie1 — 5.06 ms, osie2 — 4.75 ms
  • Scala: max — 11.71 ms, orgm — 33.12 ms, siev — 6.87 ms, osie1 — 7.44 ms, osie2 — 6.64 ms


Windows 7 (7601.win7sp1_gdr.140303-2144):
  • PyPy3: max — 35.17 ms, orgm — 119.14 ms, siev1 — 9.36 ms, siev2 — 4.83 ms, osie1 — 5.77 ms, osie2 — 4.85 ms
  • Scala: max — 21.85 ms, orgm — 48.55 ms, siev — 10.74 ms, osie1 — 13.08 ms, osie2 — 10.82 ms


В обоих тестах были использованы ванильные версии: Python 3.2.5 [PyPy 2.4.0], Scala 2.11.6 (Java 1.8.0_45).
Если вы защищаете свою существующую разработку от переписывания, то тут естественно надо учитывать и риски, и целесообразность в условиях того, что уже достигнуто на данный момент.

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

Если кто-то будет выбирать Питон или Скалу для старта проекта — какой смысл брать питон, рассчитанный вроде бы на использование не-системщиками, зная, что для достижения приличной скорости надо залезать в дебри и обладать очень хорошей именно системной и компиляторной экспертизой. Опять же, лишние риски
Вот поэтому, мы и разговариваем на разных языках…

В тестах же (кроме одного) использовал стандартные сборки (да pypy уже давно дефакто стандарт)…
Я говорю не про дурацкие простые числа, а про вашу реальную продакшен-систему. Если со стандартным питоном все хорошо, зачем вам перебирать и затачивать систему исполнения? Если кто-то начинает писать аналогичную систему с нуля, может ли он выбрать Питон рассчитывать, что ему не придется повторять ваш путь?
Автор уже коментировал что-то подобное тут. Если я правильно понял, то раньше они дошли до ситуации, когда стандартного питона им уже не хватало, а переписывать на что-то другое было нецелесообразно, и pypy был перспективный, но сырой, так-что они сделали свой python
Тогда зачем автору в принципе «собственный Jit, MemMgr, GC»?
потому что могу ©
это на самом деле не совсем касается темы статьи…
… А пока вы практиковались в занимательной арифметике чуть менее амбициозный джуниор тихо кивнул на «команду свыше» и молча начал пилить на скалке.
Есть такая тема, что когда отдел большой, то со временем «неудобные» вопросы начинают уходить к тихим сговорчивым лидам.
А потом вдруг оказывается, что люди тихо и сговорчиво написали тормозного монстра, освоили бабло и умыли руки, а заказчик обанкротился, потому что у конкурента всё летает ;)
Хотелось бы добавить несколько ссылок. Автор явно любит свое PyMNg творение, так что никакие бенчмарки не повлияют на его мнение, однако для других это может быть полезно:


Что касается PyPy и то, что он где-то «стандарт де-факто» — здесь надо наверное уточнять область. Лично я вижу, что в основном используется CPython, из-за того, что он 100%-совместим со всеми библиотеками, плюс если надо какую-то часть ускорить, всегда можно написать расширение на C (например с использованием Cython). Python выбирают не из-за скорости, тут даже говорить не о чем, а из-за количества доступных библиотек. И в этом плане использование PyPy рискованно, но опять-таки это зависит от области применения.

И наконец насчет Legacy. Я знаю несколько примеров, когда полностью меняли технологический стек, в основном из-за скорости. Одно из хороший решений — использование ZeroMQ, можно разделить приложение на несколько частей (микро-сервисы) и организовать коммуникации между ними (даже если это простой Request-Reply). После этого любой микро-сервис можно переписать на другой язык программирования и уже имея две версии, делать сравнения и анализ.
Я не поленился скачал pypy3 запустил на нем оригинальный пример поменяв на range: 3,6-4 с, взял С пример и перенес на яву 1.7 1-в-1: 1,7 с. Разумеется, тесты не по кананонам, без прогревов jvm, усреднений и тп. У меня ssd диск и i72600k, а у вас может ява стартанет медленнее, тут слишком много нюансов для таких утверждений.

Еще надо внимательно смотреть, что делаем и зачем. С пример делает принт каждый раз как найдено число, остальные собирают массив и потом один раз делают принт, это все же разные вещи. Сама реализация выделения дополнительной памяти для массива может быть разная, что тогда мы сравниваем? Есть настройки JIT компиляции в jvm, тоже можно покрутить, только что это покажет?
С пример делает принт каждый раз как найдено число, остальные собирают массив и потом один раз делают принт, это все же разные вещи.

В сях наверняка буферизован ввод-вывод.
Он везде буферизован, но дело не в этом — просто «положить результат в лукошко» или таки запустить целую функцию, которая делает явно больше, чем собирает результат (например, конвертация числа в строку, что для больших чисел уже «длинная» операция, и положить уже этот распухший результат в буфер).
Попробовал тоже самое на PureBasic (его компилятор вообще не умеет оптимизировать) ~ 4 сек. Не хуже, чем pypy3. Чтобы добавить комизма ситуации, я написал тоже самое на ActionScript3, без ввода вывода его время 3,8 сек.
А яваскрипт показал 2 сек легко печатая в консоль файрбага) Это без всяких asm.js.
Похоже это просто пиар своей платформы. Впрочем не вижу в этом ничего плохого. ))
Странный способ убеждать продажника. Обычно им достаточно на бумажке подсчитать сколько времени займёт набор новой команды и переписывание. И пояснить, что развитие проекта на это время придётся полностью остановить…
Ага. Как вы тролли достали — ведь даже на хабре…
Тролли? А что вас так заусило?
Оптимизация за счет использования более специфических, не библиотечных алгоритмов, оптимизированнных под конкретную реализацию языка, это новость разве что для новичков…
Опять же не вижу в этом ничего плохого. Кто-то новичкам должен рассказать про разницу между использованием библиотечных функций и самописных, оптимизированных под конкретную задачу и конкретный транслятор…
Но опять же, чтобы новичкам например знать о «туповатой реализации bool в pypy» надо наверное написать свою реализацию python'a.
И? Какова мораль? Для новичков мораль конкретная: учите asm (дабы понимать разницу между туповатой реализацией и «нетуповатой») и учите классические алгоритмы.
А для не новичков?
По пунктам:
1. Пиар чего? (где скачать, где ссылка, где я вообще работаю?)
2. Я убеждал нач-проекта и немного продажника (по совместительству)… И это все что вы из статьи вынесли?
3. По поводу вашего последнего же коммента я лучше промолчу. Хотя нет — учите asm.
sebres, спасибо за статью, c performance все более менее понятно. А вы не думали, что есть другие плюсы Scala по сравнению с Python? Например, статическая типизация. Какой размер вашей кодовой базы? (количество функций, количество классов, модули) Если расширяемость вашей кодовой базы (в смысле добавления новых функций пользовательского уровня) примерно происходит в виде «написал(три) одну новую фунцию на Питоне, которая ни от чего особо не зависит», то может быть, разницы вы не почувствуете. Но если приходится менять структуры классов, проводить рефакторинги, да и вообще, понимать, где в программе какие данные, где начала и где концы, образно говоря, верифицировать код до его запуска, то поддерживать такие программы на языках типа Python — есть не очень приятное занятие, ИМХО, если не назвать это оверхэдом.
кому статическая типизация плюс, кому минус…
поддерживать такие программы на языках типа Python — есть не очень приятное занятие, ИМХО, если не назвать это оверхэдом.
Ни разу не чувствовал дискомфорт, даже на тикле, у которого с типизацией еще «хуже».
Прошу прощения, но у вас постоянно этот «тикл». Это Tcl что ли?
А что такого?

Классная штука, очень обидно, что он незаслуженно забыт.
Пример на scala — без прогрева, как минимум. Значит результат можно отправлять в помойку. На JVM JIT начинает оптимизировать методы, если количество вызовов конкретного метода превышает некоторый порог (на JVM в server mode это порядко 10к, если не ошибаюсь). Если это происходит во время «бенчмарка» — результат оказывается хуже, т. к. измерялось ещё и время компиляции и замены метода.

Если метод ещё не успел скомпилироваться — то измерялось время работы кода в интерпретируемом режиме (и для сравнения стоит выкинуть из остальных JIT вообще).
Подправил тут кое-что для сито-вариантов (см. commit): а именно деление сразу целочисленное без cast-а в int и итератор в sexy_primes_below сразу только по нечетным (9, 11, 13...) т.е. с шагом 2.

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

Чисто для контраста процитирую пост(*) недельной давности:

>… мы много занимаемся машинным обучением на очень больших массивах данных. Раньше для разработки прототипов мы использовали связку IPython + Pyhs2 (hive драйвер для Python) + Pandas + Sklearn. В конце лета 2014 года приняли принципиальное решение перейти на Spark, так как эксперименты показали, что мы получим 3-4 кратное повышение производительности на том же парке серверов.

Есть конкретная задача из жизни. Есть мотивация улучшить проект. Люди рассматривали разные варианты, анализировали плюсы/минусы. В итоге:

> Мы решили выбрать Scala, так как именно на нем написан Spark, то есть можно анализировать его исходный код и при необходимости исправлять ошибки, плюс — это JVM, на котором крутится весь Hadoop.

*Ссылка на полную версию: habrahabr.ru/company/retailrocket/blog/258543
#return ((n & 1) and all(n % i for i in range(3, int(math.sqrt(n))+1, 2)))


Тут все проще, resolve операции (.) просто будут потихоньку притормаживать, рекомендуется просто обрезать по возможности, например до sqrt(n).
C pypy реализацией не знаком, но как минимум для cpython это справедливо.
Sign up to leave a comment.

Articles