Pull to refresh

Comments 133

Автор, ты заговорил — и достучался до моего сердца!
В этом тесте фактически сравнивается реализация регулярных выражений в V8 и других библиотек.
Причём, скорее всего, на тех же С/С++.
Да понятно что сравнение компилируемого языка с интерпретируемым — из области троллинга. В конце концов, сайт называется Benchmarks Game. Вы лучше посмотрите на сравнения JS с PHP, Python, Ruby, Lua и т.д.
UFO just landed and posted this here
Потому что на нем легко посмотреть и его легко запустить (конечному пользователю). Никто не станет скачивать ToDo приложение, зато в вебе его удобно запустить и посмотреть. И пользоваться тоже удобнее, нежели ставить такое себе на комп.

Стокгольмский синдром.

Не думаю, что все его прямо-таки любят. Просто выбора-то нет. Для меня другое странно — почему так долго значимые игроки сосредотачивают усилия на нем, вместо того-что бы уже давно во всю работать над универсальной машиной для исполнения кода скомпилированного из любого, удобного для разработчика, языка…
Да я в курсе, но как по мне, то уж слишком долгий этот процесс у них.
У гугла много что не взлетело и много что приземлилось, и делать это надо, конечно, не одной компании. И не нативный код, а байт-код для кроссплатформенности. В общем это немного не то.
Я подозреваю, что это синдром утёнка. Для огромного числа разработчиков JS — это их первый язык. А первый — значит лучший.
Вот откуда берется стремление все писать на JS — вот загадка. Ну, то есть понятно, откуда, учить другие языки лень. Но все же.
А вы сами как с JS?
Просто такое ощущение, что это как раз вам как следует разобраться во вселенной JS/CoffeeScript/TypeScript лень)

JS — на данный момент один из самых востребованных языков. Хорошие разработчики JS получают в среднем больше, чем плюсеры, например. Не думаю, что весь мир сошёл с ума, а вы один умный. Это маловероятно.
А я разве сказал, что JS — плохой язык? :) На мой взгляд JS примерно настолько же плох, насколько плох С. А С++ уже давно за гранью добра и зла.

Впрочем, взгляд мой не слишком обоснован, ибо, как вы справедливо отметили, мне действительно лень в его вселенной разбираться.
Никто не умный и никто не сошёл с ума. Обычные колебания рынка, пройдёт несколько лет — и на смену тому, что есть придёт что-то ещё. А в некоторых областях типа эмбеда и вовсе ничего не поменяется.
UFO just landed and posted this here
>> Ну, то есть понятно, откуда, учить другие языки лень.
Как и разработчикам из других языков (которые тоже у них когда-то были первыми) очень лень учить JS, поэтому они страдают от детских болячек при работе с JS и клянут все на свете за callback-hell и асинхронность.

В JS такое же программирование, как и в любом другом языке. Если перестать к нему относиться как к языку, на котором всплывающие окошки делаются, а постараться применять общепринятые в разработке подходы и паттерны, то ничего в нем страшного и неудобного нет. По крайней мере не больше, чем в любом другом языке.
Согласен с Вами. Столько всего пишут на JS, зачастую героически преодолевая трудности (вроде того же ООП и контекстов), при этом зачастую на JS пишут даже то, что на нем писать не стоит — десктоп, мобильные приложения. В шутку жду, когда напишут ОС на JS.
А еще можно упомянуть интересный проект: NodeOS (linux kernel + node.js runtime + npm Packages)

Как понять что мобильное приложение написано на js? оно запускается секунд 10 и тормозит. Серьезно, все эти Slack, gitter и еще десяток js мобильных приложений наводят на меня тоску. Хорошо фейсбук вовремя соскочил с жс и перешел на натив.

оно запускается секунд 10 и тормозит.

В статье как раз объяснили, что проблема не в js.
Я наблюдаю что обычно для мобильного «веб» приложения используют css фреймворки и куча html — тысячи элементов DOM. Если в нативном приложении выводить тысячи виджетов то оно тоже будет тормозить.
И наоборот, сделайте веб-приложение с «10-дивами» и оптимальным кодом — оно будет быстрое.

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

UFO just landed and posted this here

Ну так а в архитектуре проблемы из-за проблем в головах :-)

Да какая мне разница что там тормозит, для меня как обывателя каждое js based приложение продолжает доказывать что тормоза — они там где рядом есть JS.

Последний айфон, железо гипермощное, а я вынужден пялиться 10 (десять, Карл!) секунд в белый экран чтобы открылся gitter.

Хотите я сделаю еще большие тормоза на любом другом языке?

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

Я вообще не занимаюсь мобильными приложениями. Но вы почему-то делаете вывод, что то, что у многих пишущих на данном языке руки растут не оттуда — существенный недостаток языка.
Удалил нативное приложение ФБ, хожу через браузер. Тормоза на ровном месте, сожранная батарейка, баги, глюки — все это в прошлом. Просто криворукость и требования отдела маркетинга с языком не связаны никак.
Что-то я не уверен, что фейсбуку это помогло.
На iOS — 18 тысяч классов, порядка сотни мегабайт, FBEventUpdateNotificationSubscriptionLevelMutationOptimisticPayloadFactoryProtocol-Protocol.h.
На Android — жуёт аккумулятор жутко, воплей полный интернет.

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

Какая связь между кол-вом классов и скоростью работы? меня на iOS вполне устраивает нативный клиент по сравнению с жс.

Нет никаких трудностей с ООП.
CoffeeScript и TypeScript давно всё решили.

Клиент-сайд для мобилок и десктопов на js — вообще отличная вещь, если что.
То, с чем копаются обычно xaml-щики/шарписты и прочие гораздо легче и красивее делается на js/html5/css3

JS обычно начинают хейтить после знакомства со своим вторым языком =)
А потом, при углублении оказывается что новый x-lang не так уж и удобен, а JS не так уж и плох, когда знаешь как его готовить.

Упс… У меня JS далеко не первый язык. Его ещё в проекте не было, когда я начал интересоваться программированием.

Но не сказать бы что я его любил… До появления promises, lodash-underscore и Typescript (классы более человеческие и не надо постоянно писать «длинные» return & function). Просто сейчас JS, особенно с сахаристыми надстройками, очень удобен для функционального программирования и отложенной обработки. Просто не знаю, что есть лучше, читаемее и лаконичнее в этом плане. Возможно Ruby, но у JS ещё и быстродействие)

Экстаполяция Вашего собственного опыта никак не опровергает и не подтверждает мой полушуточный тезиз. Поэтому я не совсем понял Ваш "упс" =) И да, JS с сахаром вполне удобен для довольно широкого спектра задач, и где-то даже совсем безальтернативен.

Альтернатив в браузерах нет. Поэтому всем full-stack и front-end разработчикам в вебе приходится писать на нем. А веб — это огромная доля рынка и, соответственно, огромное число разработчиков. Благодаря вебу, программистов, пишущих на JavaScript больше, чем программистов, пишущих на каком-нибудь другом языке, отсюда и популярность.
При разработке сайта fullstack разработчиками, проще писать на одном языке, чем переключаться между ними, поэтому javascript появился еще и на бекенде. А потом дошла очередь и до мобильных с десктопом.
Были бы альтернативы и тогда JS не был бы настолько популярным. Например, на движке Unity3D можно разрабатывать на JS и на С#. К тому же, первоначально документация и примеры были в основном на JS. Спустя несколько лет C# вырвался в лидеры с огромным отрывом.
Мне самому нравиться C# и Pascal/Delphi, но пишу на JS, т.к. работаю front-end разработчиком.
Нет в Unity3D JS и никогда не было. В лучшем случае это местами похоже на TypeScript/AS, но стандартная библиотека EcmaScript отсутствует.
Да я бы не сказал что прям уж любят — приходится мирится (а что делать?). Понятно что уже от этого языка нам ну никуда вот совсем не деться — даже через какие нибудь лет 50, может быть когда уже и Java и C# и PHP и Ruby будут вымирать (или уже вымрут), в Сети еще будет много всякого вялятся, написаного на JS. Другое дело — кто поопытней, понял что есть возможность не парится и писать на ClojureScript, ELM и PureScript. И это гораздо, гораздо, гораздо более приятней (хотя и не без проволочек). А вот тем, кому в опен-сорсе библиотеки писать приходится, то тут уж как ни крути — JS он и на битбакете common как говорится denominator.
Главный вопрос, почему все так сильно любят JavaScript?

Не JS, а веб. Полагаю, это дань моде — делать приложения для веб, даже если они ужасны.

Ведь в нём так много неудобных вещей… и чтобы писать что-то серьезное уже нужен какой-нибудь TypeScript с классами и типами...

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

На самом деле JS прекрасен своей простотой и лаконичностью, не зря JSON-нотация вышла за пределы самого языка. Да, у нас нет классов, у нас есть только эти непонятные прототипы, но у нас есть объекты — и ничего, кроме объектов. Нам не нужно писать целый класс только для того, чтобы написать hello-world (как это заставляет делать Java), у нас и числа, и функции — всё является объектом, и мы можем писать в функциональном стиле. У нас нет различия между объектом и массивом (привет, Java, с твоими arr[i] и list.get(i)), у нас нет различий между массивом и картой (PHP, это я тебе шлю привет с твоим «this function preserves keys»), у нас даже обыкновенные числа — это объекты (Java, спасибо за примитивы и боксинг\анбоксинг для коллекций примитивов). Наконец, у нас есть возможность модифицировать объекты на лету и нам не надо генерировать 100500 классов на каждый чих. У нас нет указателей и арифметики указателей (Си, слышишь?) и сегфолтов.

Просто не надо использовать язык для того, для чего он не был изначально предназначен, не нужно нам жирных клиентов ООП, фреймворками, MVC и «многопоточностью». Это скриптовый язык. Или давайте еще bash ругать, что на нем нельзя писать большие и сложные приложения.
Нам не нужно писать целый класс только для того, чтобы написать hello-world (как это заставляет делать Java)
Точно так же про JS можно было бы сказать, что для запуска программы на нем нужно сделать html-страничку с тегом <script> и открыть ее в браузере, или npm-модуль. В данном случае, класс в Java — это не архитектурный оверинжиниринг, а способ разделить код на модули. В некотором смысле это даже проще, чем в JS — нет разделения на «глобальную» и «локальную» области видимости, весь код в методах, а все методы в классах.

У нас нет различия между объектом и массивом (привет, Java, с твоими arr[i] и list.get(i)), у нас нет различий между массивом и картой
Основное преимущество массива как структуры данных — это быстрый доступ к произвольным элементам и компактное расположение в памяти. Если эмулировать массив с помощью таблицы с числовыми ключами, как это сделано в JS или PHP, то оба преимущества теряются. Как только нужно обработать существенные объемы данных, кажущаяся простота выстреливает в спину и приходится изворачиваться с помощью костылей. Например, в JS на самом деле не один тип массива, а один объектомассив и еще девять отдельных типов массивов. В этом свете система типов Java выглядит куда более лаконично.

В цивилизованных языках типа Scala / Kotlin / C#, кстати говоря, есть перегрузка операторов индексации, которая решает проблему.

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

Деление на модули там, где модули не требуются — это и есть оверинжиниринг в чистом виде. :) Отсутствие функций вне классов — это глупость, которой нет оправдания.


Например, в JS на самом деле не один тип массива, а один объектомассив и еще девять отдельных типов массивов.

В джаве с типами тоже не очень сладко: имется зоопарк Stream, IntStream, LongStream, DoubleStream… про зоопарк функциональных интерфейсов вообще молчу. В шарпе получше, но числовые типы всё равно существуют отдельно друг от друга, что печаль. Так что красивые системы типов начинаются где-то в районе функциональных языков. Вся мультипарадигма и мейнстрим обрастают кошмарными костылями.

Отсутствие функций вне классов — это глупость, которой нет оправдания.
Наоборот, если Java изначально создавалась как объектно-ориентированный язык для энтерпрайза, вводить сущности для описания редкой на тот момент функциональной парадигмы было бы нецелесообразно. За двадцать лет ожидания выросли, и теперь поддержка ФП считается необходимым минимумом. А еще через 10 лет будем удивляться, как мы писали без зависимых типов и автоматической системы доказательств теорем.

В джаве с типами тоже не очень сладко: имется зоопарк Stream, IntStream, LongStream, DoubleStream…
Это случаем не из-за type erasure такое происходит?

В шарпе получше, но числовые типы всё равно существуют отдельно друг от друга, что печаль.
Можно чуть поподробнее? Вы о том, что примитивные числовые типы приводятся друг к другу отдельными командами, и `Decimal` не является встроенным, или что-то другое?
А еще через 10 лет будем удивляться, как мы писали без зависимых типов и автоматической системы доказательств теорем.

Вы оптимист. :)


Это случаем не из-за type erasure такое происходит?

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


Вы о том, что примитивные числовые типы приводятся друг к другу отдельными командами, и Decimal не является встроенным, или что-то другое?

Я про невозможность написать T Sum<T> (T a, T b) where T : Number => a + b.

Я про невозможность написать T Sum<T> (T a, T b) where T: Number => a + b.
Это и правда было бы очень удобно. Даже проблем на первый взгляд не видно, но всю картину портит тип Decimal, который выглядит как встроенный, но с точки зрения CLR обрабатывается совершенно по-другому.

Так что пока придется вместо T в вашем примере писать dynamic :)
В некотором смысле это даже проще, чем в JS — нет разделения на «глобальную» и «локальную» области видимости, весь код в методах, а все методы в классах.

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

Если эмулировать массив с помощью таблицы с числовыми ключами, как это сделано в JS или PHP, то оба преимущества теряются.

Конечно, за архитектурный подход приходится платить, так же, как платим, работая с примитивами, которые объекты, или строками-объектами — вместо того, чтобы работать с самими данными и их последовательностями (я имею ввиду, что строки не являются просто массивами символов). А именно, проигрываем в скорости и по памяти, по сравнению с C\C++, например.

В цивилизованных языках типа Scala / Kotlin / C#, кстати говоря, есть перегрузка операторов индексации, которая решает проблему.

Каким образом? По-моему, перегрузка операторов не решает проблему сравнительно сложного внутреннего представления.

Но, на самом деле, нам это и не нужно. Например, мы теоретически можем написать (серверное) веб-приложение на C или даже Ассемблере, используя старый добрый CGI — но зачем, когда есть более простые Java\PHP\ASP.NET\Python (даже старый добрый Perl, в конце концов).
Что касается JS — мы имеем простой и очень лаконичный язык, с минимумом исключений из правил (имея ввиду сам язык и его парсер), сравнимый по простоте с Lua. Костыли и другие ухищрения появляются, как только мы хотим сделать из него универсальный язык, таща из него сахар и привычные приблуды из других языков, а также столь милое сердцу тру-ООП. При этом забывая, что это не Java, не C++ и даже не C#.

Проблема в том, что пропагандисты прототипов и противники классов в жабоскрипте не отвечают на простой вопрос: "А как жить-то?"


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


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


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

Все дело в том, что мы привыкли мыслить классами. Но это совсем не значит, что мы должны пытаться их всеми силами эмулировать. В общем случае, прототипы не нужны, у нас есть объекты. На JS можно писать красивый код, но для этого нам нужно забыть про ООП и вспомнить либо ОП, либо ФП.
Просто в JS мы не видим эту всю «обвязку», которая в Java пугает новичков.
Мне очень нравится, как эта проблема решена в LinqPad. Вообще, в C# тоже весь код размещается в методах и классах, как в Java. Но можно выбрать один из трех режимов — «выражение», «блок кода» или «программа». В первых двух случаях пользователь просто вводит код, а уже среда подставляет его внутрь тела метода Main и выполняет. Язык же от этого особыми правилами не усложняется.

Конечно, за архитектурный подход приходится платить
Это плата не за архитектурный подход, а за золотую пулю. Синтаксически разница между {} и [] все-таки есть и логически они используются для разных вещей, но под капотом они реализованы с помощью одного примитива и одно можно превратить в другое. Особенно иронично, что при этом arguments не является полноценным массивом.

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

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

Костыли и другие ухищрения появляются, как только мы хотим сделать из него универсальный язык, таща из него сахар и привычные приблуды из других языков
Я признаю, что JS по-своему красив, некоторые вещи в нем сделаны достаточно элегантно. Но если нужно строить небоскреб, а у вас в руках только розовый пластмассовый совочек, то будь он хоть самым прекрасным совочком в мире, вы знатно намучаетесь. Даже если в результате всё получится, это будет ваша личная заслуга и героизм, проявленный вопреки всем козням инструментария.

Лучше всего с задачей превращения JS в приспособленный для разработки крупных проектов язык, на мой взгляд, справляется TypeScript. С одной стороны, большая часть заведомо абсурдных ситуаций отсекается на этапе компиляции, а с другой — он выглядит наиболее «родным», практически не вмешиваясь в существующую экосистему.
Это плата не за архитектурный подход, а за золотую пулю.Синтаксически разница между {} и [] все-таки есть и логически они используются для разных вещей, но под капотом они реализованы с помощью одного примитива и одно можно превратить в другое.

Всё принесено в жертву мантре «всё является объектом».
Я имел в виду проблему, что похожие вещи синтаксически описываются по-разному.

Эта проблема особенно досадна в Java…
Но если также рассматривать семантику, систему приведения типов и стандартную библиотеку, в JS фантастически много неожиданных поворотов.

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

В том-то и дело, что не стоило бы на скриптовом языке растить «небоскрёбы», что мы и наблюдаем сейчас. Особенно в этом выигрышно смотрятся такие строгие языки, как Java или C#, предлагая компромисс между простотой языка и его мощью, ухитряясь прятать костыли так, что не нужно по ним ходить каждый день, достаточно на первых порах набить шишек и жить спокойно.
Лучше всего с задачей превращения JS в приспособленный для разработки крупных проектов язык, на мой взгляд, справляется TypeScript.

Да, но, к сожалению, его всё равно необходимо превращать в JS вместе со всеми вытекающими.
И еще,
В цивилизованных языках типа Scala / Kotlin / C#

Достаточно холиварное утверждение. Особенно, если вспомнить, что и Scala и Kotlin нацелены на ту же JVM, и там предстают во всей красе все сложности реализации, что хорошо заметно, например, если декомпилировать сгенеренный ими байт-код в Java-код и попытаться сравнить с аналогичным Java-кодом.

А еще вспомним такие языки, как Python и Ruby — они не менее прекрасны, однако тот же Ruby (насчет Python я не в курсе) — не самый быстрый.
Ruby уже давно не такой медленный, как это было во времена 1.8. Начиная с 1.9, и особенно с 2.х основной интерпретатор Ruby в целом быстрее Python, Perl и PHP5. Язык существенно ускорился, а мифы всё тянутся за ним.
UFO just landed and posted this here
UFO just landed and posted this here
по алгоритму regexdna JavaScipt отрабатывает чуть быстрее, чем C++

В C++ версии используется re2 с lookbehind, atomic groups, possessive quantifiers, а в V8 это встроенная имплементация с довольно урезаным функционалом?

lookbehind, atomic groups, possessive quantifiers


Ни одна из этих фич в regex dna не используется.

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


Имплементация V8 — это полноценная имплементация JS RegExp. JavaScriptовые регулярные выражения действительно не поддерживают разные фичи, которые поддерживает re2, но обратное тоже верно — например: JS поддерживает zero-width positive lookahead (?=...) и backreferences \n, а re2 — нет.
Ни одна из этих фич в regex dna не используется.

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


backreferences \n,

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


А вот что вы имеете в виду под zero-width positive lookahead? Ведь любые lookahead и lookbehind это zero-width match?

Но ведь именно из-за поддержки этих фич, иначе устроен процессинг


Отнюдь. Различия между re2 и irregexp действительно фундаментальные — но они отнюдь не из-за поддержки этих фич.

Вот, например, lookbehind в irregexp сделали недавно и никакой особой заморочки с этим не было.

Для простых регекспов из этого бенчмарка основное преимущество V8 состоит в том, что irregexp транслирует регулярные выражения в машинный код, а не исполняет их на «интерпретаторе», как многие другие regexp движки.

Ну тут должно быть просто


На самом деле нет. Вот что на это отвечает Russ Cox (автор re2)

The lack of generalized assertions, like the lack of backreferences,
is not a statement on our part about regular expression style. It is
a consequence of not knowing how to implement them efficiently. If
you can implement them while preserving the guarantees made by the
current package regexp, namely that it makes a single scan over the
input and runs in O(n) time, then I would be happy to review and
approve that CL. However, I have pondered how to do this for five
years, off and on, and gotten nowhere.


https://groups.google.com/d/msg/golang-nuts/7qgSDWPIh_E/OHTAm4wRZL0J

Иными словами в re2 выбраны и реализованы только те фичи, которые можно эффективно исполнять гарантируя линейную сложность, без катастрофического отката

А вот что вы имеете в виду под zero-width positive lookahead? Ведь любые lookahead и lookbehind это zero-width match?


Они так просто часто называются.

Кстати, lookbehind (?<=re) re2 тоже не поддерживает, если верить документации :)

Ёмаё, стыдно то как, а ведь на самом деле в pe2 не всё поддерживается. Беглым взглядом я пропустил, что это альтернатива к движкам с backtracking механизмом. Отсюда и сложность с внедрением backreference. Жаль старые комментарии редактировать нельзя на хабре.
Было также интересно почитать про irregexp. Lookbehind сделан на базе read_backward, действительно просто и удивляет почему раньше это не было сделано.

Возможно в V8 регулярное выражение компилируется прямо в машинный код, благо движок JIT рядом. А C++ re2 так не может и, по сути, тут уже он оказывается интерпретируемым.

RE2 не может, потому что не сделали. Есть PCRE-JIT, rejit и ReJit — у всех есть компиляция на лету.
А как так получается, что TS, который просто транслируется в JS, настолько медленнее JS? Только из-за проверок корректности входных параметров? И всё?

Звучит очень неправдаподобно. Есть ссылочка на тест?

Дык я про картинку в посте.
В TS проверка типов происходит на этапе компиляции.
TS не медленнее JS потомучто он делает проверки соответсвия типов на момент компиляции, не на момент исполнения. в рантайме там обычный джаваскрипт, без всяких проверок
Замечательно. Ваш вариант объяснения картинки из поста?
Алгоритмы там идентично реализованы?
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here

Именно это и сгенерирует TSC:


for (var _i = 0, ii_1 = ii; _i < ii_1.length; _i++) {
    var i = ii_1[_i];
    console.log(i);
}
UFO just landed and posted this here
Почему умолчали о том что самым быстрым по этому тесту является PHP?
Или что тест просто считает много регекспов?
Бред, общим. JavaScript тормознутый, посмотрите на тесты где тестируется что-либо кроме прямых биндингов на C код, типа регулярных выражений. Особенно советую смотреть не только на скорость выполнения а и на память.
И, как говорится, а что плохого в том, что язык, выполняя конструкцию в n раз быстрее, больше утилизирует процессор (вот если бы медленнее, то тогда были бы вопросы).
посмотрите на тесты где тестируется что-либо кроме прямых биндингов на C код

Покажите, посмотрим.

Реализация PHP слишком хитрая — там читерство с потоками и она запутаннее, чем js. Найдётся умелец, который перепаяет js на потоки и расстановка сил снова изменится. А вообще в тесте соревнуются в скорости pcre-движков, только и всего, и учитывая что многие используют libpcre — разница Python, PHP и C++ должна быть минимальна. Аналогично, там есть тест с числом пи, где по сути сравнивают производительность очень оптимизированной библиотеки gmp саму с собой, которая написана, к слову, на Си и ассемблере.


Но делать такие далеко идущие выводы на основе самого сомнительного бенчмарка (там ключевое слово — game)...


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

JavaScript работает быстрее языка, на котором он написан :) Или я что-то путаю?
Он и не так умеет. Можно написать на js код который будет быстрее нативно-впиленного в js движок, на хабре мелькала эта тема. )
Если вы про Promise, то дело в том, что реализация Promise в v8 сильно неоптимальна.
Про это все знают, но оптимизациями новых фич в v8 планируют заняться несколько позже, емнип.
да не, там про перебирающие методы было, кажись про lodash. Жаль поиск по комментам не работает, это в обсуждении было к какой то статье.
Спасибо тебе, добрый человек, именно про это я и говорил. Странно что с lodash перепутал.
Хм. Надо посмотреть, но я подозреваю, что там в большинстве случаев сэкономлено на каких-то проверках.
Вот, наугад открыл — https://github.com/codemix/fast.js/blob/master/array/fill.js.
Он явно не проверяет отрицательные значения на входе (которые должны считать с конца), не конвертирует аргументы в числа.
Кстати, я не уверен что он до сих пор быстрее на свежем v8 =). Проверять надо.
Так и есть, там не учитываются всякие edge-case'ы типа разреженных массивов и тому подобного.
Это вполне возможно. Современные умные JIT (а в V8 именно JIT), умеют генерировать на лету более оптимальный машинный код, чем компиляторы.

Ага, JIT-компилятор умеет генерить более оптимальный код чем компилятор..

JIT compilation is a form of dynamic compilation, and allows adaptive optimization such as dynamic recompilation – thus in theory JIT compilation can yield faster execution than static compilation.

Just-in-time compilation

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

Этого не может быть хотя бы по причинам того, что к JIT-компилятору весьма высокие требования по скорости его собственной работы, что не позволяет в них делать тяжелые и сложные оптимизации, а простой компилятор никак в алгоритмах оптимизации не стеснен.
На счёт превосходсва в скорости — это не однозначно, специфика языков со сборкой мусора затрудняет такое тестирование, потому что цикл сборки, обычно выносится за скобки, можно, вызвать GC.collect(), но, во многих реализациях это рекомендательный метод.
Кроме того, в среднем, языки со сборщиком, выделяют/освобождают память быстрее, чем языки с ручным управлением памятью (за это приходится платить предсказуемостью загрузки ЦП в данный, конкретный момент).

По моему впечатлению, часто работает правило: «быдлокод на JavaScript быстрее быдлокода на C/C++», это не столько минус C++ сколько закономерное следствие его дизайна, который, во многих случаях, как раз хорош.
По поводу webassembly — если не использовать DOM, то он реально быстрее.
Например, если сравнить девелоперский build Unity игры на webgl (он на чистом яваскрипте) с production build (а он — на asm.js), то у второго FPS на 15-20% выше.
Да вообще-то оба билда на asmjs так как emscripten в js компилироваться не умеет. А разница просто в скорости сборки и уровне оптимизаций.
Вы не правы. AOT компилятор включается только при наличии в скрипте директивы "use asm"
Так вот в девелоперском билде такой директивы нет (специально перепроверил сейчас)
И, хотя код тот же самый, но в девелоперском билде он исполняется интерпретатором js, а в production — прогоняется через AOT компилятор.
Давайте называть вещи своими именами. WebAsembly — это на данный момент бинарное представление asmjs. Asmjs — подмножество js. Даже при выключенной AOT компиляции данный код не перестает оптимизироваться лучше так как содержит только арифметику и работу с кучей и не содержит объектов и собственно не перестает быть asmjs кодом.

На счет директивы — вы думаете ее специально отключают? С какой целью? Это ведь одна строчка в коде выставляемая emscripten которая вряд-ли экономит время сборки. Сейчас тоже проверю на чем-то простеньком.
Всё так. Но даже при том, что код, действительно оптимизирован в обоих случаях, AOT даёт ощутимую прибавку по сравнению с интерпретатором.
Что касается отключения AOT в девелоперском билде, полагаю, это сделано с целью облегчения отладки в браузерном дебагере. Хотя точно не знаю зачем.
В js в браузере нет интерпретатора, есть разные виды компиляторов. Наличие директивы «use asm» никак не влияет на отладку. При открытом отладчике FF иногда отключает AOT компиляцию, но на отладку это не влияет. Я проверил ради интереса — в обоих случаях работает AOT компиляция, так что все осмыслено и директива остается на месте.
>В js в браузере нет интерпретатора, есть разные виды компиляторов.
JIT, конечно есть. Тут я был неточен. Но я хотел сравнить js без AOT и webassembly (где AOT есть всегда).

>Наличие директивы «use asm» никак не влияет на отладку. При открытом отладчике FF иногда отключает AOT компиляцию, но на отладку это не влияет
Возможно, это было просто предположение.

>Я проверил ради интереса — в обоих случаях работает AOT компиляция, так что все осмыслено и директива остается на месте.

А директива «use asm» у вас тоже есть в коде в обоих случаях? В моих девелоперских билдах её нет.
Если она у вас есть, то, видимо, мы используем разные настройки девелоперских билдов.
Если её у вас нет, то как именно вы определили, что AOT работает в обоих случаях?
FF пишет о том, что asmjs код скомпилирован за такое-то время, этого достаточно чтобы понять, что директива где-то есть и не искать ее в дебрях скомпилированного кода. Я думаю, что вы скорее ее где-то потеряли так как ее принудительное отключение попросту не имеет смысла.

Публичные версии юнити пока не умеют компилировать в WebAssambly (есть демо angry bots, но оно сделано внутри компании).
Да, вы правы. В обоих случаях срабатывает AOT и мое сравнение некорректно, а разница в скорости связана с оптимизацией кода.
Я ошибочно связал два факта — существенную разницу в скорости и наличие директивы use asm в production билде при её отсутствии (ну нет её там!) в девелоперском.
FF, действительно влючает AOT несмотря на отсутствие директивы. Интересно, кстати, почему.

>Публичные версии юнити пока не умеют компилировать в WebAssambly

Да, но для целей сравнения скорости достаточно сравнить asm.js и обычный js. Потому что на даный момент WebAssembly — просто бинарное представление asm.js и работает оно ровно с той же скоростью. Разница лишь во времени на скачивание, разархивирование и парсинг. Всё это происходит при инициализации. А дальше скорость одинакова.
И директива есть в файле Development/<%= Build Name %>.js:
...
// EMSCRIPTEN_START_ASM
var asm = (function(global, env, buffer) {
  'use asm';
...
И здесь вы правы. Почему-то в production оно ''use asm'', а в developers — 'use asm'
Именно поэтому я и не нашел её. Искал с двойными кавычками.
Видимо uglify его так переделывает.
WebAssembly от asm.js скоростью _работы_ отличаться не должен — они изоморфны, это два способа записи одного и того же.
Скоростью загрузки и разбора — вполне.
От чистого яваскрипта они оба по скорости работы должны отличаться одинаково.
Я про то и говорю. Я сравнил asm.js (который по скорости работы равен Webassembly) и обычный интерпретатор javascript (который исполнят в Unity девелоперские сборки)
Очередной автор не отвечающий на собой же заданный вопрос…
А кому вообще в случае с webassembly тот DOM нужен будет? На нём будут запускать игрушки (полноэкранные), всякую математику и криптографию (там вообще интерфейс пофигу), эмулировать нативную графику мобильных платформ (опять же, никакого DOM).
За заголовок автору респект. В эпоху засилья зануд и эгоцентриков на хабре — нормально так, освежает.
Почему JavaScript работает быстрее, чем С++?

Очевидно потому что авторы конкурирующего кода на С++ умеют писать на плюсах хуже, чем авторы V8 (или какой движок JS там использовался).
Интересно было бы прогнать Parser-3 по тем же бенчмаркам. Мне кажется, он не далеко отстал бы от JS.
Весь пост — непрерывный лютейший ад от начала и до конца. Я даже не знаю, смеяться или плакать.

Давайте начнем с того, что язык не может быть медленным или быстрым. Медленным или быстрым может быть ваш рантайм, ваш JIT-компилятор, ваш интерпретатор и т.п.

В случае JavaScript я часто слышу понятие «движок». Так вот, мы можем говорить о производительности движков, но не о производительности языка. Так вот:
  • чем запускают ваш JavaScript?
  • кто вам сказал, что он интрепретируется, а не компилируется?
  • кто вам сказал, что описанные методики и результаты корректны?


Далее, о том, что синтетические бенчмарки ни о чем не говорят — известно уже очень давно.

Чтобы реально говорить о том, что быстрее и почему, а не разбрасываться словами, надо смотреть, почему именно. Искать корень того, почему ваш бенчмарк не может работать быстрее, смотреть, во что упирается разгон тестируемого кода. В статье я ничего такого не вижу.
Давайте начнем с того, что язык не может быть медленным или быстрым

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


(Оставляю за скобками web assembly и прочие костыли, которые по сути кодируют один язык с помощью другого и не предназначены для использования программистом напрямую.)

Не может. Вы пытаетесь играть словами и придумывать собственные интерпретации слов.

Но нет такого свойства у языка — «скорость».

Скорости — нет, системы типов и прочие архитектурные особенности, ограничивающие реализации в оптимизациях — есть. К чему городить сложные словесные конструкции?


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

Если автор хочет сказать, что реализация Regexp в JS чуть быстрее, чем в C++, то почему такой желтый заголовок?
Может автор маркетолог а не программист?
Чтобы вы почитали, наверное :)

Поправка: реализация регекспов чуть быстрее для данной конкретной задачи.

Я, конечно понимаю, что JavaScript — это реализация EcmaScript, которая преимущественно, отличается наличием DOM, но всё же, меня не покидает ощущение, что автор смешивает производительность самого языка и производительность объектного дерева, которого, если верить той же википедии может и не быть в конкретной реализации:
Если рассматривать JavaScript в отличных от браузера окружениях, то объектная модель браузера и объектная модель документа могут не поддерживаться.

О, прикольно. Я в 2010-м году про этот же тест и эту же benchmark game писал. JavaScript V8 и тогда всех выигрывал по regexdna. Меня тогда заминусовали, и я удалил пост. До сих пор стыдно :(

Javascript давно уже не только дум. К примеру
https://github.com/josephmisiti/awesome-machine-learning#javascript
Почему опять про Groovy забыли?
А JRuby почему медленный? Groovy компилируется в Java с использованием своих пакетов, но тем не менее от этого не страдает и даже позволяет использовать его на серверах. Как тогда JRuby действует?
Насколько мне известно самый быстрый (в среднем) интерпретатор — у LuaJIT. А у V8 JS интерпретатора вообще нет — есть 2 JIT-компилятора, один умеет быстро компилироваться, а другой — выдавать быстрый код. У Mozilla Spider(Ion)Monkey интерпретатор есть, но он не то, чтобы очень быстрый. Кроме того, крайне эффективный JIT-компилятор есть у Apple — до недавнего времени они использовали LLVM, но недавно написали свой бэкэнд. И тот же LuaJIT зачастую с микротестах работает быстрее любых JIT-компиляторов JS, даром что его один человек написал. Проигрывает LuaJIT в основном по причине простенького сборщика мусора, до которого у Майка раньше просто не дошли руки, а теперь процесс завис в непонятном состоянии.
Что же касается фразы «JS быстрее C++», то это вполне возможно даже если считать генерируемый JIT-ом код. Java не даст соврать. Пока, конечно, на длинных дистанциях у Hotspot конкурентов нет, но ничто не мешает прикрутить подобный механизм к V8. Хотя вряд ли кому придёт в голову это делать — требования к потребляемой памяти и скорости генерации кода у серверного и клиентского бэкэндов совсем разные. Скорее научат Java и C# генерировать IR-код для универсальной машины WebAssembly.
Вот что ещё подумал: если где-то пишут, что X быстрее C\C++, то это скорее всего означает, что C\C++ можно ускорить так, что он всё равно будет первым. Неоптимальный алгоритм? Реализуем оптимальный. Упор на массовую многопоточность? C\C++ есть чем ответить Erlang-у и Scala\Akka. Выигрыш от использования оптимизированного GC? Ничего не мешает взять этот GC целиком себе в проект, тем более, что он на C\C++ скорее всего и написан.
Как аргумент — проект максимально быстрой библиотеки регулярных выражений, с JIT, SIMD и всем этим. По словам автора этот написанный на C++ проект всё же опережает безусловно очень быстрый движок RE V8 в тесте regexdna.
https://github.com/coreperf/rejit
Ожидал увидеть в статье важный на мой взгляд тезис, что основное преимущество JavaScript (и других интерпретируемых языков) состоит в компиляции на компьютере пользователя и наличии интерпретатора с профайлером перед компилятором в машинные коды. Первое позволяет компилировать код в самые эффективные команды, доступные на запускаемой архитектуре. А второе позволяет эффективно оптимизировать основной путь исполнения кода. Ну и конечно JS позволяет делать эффектные оптимизации с помощью кодогенерации.
Еще раз: JavaScript на клиенте не лагает. Лагает медленный DOM (точнее манипуляции с DOM).

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

DOM медленный, но есть тот же mol, который работает с реальным DOM напрямую и судя по todomvc бенчмаркам (раз, два), гораздо быстрее многих фреймворков вроде реакта и ангулара. Дело в том, как изменения в стейте отражаются на DOM, в цене минимизации обновлений, а это уже архитектурные проблемы на стороне фреймворка.
Ускорив DOM, можно только замаскировать эти проблемы, задвинуть их на второй план.
Sign up to leave a comment.

Articles