Комментарии 91
Неплохо было бы написать версии браузеров. Результаты в Firefox 3.6 и 4 могут сильно отличаться.
+2
Учитывая, что LuaJIT позиционируется как высокопроизводительный инструмент для 3D моделирования и игр, то это очень весьма-весьма неожиданно.
В очередной раз порадовала скорость JS в Хроме :)
В очередной раз порадовала скорость JS в Хроме :)
+2
Удивило, что LuaJIT отстал даже от Internet Explorer.
+4
Может вы как-то не в курсе, но 9-й эксплорер показывает неплохую скорость на фоне остальных браузеров.
-7
Lua создавался как дополнительный язык и не предназначен для написание рейтрейсерор, он скорее предназначен чтобы писать расширения части приложений, например логику или задания для игры, а не полноценные приложения.
+2
JavaScript создавался как дополнительный язык и не предназначен для написание рейтрейсерор, он скорее предназначен чтобы писать расширения части приложений, например логику или задания для игры, а не полноценные приложения.
+16
Теперь с приходом HTML5, JavaScript хотят превратить в полноценный язык для написания Веб-приложений, и как ни странно ребятам из WHATWG это удалось.
-2
Зачем тогда Lua, если есть JavaScript?
0
Зачем язык X, если есть язык Y. Это универсальный вопрос и пытаться дать на него ответ бессмысленное занятие.
+5
НЛО прилетело и опубликовало эту надпись здесь
Только вот незадача-то, lua на два года старше JavaScript.
0
НЛО прилетело и опубликовало эту надпись здесь
Если я правильно понял, то ваша фраза про «поделие времен жестокого прессинга некрософтом нетскейпа» переводится что-то вроде «в те далёкие-далёкие времена, к которым lua отношения не имеет».
Теперь оказывается, что всё наоборот и это всё равно не имеет значения. Забавно.
Теперь оказывается, что всё наоборот и это всё равно не имеет значения. Забавно.
0
Он имеет ввиду, что первая версия javascript была реализован Netscape за 7 дней, без особого проектирования. Ходит такая байка.
-1
Какая странная версия. Она противоречит всему, что я знаю об этом языке.
0
Странно, а везде написано, что JS создавали три человека. Исходник переведённой статьи недоступен (надо будет поискать копии), а процитированные фразы выносят мне мозг.
Например: «что-то вроде PHP, только еще хуже. Его босс Netcsape быстро «зарубил» (в июле 1995, если мне не изменяет память; я сдлелал JS в начале/середине мая), т.к. это был уже третий язык после Java и JS. Было и так трудно обосновать то, что у нас 2 новых языка программирования для web.»
Такое ощущение, что речь идёт о каком-то ещё языке, который был уже после Java и JS. О каком? Так как это выдрано из контекста, в комментариях к статье люди подумали, что это относится к JavaScript.
Я знаю, что был язык до JS, который назывался сначала Cmm, а потом стал называться ScriptEase (очень странное название, рифмующееся у меня со striptease).
Например: «что-то вроде PHP, только еще хуже. Его босс Netcsape быстро «зарубил» (в июле 1995, если мне не изменяет память; я сдлелал JS в начале/середине мая), т.к. это был уже третий язык после Java и JS. Было и так трудно обосновать то, что у нас 2 новых языка программирования для web.»
Такое ощущение, что речь идёт о каком-то ещё языке, который был уже после Java и JS. О каком? Так как это выдрано из контекста, в комментариях к статье люди подумали, что это относится к JavaScript.
Я знаю, что был язык до JS, который назывался сначала Cmm, а потом стал называться ScriptEase (очень странное название, рифмующееся у меня со striptease).
0
Между Lua и JS есть важное отличие: Lua-программа может взаимодействовать с ОС (записывать файлы например), а также Lua-машину можно расширить любым кодом на любом языке (можно dll подключить и вызывать функции из этой dll прямо из кода на Lua). JS ограничен рамками браузера.
-2
Как фанат языка Lua, ни за что не поверю в данные результаты, где то есть подводный камень, который всё это объясняет.
+1
Я тоже фанат Lua и очень хочу найти этот подводный камень :) Этот рейтрейсер на Lua я написал не просто так: я хочу сделать рейстрейсер 4-х мерного пространства, а там нужна производительность хотя бы 1,000,000 RPS. Мне казалось, Lua будет в 20 раз быстрее JS, а оказалось…
+4
Скорее всего в Lua неоптимально реализованы математические функции. Может это «исследование» позволит выявить «слабое звено» и оптимизировать LuaJIT
0
Рейтрейсеру нужно только уметь делать 4 арифметические операции и находить квадратный корень. Все эти пять действий вычисляются процессором, так что их не получится неоптимально реализовать. Другое дело сама среда Lua — сборщик мусора, создание новых объектов, обращения к полям таблиц — может иметь какие то особенности которых я не знаю.
0
0
Для чистоты эксперимента его нужно будет делать и для JS и для Lua.
+1
Поможет, но когда я напишу рейтрейсер на C :) Тот хак для квадратного корня заточен под разрядность числа, а в JS я не знаю сколько бит в числах.
+2
Интересно что, по тестам shootout.alioth.debian.org/u64/performance.php?test=mandelbrot&sort=elapsed LuaJit лишь немногим медленнее С++. Для построения множества мандельброта тоже требуется лишь небольшое множество математических операций.
0
Проекцию из 4D в 2D? А какая там будет логика z-буфера? Или речь идет о проекции трехмерного сечения 4D?
+1
Нет, именно всего 4D на 2D. Сделать проекцию трёхмерного среза 4D на 2D можно уже сейчас: нужно просто заменить строку vec.dim = 3 на vec.dim = 4. Получится такая картинка:
Увидеть все 16 вершин не получится: они не лежат в трёхмерном пространстве.
Проецирование 4D я собираюсь делать в два шага: сначала спроецирую 4D на трёхмерный куб (аналог 2-мерного монитора) и затем этот куб спроецирую на плоский экран. Но делать это буду наоборот: буду выпускать лучи из камеры (то место откуда смотрит 3-мерный наблюдатель) лежащей в одном 3-мерном срезе с кубом, лучи будут проходить через куб и через точки пересечения луча с кубом я буду запускать лучи из второй камеры (глаз четырёхмерного наблюдателя) которые пересекаясь с тем 3-мерным кубом ровно в одной точке будут сталкиваться с предметами на сцене (с тессерактом). Это требует N3 лучей где N — ширина кубического монитора. Учитывая, что лучи преломляются и отражаются в среднем 300 раз, надо отрендерить 300•N3 лучей, 0.3 триллиона.
Увидеть все 16 вершин не получится: они не лежат в трёхмерном пространстве.
Проецирование 4D я собираюсь делать в два шага: сначала спроецирую 4D на трёхмерный куб (аналог 2-мерного монитора) и затем этот куб спроецирую на плоский экран. Но делать это буду наоборот: буду выпускать лучи из камеры (то место откуда смотрит 3-мерный наблюдатель) лежащей в одном 3-мерном срезе с кубом, лучи будут проходить через куб и через точки пересечения луча с кубом я буду запускать лучи из второй камеры (глаз четырёхмерного наблюдателя) которые пересекаясь с тем 3-мерным кубом ровно в одной точке будут сталкиваться с предметами на сцене (с тессерактом). Это требует N3 лучей где N — ширина кубического монитора. Учитывая, что лучи преломляются и отражаются в среднем 300 раз, надо отрендерить 300•N3 лучей, 0.3 триллиона.
+6
Понятно. Z-буфер будет на обеих проекциях? Или только на первой, а визуализация 3D будет полупрозрачными объектами?
Играясь с сочетаниями перспективных проекций 4D->3D->2D (точнее, я начинал даже с 5D), я обнаружил странный факт: результат можно описать формулами X=x/w, Y=y/w в подходящей прямоугольной системе координат, т.е. это будет сочетанием центральной и параллельной проекций! Но что там с z-буфером, я еще не разбирался. Кажется, роль «глубины» будет играть z-координата, вдоль которой идет параллельная проекция. Но надо смотреть подробнее.
Играясь с сочетаниями перспективных проекций 4D->3D->2D (точнее, я начинал даже с 5D), я обнаружил странный факт: результат можно описать формулами X=x/w, Y=y/w в подходящей прямоугольной системе координат, т.е. это будет сочетанием центральной и параллельной проекций! Но что там с z-буфером, я еще не разбирался. Кажется, роль «глубины» будет играть z-координата, вдоль которой идет параллельная проекция. Но надо смотреть подробнее.
0
Я может глупость спрошу, но разве в рей-трейсинг есть Z-буфер?
+1
Может, и нет. Имелось в виду, как будут взаимодействовать объекты, проектирующиеся в одну точку: будет ли один из них перекрывать другой, и если да — в каком порядке (ведь в точку там проецируется 2D-плоскость!), или они будут как-то сливаться (как полупрозрачные облака)
0
Я наверно запутанно описал свою идею. Она же, но немного по другому.
Пусть у нас есть тессеракт T в 4-х мерном пространстве. Выберем трёхмерный куб M3 — монитор 4-х мерного наблюдателя. Возьмём камеру C не лежащую в трёхмерной плоскости с M3. Спроектируем T на M3 с помощью C и получим проекцию T' — она лежит внутри M3. Теперь возьмём наш двумерный монитор M2 и камеру C2 так, чтобы из этой камеры было видно через M2 проекцию T'. Спроектируем T' на M2 и получим T'' — это то что мы увидим на экране. Реализация этого алгоритма будет делать всё в обратном порядке: выпускать луч из C2, находить пересечение с T', выпускать луч из C через точку пересечения и находить пересечение с T.
Пусть у нас есть тессеракт T в 4-х мерном пространстве. Выберем трёхмерный куб M3 — монитор 4-х мерного наблюдателя. Возьмём камеру C не лежащую в трёхмерной плоскости с M3. Спроектируем T на M3 с помощью C и получим проекцию T' — она лежит внутри M3. Теперь возьмём наш двумерный монитор M2 и камеру C2 так, чтобы из этой камеры было видно через M2 проекцию T'. Спроектируем T' на M2 и получим T'' — это то что мы увидим на экране. Реализация этого алгоритма будет делать всё в обратном порядке: выпускать луч из C2, находить пересечение с T', выпускать луч из C через точку пересечения и находить пересечение с T.
+1
Нет, эту идею я понял хорошо — я этот вариант проекции называю «трехмерной сетчаткой». Но дело в том, что как бы мы не реализовывали проекцию 4D на 2D, у нас каждой точке экрана будет соответствовать двумерная плоскость в 4D. Часть этой плоскости будет «невидимой», а остальные точки неизбежно будут как-то отсортированы по отношению «кто кого перекрывает». Например, в случае «трехмерной сетчатки» картина будет такой:
Видимая область для данной точки экрана — угол с вершиной в камере C. Границы угла будут определяться положением камеры C2 (в этом месте я не уверен). Если записать точку внутри этого угла в полярных координатах (r,a), то для двух точек (r1,a1) и (r2,a2) видимой будет та, для которой a1<a2 или (a1=a2 и r1<r2). То есть основным будет порядок по углу (проекция C2), а вторичным — порядок по дальности (проекция C).
Может быть, пересечение модели с углом и ближайшую точку можно будет найти быстрее, чем трассируя все лучи этого угла?
Видимая область для данной точки экрана — угол с вершиной в камере C. Границы угла будут определяться положением камеры C2 (в этом месте я не уверен). Если записать точку внутри этого угла в полярных координатах (r,a), то для двух точек (r1,a1) и (r2,a2) видимой будет та, для которой a1<a2 или (a1=a2 и r1<r2). То есть основным будет порядок по углу (проекция C2), а вторичным — порядок по дальности (проекция C).
Может быть, пересечение модели с углом и ближайшую точку можно будет найти быстрее, чем трассируя все лучи этого угла?
0
Еще немного смущает наличие «монитора M3». Если действовать так, как Вы описали, то получится изображение куба, «вырезанного» из некоторой трехмерной среды. Будут видны его грани, где в разрезе покажут «внутренние» детали изображения (нет, 4D-наблюдатель будет считать их внешними, но мы обычно можем видеть лишь «силуэты» того, что видит он). Это действительно соответствует замыслу? Или в идеале хотелось бы получить проекцию того, что наблюдатель увидел бы на бесконечном дисплее (со зрением, охватывающим 180 градусов)?
0
И есть у этого подхода серьезная проблема. Если таким образом попытаться получить изображение четырехмерной комнаты, то окажется, что по краям монитора M3 будут только изображения пола, стен и потолка, а все самое интересное будет спрятано внутри. Даже если съемка идет на открытом воздухе, то мы увидим, что часть объекта, находящаяся ниже уровня камеры «утонет» в земле (на фотографиях нашего имра мы видим, что часть тела человека находится на фоне земли, но флатландец, изучив эту фотографию, сказал бы, что человек утонул в земеле, а на поверхности торчит только голова, состоящая из волос и ушей.
Что со всем этим делать, я так и не придумал. Поэтому идею своего 4D-вьюера/редактора мне пришлось отложить на неопределенное время.
Что со всем этим делать, я так и не придумал. Поэтому идею своего 4D-вьюера/редактора мне пришлось отложить на неопределенное время.
0
У вас может быть много пересечений, и вы ищете ближайшее.
0
Я планирую обойтись без Z-буфера. Визуализацию 3D пока не знаю как лучше сделать: можно сплошной (как на рисунках) а можно и полупрозрачной (будет дольше работать). Смотря как красивее получится.
0
Если нужна производительность, стоит обратить внимание на GPU. OpenCL или CUDA на приличной карточке гораздо лучше справятся с такой высокопараллельной задачей чем скриптовые языки.
+2
Надеюсь, что дело в том, что LuaJIT сейчас в фазе стабилизации, а после фазы оптимизации ситуация улучшится.
0
Теперь бы еще сюда добавить результаты на С++, Java, C# и Phyton.
+7
Питон? Зачем? Разве что PyPy потестить, конечно…
-1
ссылочка в тему: www.cnblogs.com/miloyip/archive/2010/07/07/languages_brawl_GI.html
там правда все по-китайски, но суть ясна и без знания китайского: человек тоже какой-то рендерер написал на куче языков; можно иероглифы пропускать и в пролетарскую суть диаграм с результатами замеров вникать ;-)
там правда все по-китайски, но суть ясна и без знания китайского: человек тоже какой-то рендерер написал на куче языков; можно иероглифы пропускать и в пролетарскую суть диаграм с результатами замеров вникать ;-)
+3
ИМХО дело в том, сколько внимания уделяют языку. JavaScript развивается динамичней ибо он востребован, под него затачиваются интерпретаторы, движки браузеров; в него вкидываются деньги на порядок больше, чем в Lua, вот и результат
0
Робко прошу вас задокументировать код.
+1
Мысль очень правильная :) Я не сделал этого по одной причине: боялся, что кто-нибудь откроет файл raytracer.js, увидит там 2000 строчек какого то текста и подумает «ну вот… а говорил, что код рейтрейсера простой — а тут как обычно манускрипт на несколько экранов», хотя большая часть текста будет на самом деле комментариями. Я однажды читал исходник алгоритма BWT написанный автором DjVu (они в свободном доступе) — там столько текста, что… Но если выкинуть комментарии, то окажется, что кода совсем немного.
Мне не сложно прокомментировать: напишите только список файлов в которых вы хотите увидеть комментарии.
Мне не сложно прокомментировать: напишите только список файлов в которых вы хотите увидеть комментарии.
+1
Да вроде всё понятно. Просто нужно было догадаться, что в этих языках так объекты выглядят. :)
0
raytracer.lua и screen.lua.
И в методе vec.vec похоже происходит что-то простое, но лень читать две страницы кода на lua когда вы это одним предложением по-русски можете сказать :)
И в методе vec.vec похоже происходит что-то простое, но лень читать две страницы кода на lua когда вы это одним предложением по-русски можете сказать :)
0
Прошу прощения за назойливость, но когда можно ожидать комментарии?
0
вы бы еще на перле написали и пнули тушку попугая…
+1
chrome9 (32b) — 16556
luajit-2.0.0-beta5 (64b) — 8881
luaj не смог запустить, org.luaj.vm2.LuaError: cubecyl.lua:37: attempt to index? (a nil value)
osx 10.6/core2duo 2.53
luajit-2.0.0-beta5 (64b) — 8881
luaj не смог запустить, org.luaj.vm2.LuaError: cubecyl.lua:37: attempt to index? (a nil value)
osx 10.6/core2duo 2.53
0
Node.js+node-canvas в среднем чуть медленнее, но не больше 5%.
GC: 9.0.597.84 beta
Node: v0.3.7
node-canvas: 0.4.3
GC: 9.0.597.84 beta
Node: v0.3.7
node-canvas: 0.4.3
0
Intel Core i5 750, 2.67GHz
Windows 7 Ultimate
chrome9 (9.0.597.84) — 22129
luajit-2.0.0-beta5 — 23946
изменения в коде луа:
— все вызовы глобальных функций переделаны на вызов локальных функций:
local bitband, bitlshift = bit.band, bit.lshift
— понижена цикличность сборки мусора
collectgarbage(«setpause», 600)
Windows 7 Ultimate
chrome9 (9.0.597.84) — 22129
luajit-2.0.0-beta5 — 23946
изменения в коде луа:
— все вызовы глобальных функций переделаны на вызов локальных функций:
local bitband, bitlshift = bit.band, bit.lshift
— понижена цикличность сборки мусора
collectgarbage(«setpause», 600)
+4
0
Впечатляет. Я ещё заметил, что Lua тратит много времени на заполнение массива в screen.render:
Если убрать эту строчку, а также вывод процентов через io.write, то скорость возрастает более чем в три раза. Надо заметить, что для JS это не важно: там вывод на экран и сохранение пикселей не влияет на скорость. Как сказать Lua, что this.pixels это массив фиксированной длины?..
this.pixels[index] = color
Если убрать эту строчку, а также вывод процентов через io.write, то скорость возрастает более чем в три раза. Надо заметить, что для JS это не важно: там вывод на экран и сохранение пикселей не влияет на скорость. Как сказать Lua, что this.pixels это массив фиксированной длины?..
+1
Впечатляет. Я ещё заметил, что Lua тратит много времени на заполнение массива в screen.render:
this.pixels[index] = color
трудно сказать в чем дело, но если заменить эту строчку на
this.pixels[index] = index
то RPS увеличивается до 41491
Или снова сборщик мусора, или не совсем оптимальный алгоритм хеширования в таблице.
+1
все вызовы глобальных функций переделаны на вызов локальных функций
если вы действительно все вызовы заменяли, то ради чистоты эксперимента следовало бы аналогичную операцию и с JavaScript проделать.
понижена цикличность сборки мусора
да, встроенный GC в Lua при «мусора много и мрет он молодым» ведет себя хуже GC V8.
0
если вы действительно все вызовы заменяли, то ради чистоты эксперимента следовало бы аналогичную операцию и с JavaScript проделать.
Запустил Lua тест с оригинальными файлами без локальных функций. Изменений особых нет +- пару процентов.
да, встроенный GC в Lua при «мусора много и мрет он молодым» ведет себя хуже GC V8.
Да, сборка мусора в хроме отменная: скрипт добирается до 200Мб, потом через несколько секунд чистит мусор до 96мб, и снова увеличивается в размере. Насколько я помню, в v8 сборщик многопоточный, видимо тут выигрыш.
С луа все гораздо хуже: если шаг сборки 600, то сборщик видимо вообще не срабатывает, кушая 500мб. Если шаг 300, то потребление памяти медленно растет до 230 мб.
0
Запустил Lua тест с оригинальными файлами без локальных функций. Изменений особых нет +- пару процентов.
Т.е. если функции вызывать глобально, а сборку мусора отложить, то получается быстро?
Ага! Ну я так и думал, что в GC дело. От LJ2 следует ожидать, что он сам поднимет загрузку глобалов (load hoisting). На обычных числодробилках даже Crankshaft (V8 после 3.0) к LuaJIT2 вроде не подобрался пока, я уж не говорю о классическом бэкенде (V8 до 3.0).
Насколько я помню, в v8 сборщик многопоточный
Нет, он однопоточный (точнее они, для частичных сборок в молодом поколеннии копирующий scavenger, для полных сборок — MarkSweep/MarkCompact). Ну и пауза в несколько секунд — это, м-м-м-м, не сказать что бы отменный сборщик :-)
+1
Участие принимали Chrome 9.0 Beta
Хм. А ведь это с V8 2.5.x, т.е. без Crankshaft, т.е. без серьезной адаптивной компиляции.
Как бы не оказалось, что тут все упирается исключительно в GC.
0
Если вы перепишите код на С++ то я готов помочь портировать на C# для Silverlight (WriteableBitmap) и WinForms (GDI+).
Очень интересно сравнить скорость.
Очень интересно сравнить скорость.
+1
Тред про этот хабратопик в Луашной рассылке:
thread.gmane.org/gmane.comp.lang.lua.general/75252
Мнение Майка Палла, автора LuaJIT:
article.gmane.org/gmane.comp.lang.lua.general/75265
thread.gmane.org/gmane.comp.lang.lua.general/75252
Мнение Майка Палла, автора LuaJIT:
article.gmane.org/gmane.comp.lang.lua.general/75265
+2
Я бы не догадался написать «a = ffi.new('double[?]', ...)» вместо «a = {}». Это какая то фича LuaJIT — в документации Lua я такого не встречал. Вообще было бы неплохо, если бы Mike написал подобные простые сценарии кода.
Я могу дать ему инвайт, если он захочет зарегистрироваться.
Я могу дать ему инвайт, если он захочет зарегистрироваться.
0
Да, это фича LuaJIT 2, начиная с beta6. См. luajit.org/ext_ffi.html и соседние топики в меню слева.
Майк сожалеет, но у него сейчас недостаточно времени, чтобы отвечать на Хабре.
Он читает письма и отвечает на вопросы в официальной рассылке Луа (на английском): www.lua.org/lua-l.html
По-русски вопросы Майку можно задавать, например, через меня.
Майк сожалеет, но у него сейчас недостаточно времени, чтобы отвечать на Хабре.
Он читает письма и отвечает на вопросы в официальной рассылке Луа (на английском): www.lua.org/lua-l.html
По-русски вопросы Майку можно задавать, например, через меня.
0
Почитал про эту фичу, впечатляет. Однако я вынужден не согласиться с Майком по поводу использования таких методов при сравнении. Ниже ответ ему.
Hello Mike,
Today I suddenly found from agladysh that you know about my simple raytracer and you even analysed my code. You found that the code produces lots of temporary objects (that become garbage almost immediately after creation) and that the code dynamically inserts pixels to a Lua-table. These two things make the program extremely slow. Almost exactly the same code I've written in JavaScript — it also produces lots of temporary objects and inserts pixels one-by-one to an array — and this code appeared much faster under Chrome than the Lua code under LuaJIT.
You offered a simple solution: to replace the standard and simple array «pixels = {}» with a special array «pixels = ffi.new(...)». Your solution makes the program much faster — even faster than JS under Chrome. But from this point we're comparing not JS and Lua but JS and Lua+LowLevelFeatures. To make the comparsion correct, we must allow to use in JS features like WebGL and that'd make the comparsion meaningless — I didn't want to know what is faster WebGL or FFI.
It'll be more honestly to rewrite the Lua code so as it'll not create tons of objects with short life, but this thing must be done in both Lua and JS code and it's unclear who will appear faster: LuaJIT or JS V8.
ankh1989@habrahabr.ru
Hello Mike,
Today I suddenly found from agladysh that you know about my simple raytracer and you even analysed my code. You found that the code produces lots of temporary objects (that become garbage almost immediately after creation) and that the code dynamically inserts pixels to a Lua-table. These two things make the program extremely slow. Almost exactly the same code I've written in JavaScript — it also produces lots of temporary objects and inserts pixels one-by-one to an array — and this code appeared much faster under Chrome than the Lua code under LuaJIT.
You offered a simple solution: to replace the standard and simple array «pixels = {}» with a special array «pixels = ffi.new(...)». Your solution makes the program much faster — even faster than JS under Chrome. But from this point we're comparing not JS and Lua but JS and Lua+LowLevelFeatures. To make the comparsion correct, we must allow to use in JS features like WebGL and that'd make the comparsion meaningless — I didn't want to know what is faster WebGL or FFI.
It'll be more honestly to rewrite the Lua code so as it'll not create tons of objects with short life, but this thing must be done in both Lua and JS code and it's unclear who will appear faster: LuaJIT or JS V8.
ankh1989@habrahabr.ru
+1
спасибо за вашу статью!
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Публикации
Изменить настройки темы
Lua vs. JavaScript