Вы наверное шутите, мистер Дал, или почему Node.js — это венец эволюции веб-серверов

WTF is Node.js?

Node.js — вещь, вокруг которой сейчас много шума, восторженных отзывов и гневливых выкриков. При этом, по моим наблюдениям, в умах людей закрепилось следующее представление о том что же такое Node.js: «это штука, позволяющая писать на JavaScript на серверной стороне и использующая JavaScript-движок от Google Chrome». Поклонники языка восторженно вздохнули: «Ах! Сбылось!», противники же процедили сквозь зубы: «Ну вот только еще этой ерунды с прототипами и динамической типизацией нам на серверах не хватало!». И дружно побежали ломать копья в блоги и форумы.

При этом многие представители обоих лагерей придерживаются мнения, что Node.js — это эзотерическая игрушка, веселая задумка для переноса языка браузерных сценариев на «новые колеса». Дабы быть до конца честным, признаюсь, что я так же придерживался подобной точки зрения. В один прекрасный момент, я набрался духу и решил «копнуть поглубже». Выяснилось, что создатель Node.js Райан Дал далеко не фанатик, а человек, пытающийся решить реальную проблему. А его творение — не игрушка, а применимое на практике решение.


Так что же такое Node.js? На официальном сайте красуется надпись: «Evented I/O for V8 JavaScript». Не очень то содержательно, верно? Ну что ж, давайте попробуем «изобрести велосипед» и «придумаем» этот самый пресловутый «Evented I/O for V8 JavaScript». Конечно же мы не будем писать никакого кода (бедняге Райану все таки пришлось это делать), а лишь попробуем построить цепочку умозаключений, которые приведут нас к замыслу создания Node.js и тому как он должен быть устроен.

Keep it simple, stupid


Итак, вы знаете, что web-приложения используют клиент-серверную программную модель. Клиентом выступает браузер пользователя, а сервером — например, одна из машин в датацентре некоторого хостера (выберите любого на ваш вкус). Браузер запрашивает какой-то ресурс у сервера, тот, в свою очередь, его отдает клиенту. Такой способ общения клиента и сервера называется «client pull», т. к. клиент буквально дергает (англ. pull) сервер — «Дай-ка мне вон ту страничку, ну дай...». Сервер «обдумывает» ответ на вопрос назойливого клиента и отдает ему его в удобоваримом виде.

Simple web server

Итак, у нас есть модель простейшего веб-сервера — программа, которая принимает запросы от клиентов-браузеров, обрабатывает их и возвращает ответ.

Parallel universe


Здорово, но такой простейший сервер умеет одновременно общаться лишь с одним пользователем. Если в момент обработки запроса к нему обратиться еще один клиент, то ему придется ждать пока сервер ответит первому. Значит нам нужно распараллелить обработку запросов от пользователей. Очевидное решение: обрабатывать запросы пользователей в отдельных потоках или процессах операционной системы. Давайте назовем каждый такой процесс или поток — worker'ом (англ. рабочий).

Server with threads

В том или ином виде данного подхода придерживаются многие наиболее популярные сегодня веб-серверы (например, Apache и IIS). Данная модель относительно проста в реализации и при этом может удовлетворить потребности большинства малых и средних веб-ресурсов на сегодняшний день.

Но данная модель совершенно не дееспособна, если вам нужно обрабатывать тысячи запросов одновременно. Причин для этого несколько. Во-первых, создание и процессов и потоков — вещь чертовски накладная для любой операционной системы. Но мы можем пойти на хитрость и создавать потоки или процессы заранее и использовать их по мере надобности. OK, мы только что придумали механизмы под названием «thread pool» для потоков и «prefork» для процессов. Это поможет нам не тратить лишний раз ресурсы на создание процессов и потоков, поскольку эта накладная операция может быть выполнена, например, при запуске сервера. Во-вторых, что делать, если все созданные worker'ы заняты? Создать новые? Но мы и так по полной загрузили все ядра процессора нашего сервера, если мы добавим еще несколько потоков или процессов, то они будут конкурировать за процессорное время с уже исполняющимися потоками и процессами. А значит и те и другие будут работать еще медленней. Да, и как отмечалось ранее, создание и обслуживанием потоков и процессов — вещь затратная в плане потребления оперативной памяти и если мы будем создавать поток для каждого из тысячи пользователей, то вскоре можем оказаться в ситуации, когда памяти на сервере попросту не останется, а worker'ы будут находится в состоянии постоянного соревнования за аппаратные ресурсы.

Бесконечность — не предел!


Казалось бы мы оказались в неразрешимой ситуации при имеющихся у нас вычислительных ресурсах. Единственное решение — масштабирование аппаратных ресурсов, что затратно во всех отношениях. Давайте попробуем взглянуть на проблему с другой стороны: чем же заняты большинство наших worker'ов? Они принимают запрос от клиента, создают ответ и отправляют его клиенту. Так где же тут слабое звено? Их здесь целых два — прием запроса от клиента и отправка ответа. Что бы понять что это так, достаточно всего лишь вспомнить среднюю скорость интернет-соединения на сегодняшний день. Но ведь подсистема ввода/вывода может работать в асинхронном режиме, а следовательно может не блокировать worker'ов. Хм, тогда получается фактически единственное чем будут заниматься наши worker'ы — это генерация ответа для клиента и управление заданиями для подсистемы ввода/вывода. Ранее каждый worker мог обслуживать лишь одного клиента одновременно, т. к. брал на себя обязанности по исполнению всего цикла обработки запроса. Теперь же когда сетевой ввод/вывод мы делегировали подсистеме ввода/вывода, то один worker может одновременно обслуживать несколько запросов, например, генерируя ответ для одного клиента, пока ответ для другого отдается подсистемой ввода/вывода. Получается теперь нам не нужно выделять поток для каждого из пользователей, а мы можем создавать по одному worker'у на процессор сервера, предоставляя ему, таким образом, максимум аппаратных ресурсов.

На практике такое делегирование реализуется с использованием парадигмы событийно-ориентированного программирования. Программы, разработанные согласно данной парадигме могут быть реализованы как конечный автомат. Определенные события переводят данный автомат из одного состояния в другое. В нашем случае сервер будет реализован в виде бесконечного цикла, который будет генерировать ответы для клиентов, опрашивать дескрипторы подсистемы ввода/вывода на предмет их готовности для выполнения той или иной операции, и, в случае успеха, передавать им новое задание. Процесс опроса дескрипторов подсистемы ввода/вывода называется «polling». Дело в том, что эффективные реализации polling'а на сегодняшний день имеются лишь в *nix-системах, т.к. последние предоставляют очень быстрые системные вызовы c линейным временем исполнения для данных целей (например, epoll в Linux и kqueue в BSD-системах). Это очень эффективная модель сервера, т. к. позволяет использовать аппаратные ресурсы по-максимуму. Фактически, ни одна из подсистем сервера не простаивает без дела, в чем можно легко убедиться посмотрев на рисунок.

Server with async I/O

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

Let's come together


Но (всегда же есть «одно но»), до этого мы отталкивались от идеи, что генерация ответа занимает на порядок меньше времени чем общение с клиентом. И это отчасти верно. Тем не менее, генерация ответа порою может быть сложной и комплексной задачей, которая может включать в себя чтение и запись на диск, работу с базой данных (которая так же может находиться на удаленном сервере). Что же, получается мы фактически вновь вернулись к исходной проблеме. На практике она разрешается следующим образом: система разбивается на две части — front-end и back-end. Front-end — это сервер, с которым непосредственно общается клиент. Как правило это сервер с асинхронной событийной моделью, который умеет быстро устанавливать связь с клиентами и отдавать им результаты запроса (например, nginx). Back-end — это сервер с блокирующей моделью ввода/вывода (например, Apache), которому front-end делегирует создание ответа для клиента, точно так же как он это делает с подсистемой ввода/вывода. Подобный front-end так же называют «reverse proxy», т. к. по сути это обычный proxy-сервер, но установленный в том же серверном окружении, что и сервер, к которому он перенаправляет запросы.

Если проводить аналогии с реальной жизнью, то front-end — это менеджер с блестящими от белизны зубами и в дорогом костюме, back-end — группа рабочих на заводе, а подсистема ввода/вывода — транспортный отдел компании, на которую работает менеджер и которой принадлежит завод. Клиенты обращаются к менеджеру, отправляя ему письма через транспортный отдел. Менеджер заключает сделку с клиентом на поставку партии изделий и направляет указание рабочим изготовить партию. Сам менеджер, в свою очередь, не ожидает пока рабочие закончат исполнение заказа, а продолжает заниматься своими непосредственными обязанностями — заключает сделки с клиентами и следит за тем, что бы весь процесс происходил согласованно и ладно. Периодически менеджер связывается с рабочими что бы осведомиться о степени готовности заказа, и, если партия готова, то дает указание транспортному отделу отправить заказ клиенту. Ну и, естественно, периодически следит, что бы товар дошел до клиента. Вот так придуманная тысячи лет назад идея разделения труда нашла неожиданное применение в высоких технологиях.

И жнец, и швец, и на дуде игрец (казалось бы, причем тут JavaScript?)


Что же, все это прекрасно работает, но как то наша система чрезвычайно усложнилась, не находите? Да, хоть мы и делегируем генерацию ответа другому серверу, это все равно не самый быстрый процесс, т. к. в ходе него могут происходить блокировки из-за файлового ввода/вывода и работы с базой данных, что неминуемо приводит к простою процессора. Так как же нам вернуть системе целостность и при этом ликвидировать узкие места в процессе генерации ответа? Элементарно, Ватсон — сделаем весь ввод/вывод и работу с базой данных неблокирующими, построенными на событиях (да-да, то самое evented I/O)!

«Но это же меняет всю парадигму создания веб-приложений, и большинство имеющихся framework'ов уже не применимы или применимы, но решения с их использованием не элегантны!» — скажите вы и будете правы. Да, и нельзя исключать человеческий фактор — применяя закон Мерфи можно утверждать, что «если имеется возможность использовать функции блокирующего ввода/вывода, то кто-нибудь рано или поздно это сделает», поломав таким образом всю первоначальную задумку. Это лишь вопрос времени, объемов проекта и квалификации программистов. «Be careful making abstractions. You might have to use them.» (англ. «Будьте осторожны в создании абстракций, ведь, возможно, вам придется их использовать») — говорит Райан в своем выступлении на Google Tech Talk. Так давайте будем придерживаться минимализма и создадим лишь фундамент, который позволит нам разрабатывать веб-приложения и при этом будет настолько хорошо заточен под асинхронную модель программирования, что у нас не будет возможности, а главное — желания, от нее отступить. Так какой же минимум нам нужен?

Очевидно, что для начала нам нужна исполняющая среда, основные требования к которой — быстрое исполнение кода генерации ответа и асинхронный ввод/вывод. Какой современный язык программирования заточен под событийную модель, известен всем веб-разработчикам и при этом имеет быстрые и активно развивающиеся реализации? Ответ очевиден — это JavaScript. Более того у нас в распоряжении есть JavaScript-движок V8 от Google, распространяемый под очень либеральной BSD-лицензией. V8 прекрасен во многих аспектах: во-первых, он использует JIT-компиляцию и множество других приемов оптимизации, а во-вторых, это образец добротно сделанного, продуманного и активно-развивающегося программного продукта (обычно я привожу V8 в качестве примера по-настоящему качественного кода на C++ для коллег на работе). Добавим ко всему этому библиотеку libev, которая позволит нам легко организовать событийный цикл и предоставит более высокоуровневую обертку для механизмов polling'а (так что нам не придется заботиться об особенностях его реализации для различных операционных систем). Так же нам понадобится библиотека libeio для быстрого асинхронного файлового ввода/вывода. Отлично, на этом нашу исполняющую среду можно считать готовой.

И, конечно же, нам нужна стандартная библиотека, которая будет содержать JavaScript-обертки для всех базовых операций ввода/вывода и функций, без которых в веб-разработке далеко не уйдешь (например, парсинг HTTP-заголовков и URL, подсчет хэшей, DNS-резолвинг и т. д.).

Node.js architecture

Наверное, стоит нас поздравить — мы только что придумали концепцию очень быстрого сервера — Node.js.

I'm just sayin'


Резюмируя, хочется сказать, что Node.js – это очень молодой проект, который при правильном использовании может в свое время произвести революцию в мире веб-разработки. Сегодня у проекта есть ряд еще нерешенных проблем, осложняющих его использование в реальных высоконагруженных системах (хотя уже имеются прецеденты). Например, Node.js представляет собой по сути лишь один worker. Если у вас, допустим, двухядерный процессор, то единственный способ по полной использовать его аппаратные ресурсы с Node.js — это запустить два экземпляра сервера (по одному на каждое ядро) и использовать reverse proxy (например, тот же nginx) для балансировки нагрузки между ними.
Но, все подобные проблемы разрешимы и над ними ведется активная работа, а вокруг Node.js уже строится огромное коммьюнити и многие крупные компании уделяют немалое внимание данной разработке. Остается лишь пожелать мистеру Далу довести его дело до конца (в чем, кстати, можно ему помочь), а тебе, дорогой читатель, — провести много приятного времени за разработкой под Node.js.
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 252
  • +37
    Напишите еще статью с примерами разработки на node.js
    • +36
      С радостью! Как раз в планах имеется подобный топик.
      • 0
        ок
        • 0
          Каюсь, забил я на писательство. К сожалению, на него банально не хватает времени.
    • +3
      Так где же тут слабое звено? Их здесь целых два — прием запроса от клиента и отправка ответа.
      Отдаём это на откуп nginx, обрабатывающему все запросы в одном потоке (ну, можно и в нескольких, если хочется все процессы занять) и спим спокойно, продолжая использовать существующую инфраструктуру.
      • +7
        Именно об этом и повествует абзац из которого вы взяли данную цитату
        • +3
          Тьфу, не дочитал.
          Что же, все это прекрасно работает, но как то наша система чрезвычайно усложнилась, не находите? Да, хоть мы и делегируем генерацию ответа другому серверу, это все равно не самый быстрый процесс, т. к. в ходе него могут происходить блокировки из-за файлового ввода/вывода и работы с базой данных, что неминуемо приводит к простою процессора.

          Если у нас база перегружена, то, быстрее, чем есть, не получится. И решается это держанием нескольких воркеров на процессор.

          Как мне кажется, запихивать всё в одно место — не всегда наилучшее решение, оставьте работу с клиентами HTTP-серверу, а логику обрабатывайте на чём-нибудь, с чем он связывается через fastcgi (через unix-сокеты работает _очень_ быстро). Таким образом ещё и статика будет нормально раздаваться.
          • +3
            Само собой, Node.js — это не silver bullet. Но когда нужна простота инфраструктуры, быстрое развертывание и простая разработка я выступлю за Node.js (как только его доделают конечно же =))
            • +3
              Я сейчас использую связку nginx+mono-fastcgi-server, получил плюшки ASP.MVC на сервере с дебианом, очень доволен. Единственное, mono надо компилять свежий, старьё в репах lenny неработоспособно.
            • +3
              Вы точно уверены что «через unix-сокеты работает _очень_ быстро»? Я пробовал по разному настраивать nginx+php-fpm для отдачи <?php phpinfo(); на разных серверах и в итоге получалось, что только, используя tcp я смог добиться отдачи в 100000 одновременных соединений без единого fail через ab.
          • +7
            Вы уж определитесь, эзотерическая или экзотическая.
          • +8
            > Какой современный язык программирования заточен под событийную модель, известен всем веб-разработчикам и при этом имеет быстрые и активно развивающиеся реализации?
            Если взять первый и последний пункт — то Erlang, только он чуть хуже известен разработчикам.
            Зато событийность, fsm, эффективное использование всех ядер, надежность (чтобы ошибка в одном запросе не уронила все остальные) — все это «из коробки».
            На мой взгляд, имело бы смысл сделать обвязку всего этого добра на эрланге, а контент генерить каким-нибудь скриптовым языком.
            • +4
              Согласен, Erlang, пожалуй, даже лучше подходит для данных целей, но как вы правильно отметили — он меньше знаком разработчикам. Чего нельзя сказать о JS, который известен подавляющему большинству веб-программистов. Из чего вытекают два его неоспоримых плюса: 1)реализации исполняющей среды будут продолжать развиваться и поддерживаться крупными мейнтейнерами (в нашем случае — Google), 2)не потребуется заниматься переобучением персонала
              • +3
                Да. Наличие разработчиков — это очень важный фактор. См. историю успеха PHP.
                • +2
                  отмечу что большинству знаком не js, а js фреймворки (jquery, prototype, mootools), основная масса в лучше случае умеет создавать функции для js

                  зы в питере сейчас не найти толковых яваскриптеров, есть кадровый «голод»
                  • +4
                    х3, я наверное исключение, но лично я неплохо пишу на JS, и вообще не знаком с JS фреймворками :D
                    • –1
                      и вообще не знаком с JS фреймворками :D

                      • +1
                        А зря.
                        • –1
                          Почему сразу зря? Каждому свое. Я люблю low-level.
                          • +1
                            потому что вы можете любить low-level и даже использовать свой фреймворк/писать без фреймворка. Но не знание общепринятых фреймворков повышает ваш уровень профессионализма. Тем более, что в Javascriptе они прекрасны.
                            • +1
                              Если будет проект с требованием использования фреймворка — я способен быстро освоить нужный.
                              Учить заранее то, что может и не пригодиться — не вижу смысла, у меня есть интересные вещи для изучения и без этого.
                              При разработке «для себя» тянуть за страницами многосоткилобайтовые фреймворки не очень хочется.
                              • +1
                                я знаю на высоком уровне несколько Javascript фреймворков и при этом умею хорошо писать на чистом JS.
                                так вот — мне вас жаль)
                                • +3
                                  Если в текущий момент два разрабатываемых мной проекта вообще не требуют JS — мне что, надо все бросить и изучать фреймворки? Зачем?
                                  • +2
                                    но лично я неплохо пишу на JS, и вообще не знаком с JS фреймворками

                                    Неплохо писать на JS и быть незнакомым с фреймворками в большинстве случаев — мазохизм.
                                    • –1
                                      Это ваше имхо.
                                      • –1
                                        это недюжинный опыт мой и многих разработчиков, которые знают вариант программирование и без фреймворка и с фреймворком.
                                        • 0
                                          Ваш и других разработчиков опыт — истина в последней инстанции, лишающая других права иметь свое мнение и предпочтения?
                                          • –1
                                            вам нихто не мешает иметь своё сообственное мнение, что вы так нервничаете?
                                            просто чтобы утверждать, что о преимуществах разных подходов — необходимо знать все эти подходы, а не говорить «не пробовал, но осуждаю».
                                            а ваше невежество и отрицание хороших практик может послужить плохую службу тем, кто будет поддерживать ваш код.
                                            вы бы попробовали перед тем, как осуждать и с гордостью говорить о том, что не смогли осилить отличные инструменты.
                                            • +1
                                              А я где то утверждал, что делать так, как делаю я — единственно правильно и хорошо?
                                              Я писал, что так делаю я. Что так нравится мне. Это мое мнение.
                                              Вы же начали как раз таки кидаться фразами «мазохизм» «мне вас жаль» «а зря» и т.п.
                                              Я предлагаю сойтись на мнении, что для каждой задачи нужен подходящий инструмент и что нет абсолютной истины в последней инстанции, все субъективно.
                                              • 0
                                                а я вам могу просто порекомендовать посмотреть фреймворки. без подъёбок — не пожалеете.
                                                • 0
                                                  Спасибо за совет, обязательно посмотрю. Просто пока совсем не до того, как уже писал, два проекта, один на C#, другой на C, но если будет задача подходящая — у меня было в планах глянуть jQuery :)
                                                  Кстати, гляньте демку, которую я постил чуть ниже, у меня как раз большинство задач было такого рода — где важнее скорость работы и объем, чем скорость разработки, наверное поэтому не возникало желания посмотреть фреймворки.
                                  • 0
                                    Ваше мышление ограничивается фреймворками. Они являются вашим ограничителем при выборе решений.
                                    • 0
                                      моё мышление — разносторонее и основанное на опыте программирования без фреймворков и программирования на базе разных фреймворков.
                                      • 0
                                        Какие основные проблемы большинства популярных фреймворков вы знаете?
                                        • –2
                                          не надо меня инспектировать, я вам не провинившийся студент.
                                          • 0
                                            Для человека, который хоть раз в жизни над этим задумывался, дать ответ особого труда не составляет.
                                            • 0
                                              я осознаю проблемы большинства фреймворков. именно потому через год опыта работы с JQuery я перешёл на MooTools для некоторых фреймворков.
                                              Более того, я знаю, как эти фреймворки устроены, потому знаю их внутренние недостатки и приблизительно представляю, где могут быть потери производительности.
                                              но я не обязан перед вами отчитыватся, словно вы профессор, а я — школьник.
                                              • 0
                                                Устройство фреймворка не влияет на проблемы. Проблемы лежат за пределами их содержимого. Например, большинство нынешних фреймворков работают по принципу «Сначала найди что-то, а потом работай с этим». Реальность же такова, что в процессе изменения задачи изменяется и содержимое дерева нод, уровни вложенности, структура. И поэтому приходится постоянно видоизменять и HTML, и JS. Это один из примеров проблематики.
                                                • –1
                                                  какая проблема? в JQuery есть live и delegate для этого. более того, даже до появления этих методов всё отлично работало через event.target. В фреймворках есть некоторые проблемы, но то, что вы сказали к ним явно не относится.
                                                  • –1
                                                    Нет проблем, все нормально, не отвлекайтесь.
                                      • 0
                                        Диагноз по аватарке?
                                        В принципе, я понимаю ваш скептицизм, но что, чёрт побери, делать с фактом «фреймворки ускоряют разработку»?
                                        • –1
                                          Какие из? Я могу сказать, что любая команда разработчиков рано или поздно придет к своему собственному фреймворку. Чужие фреймворки ускоряет начальную разработку, но не длительную поддержку продуктов в актуальном состоянии. Стоимость разработки на собственном фреймворке гораздо дешевле, чем на фреймворках сторонних производителей.
                                          • +2
                                            глупости.
                                            • –2
                                              Какой содержательный и конструктивный ответ! Браво!
                                            • 0
                                              Стоимость разработки на собственном фреймворке гораздо дешевле, чем на фреймворках сторонних производителей.
                                              Нет-нет, что вы, это вовсе не синдром NIH.
                                              • –1
                                                А при чем тут Национальный Институт Здоровья? )
                                          • –1
                                            фреймворки дополняют функционал, которого не хватает в JS. В HTML5 уже добавлены css expressions, getEleventsByClassName и т.д.
                                            • 0
                                              Фреймворк, написанный на JS не может дополнять функционал самого JS. Он может предоставлять более быстрый доступ к удобному функционалу. Но этот же функционал можно сделать и без фреймворков.

                                              CSS-expressions не дополняют и не расширяют JS, и тем более фреймворки, они затыкают те дыры, которые традиционно приходилось решать при помощи JS.
                                              • –1
                                                Конечно можно, можно и на ассемблере это сделать… просто будет ещё дольше. Просто фреймворки реализуют функционал, которого не хватает в языке. Потом за ними и стандарты подтягиваются, и браузеры.
                                                • 0
                                                  Любая функция JS реализует функционал, которого нет в JS.

                                                  Чувствую себя КО
                                        • +2
                                          Не покажете ваш код?
                                          • +1
                                            На чистом JS? А зачем?
                                            Вы хотите меня ткнуть носом в какую нибудь ошибку или некрасивость и злорадно похихикать? Смысл?
                                            • 0
                                              Боюсь так и будет.
                                              • 0
                                                Ссылка ниже) тыкайте
                                                • 0
                                                  Я как раз пролистал :-)
                                                  • 0
                                                    Но не считаю себя достаточно сведущим, чтобы оценивать :-)
                                                • –3
                                                  Боюсь, что ваше тыканье может быть осмеяно. Приведенный пример категорически запрещено писать на фреймворках.
                                                  • –2
                                                    Дело не в использовании или не использовании фреймворков, а в представленном по ссылке коде.
                                                    • 0
                                                      Для начала стоит задуматься, почему там не используются популярные фреймворки.
                                                      • 0
                                                        Если какой-то код упрощён для ускорения в ущерб понятности, он должен быть прокомментирован. Причины должны быть изложены в комментариях. Об остальном сказал TheShock.
                                                        • 0
                                                          Любые вызовы функций делают свои пенальти. Чем проще код, тем меньше пенальти на обслуживание инфраструктуры вызовов, тем выше производительность.
                                              • +1
                                                Ок, специально для активно минусующих дам ссылку на сделанную фо фан демку — lorgame.ru/sprites2.php — в самой странице код намеренно был обфусцирован, не помню уж почему) подключаемые скрипты нет.
                                                • +3
                                                  Ну вот просто оцените:
                                                  var div;
                                                  div=document.createElement("div");
                                                  div.id='spritediv'+id;
                                                  div.style.position='absolute';
                                                  div.style.overflow='hidden';
                                                  div.style.left=x-bx;
                                                  div.style.top=y-by;
                                                  div.style.width=width;
                                                  div.style.height=height;
                                                  document.body.appendChild(div);
                                                  
                                                  // =>
                                                  
                                                  $('<div/>', { id : 'spritediv' + id})
                                                  	.css({
                                                  		position : 'absolute',
                                                  		overflow : 'hidden',
                                                  		left     : x-bx,
                                                  		top      : y-by,
                                                  		width    : width,
                                                  		height   : height
                                                  	})
                                                  	.appendTo('body');
                                                  


                                                  Потом, мне не понравился этот участок. Могу объяснить, почему, но, думаю, вы и сами догадаетесь.:
                                                  function SAddSprite(name,width,height,bx,by,x,y,sx,sy,tx,ty,dir,states,state)
                                                  {
                                                     var len=sprites.length,id=sprcurid++;
                                                     sprites[len]=new Array();
                                                     sprites[len][0]=id;
                                                     sprites[len][1]=name;
                                                     sprites[len][2]=width;
                                                     sprites[len][3]=height;
                                                     sprites[len][4]=bx;
                                                     sprites[len][5]=by;
                                                     sprites[len][6]=x;
                                                     sprites[len][7]=y;
                                                     sprites[len][8]=sx;
                                                     sprites[len][9]=sy;
                                                     sprites[len][10]=tx;
                                                     sprites[len][11]=ty;
                                                     sprites[len][12]=dir;
                                                     sprites[len][13]=state;
                                                     sprites[len][14]=states[state][0];
                                                     sprites[len][15]=0;
                                                     sprites[len][16]=state;
                                                     sprites[len][17]=states;
                                                     SCreateImage(id,name,width,height,bx,by,x,y,dir,sprites[len][14]);
                                                     return id;
                                                  }
                                                  


                                                  Функция SRefreshSprites() напоминает perl. Думаю, значительного улучшения читабельности можно было бы достичь, если в SAddSprite указывать в качестве sprites[len] не массив, а объект с именованными параметрами.
                                                  Почему вы используете
                                                  var len=sprites.length;
                                                  sprites[len]=new Array();
                                                  // Вместо
                                                  sprites.push(new Array())
                                                  

                                                  Уверены, что это будет быстрее, а не медленнее?

                                                  Функция SAddSprite(name,width,height,bx,by,x,y,sx,sy,tx,ty,dir,states,state) ужасает даже больше, чем drawImage в canvasApi:
                                                  Вот вы можете сходу сказать, что значит каждый из примеров?
                                                  // Plain Javascript
                                                  ctx.drawImage(img, 30, 30, 45, 60, 15, 15, 15, 20);
                                                  // VS (LibCanvas)
                                                  ctx.drawImage({
                                                  	image : img,
                                                  	crop  : [30, 30, 45, 60],
                                                  	draw  : [15, 15, 15, 20]
                                                  });
                                                  // VS (LibCanvas)
                                                  ctx.drawImage({
                                                  	image : img,
                                                  	crop  : {
                                                  		from : [30, 30],
                                                  		size : [45, 60]
                                                  	},
                                                  	draw : {
                                                  		from : [15, 15],
                                                  		size : [15, 20]
                                                  	}
                                                  })
                                                  

                                                  Я вот до сих пор не могу запомнить порядок аргументов в оригинальной функции.

                                                  И еще. Заметно, что вы не знаете очень многих интересных особенностей Javascript. Рекомендую вам поизучать внутренности и устройство фреймворков — будете приятно удивлены.

                                                  Не обижайтесь, ничего личного. Вы ведь сами просили прокомментировать.
                                                  • +1
                                                    Благодарю за конструктивную критику.
                                                    Использование объектов возможно, но мне кажется, что массивы быстрее. Писалось конкретно для небольшой демки, поэтому тут нестрашно иметь такие страшные прототипы функций)

                                                    А вообще да, я бы не осмелился назвать себя профессиональным разработчиком на JS, опыта у меня в нем не просто меньше, а на порядки меньше чем в «основных» для меня языках — C, php. В последнее время работаю также с C#, но там тоже опыта пока не так много.
                                                    • 0
                                                      очень спорный вопрос, что быстрее. а главное — имеет ли смысл это ускорение. Видимо, вы на JS стараетесь перенести логику работы на C. На самом деле, если очень увлечся этим языком и разобратся, то вы будете в дичайшем восторге ;)
                                                      • +1
                                                        каюсь, я почти везде ее переношу (логику C) :D
                                                        это моя проблема, да.
                                                        • +1
                                                          впрочем я пока не в дичайшем, но в некотором восторге от C#, ввиду его заточенности под _быструю_ разработку и минимизацию ошибок. Писать на нем гуевые приложения — одно удовольствие.
                                                          • 0
                                                            А я вот не в востороге от js. Даже скорее меня от него тошнит. Это я к тому, что не обобщайте :)
                                                          • +3
                                                            Массивы в JS — те же объекты, по сути ) Не должно там быть заметной разницы в скорости.
                                                          • 0
                                                            Производительность приведенного вами кода будет плачевна. Да, быстрее написали, красивее вроде выглядит, но медленнее работает.
                                                            • +1
                                                              нормально работает. это не будет узким местом, особенно учитывая тот факт, что функция вызывается крайне редко.
                                                              более того, многие вещи во фреймворке оптимизированны с учётом особенностей работы языка и в итоге может оказатся, что весь код на чистом ЖС тормозит больше, чем с использованием фреймворка.
                                                              • +1
                                                                а еще абстрагированно куча проблем с кроссбраузерностью
                                                                • –3
                                                                  Вы только что нагородили таких огородов…
                                                                  Фреймворк, написанный при помощи JS не может работать быстрее нативного JS кода. Хоть вы тресните, но быстрее работать не будет.
                                                                  • +3
                                                                    var divs = document.getElementsByTagName('div');

                                                                    for (var i = 0; i < divs.length; i++) {
                                                                      console.log(div.id);
                                                                    }

                                                                    медленнее, чем

                                                                    $('div').each(function() { console.log(this.id) });

                                                                    Я к тому, что фактор кривых рук тоже не стоит упускать из внимания.
                                                                    • –4
                                                                      Бенчмарк в студию!
                                                                      • +3
                                                                        А вы сами только спрашиваете и оцениваете результат, как я понял?
                                                                        • +2
                                                                          он тут главный, он собирает факты, а потом решает, как со всем этим быть. по крайней мере, он так считает.
                                                                      • +1
                                                                        jQuery против нативного JS. 10000 элементов.

                                                                        33 против 17 в FF 3.6
                                                                        8 против 8 в Хроме 7
                                                                        17 против 10 в Опере 10.6

                                                                        Увы, но JQ не быстрее, как бы вам не хотелось.
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                          • +1
                                                                            Я вам привел цифры, которые опровергают постулат, что на jQ можно написать код, который будет работать быстрее нативного JS. Ваши придирки к цифрам кроме как придирок я воспринимать не могу.
                                                                            • 0
                                                                              Зато на jQuery можно писать код быстрее, чем на нативном JS. Если есть слишком узкие места — их всегда можно перевести на нативный JS для ускорения.
                                                                              • 0
                                                                                Первый раз писать — быстрее. Поддерживать и развивать — терпения вам и внимательности.
                                                                      • +4
                                                                        конечно, на искуственных тестах типа document.getElementById('test') vs $('#test') JQuery проиграет. Но, допустим, как на счёт теста — кроссбраузерно выбрать все элементы с классом «testClass» внутри элементов "<ul>".
                                                                        На JQuery это будет приблизительно так:
                                                                        $('ul .testClass')
                                                                        

                                                                        допустим, на нашем фреймворке это будет так (для ускорения работы уберем парсер запроса):
                                                                        dom.tagName('ul').className('testClass')
                                                                        

                                                                        Вы уверены, что более нативная реализация без парсера будет быстрее? Учтёте в большинстве современных браузерах метод getElementsByClassName? Или и в ИЕ и в Хроме будете перебирать все элементы? Знаете, что во многих браузерах движок ксс-селекторов есть нативно и вполне возможно, что через селектор будет быстрее, чем через два метода? конечно, на всяких низкоуровневых атомных тестах натив будет быстрее (что не факт).

                                                                        но фреймворки так заоптимизированны, что кроссбраузерное решение практически невозможно сделать более быстрым, чем в, например, JQuery.
                                                                        • –5
                                                                          Патетика чистой воды. JQ имеет обвязку, которая создает деградацию по скорости. Решив задачу методами JQ, но не сделав всю его обвязку, можно получить прирост по скорости.
                                                                          • 0
                                                                            Судя по минусующим, тут собрались мегагуру, которые верят в сверх-чудо оптимизации фреймворков… :D
                                                                            • –1
                                                                              Исходники jQuery доступны публично, поэтому ничто не мешает ткнуть пальцем в эту самую «Тормозную Обвязку». И утереть нос присутствующим. Иначе ваше утверждение выглядит довольно голословно.
                                                                              • 0
                                                                                Оно не может быть голословным. jQuery библиотека, написанная на самом javascript. А это значит, что и без её использования можно всегда как минимум повторить её быстродействие, а то и превзойти его.
                                                                              • +1
                                                                                Боюсь всё проще и плачевней. Люди не представляют, как оно работает на более низком уровне, чем js, потому вполне логичные слова, которые как-то даже глупо оспаривать, подвергаются остракизму.
                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                        • 0
                                                                          Нет. Просто одно время оптимизацией скорости пришлось заниматься очень плотно.
                                                                      • +3
                                                                        function SAddSprite(name,width,height,bx,by,x,y,sx,sy,tx,ty,dir,states,state)
                                                                        {


                                                                        Согласен, это чудовищно.

                                                                        К тому же что мешало использовать волшебный массив arguments?

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

                                                                        function SAddSprite(params) {

                                                                        }
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                  • –3
                                                                    Вот вы русский язык не знаете, пишете с ошибками, а другим толкуете о каком-то знании/незнании каких-то-там фреймворков. В чужом глазу…
                                                                    • 0
                                                                      Указывать на орфографические ошибки оппоненту — дурной тон, тем более, что у меня они хоть и проскакивают, но встречаются крайне редко.
                                                                      Я русский язык в школе не учил и считаю, что мой уровень знания иностранного для меня языка достаточно высок.
                                                                      Напишите пару предложений на украинском, посмотрим, какой вы грамотный.
                                                                      • +2
                                                                        Этим комментарием я НЕ хотел сказать: «Вы говно, потому что неграмотно пишете по-русски». Я и сам частенько позволяю себе ошибки/опечатки, дело не в этом.

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

                                                                        (А уровень знания языка у вас, без сомнения, высок даже для коренного жителя России, без сомнения. И это не сарказм.)
                                                                        • 0
                                                                          Спасибо.

                                                                          Ну так о чём речь? Я же не говорю человеку, что не надо программировать на Javascript, раз он не владеет в совершенстве фреймворками. Я утверждаю, что отрицать фреймворки нужно только разобравшись в них. Особенно учитывая высокое качество фреймворков на Джаваскрипт.
                                                                          • 0
                                                                            Речь о «каждый дрочит как он хочет», вы же не на работу его принимаете:)
                                                                            • 0
                                                                              почитал ваш профиль, желание спорить окончательно отпало:)
                                                                              • 0
                                                                                в негативном или позитивном плане?
                                                                                • 0
                                                                                  В позитивном, конечно. Куча статей про node.js, полезных статей. Так держать!
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                              • +1
                                                                Эх, как бы хотел писать на фреймворках… Аж слезы из глаз текут… Но к сожалению, на JS я пишу не для десктопа, а для embedded (конкретно — для IPTV-приставок), где зачастую уже почти стандарт де-факто — ядро Линукс + браузер (Опера или какой-нибудь ANT Galio). Производительность у приставки в среднем в несколько десятков раз меньше, чем у десктопа, например на D-Link DIB-120, которую ковыряю сейчас, redraw элемента на экране занимает порядка 200 мс, а reflow — не меньше 500 мс. И все остальное в том же духе.
                                                                В таких условиях большинство тестовых страниц с бенчмарками для проверки работы фреймворков (что jquery, что mootools, о монтруозном prototype я и не говорю) вообще не завершается в обозримое время… Поэтому все ручками, ручками. Учитывая, что на JS надо не просто чего-то делать, а рисовать более-менее полноценный пользовательский интерфейс (не ExtJS, конечно, но все-таки), все становится еще интереснее. :-)
                                                                • 0
                                                                  это, наверное, очень интересно, честно.
                                                                  и как справляетесь? почему бы не написать топик об этом?
                                                                  • +5
                                                                    Честно говоря, не уверен, что это было бы интересно массовому хабраюзеру. Да и о чем конкретно писать? JS — он и в Африке JS. Есть API от производителя железа — в браузере несколько дополнительных встроенных объектов, через которые можно управлять оборудованием. Основное время уходит вообще не на кодинг, а именно на обход глюков/особенностей как оборудования, так и встраиваемой реализации браузера. Плюс в том, что не нужно поддерживать тот же IE (поддержка которого как раз и занимает немалую часть во фреймворках): ANT Galio/Fresco работает на движке Firefox, а Опера — она и есть Опера (собственно, она сейчас всех плавно с этого рынка и выдавливает — вполне заслуженно, надо сказать). Так что, например, создавать GUI можно достаточно легко на чистом CSS, т.к. поддерживаются и полупрозрачные png, и всякие :before, :after и не нужно думать о костылях для того же IE6… Короче, разработка идет под конкретный браузер по сути, и не нужно ждать, что окажешься во «враждебной» и незнакомой среде.

                                                                    Но на десктопе обычно не нужно задумываться о тех же redraw/reflow, а тут это уже важно, т.к., например, применение к диалоговому окошку класса «hide» внутри которого написано «display: none;» и применение непосредственно стиля «display: none;» — это две большие разницы, т.к. смена класса однозначно вызывает именно reflow и отрабатывается раза в три медленнее, чем изменение одного свойства стиля. С другой стороны, иногда бывает лучше спрятать то же окошко под черной фоновой «заглушкой» и показывать его туда-сюда через изменение z-index'а…
                                                                    Вся работа с DOM (особенно изменение) происходит очень медленно, поэтому всякие getElementById практически не используются (максимум — один раз, чтобы получить сам объект), а вся работа — только с объектами. Аналогично innerHTML — быстрее будет создать элементы через createElement/createTextNode, собрать из них что надо и один раз вставить, а чтобы потом менять — лучше лишний раз опять же не дергать DOM, а только заменить текстовое содержимое элемента, а временно ненужный — спрятать.
                                                                    Мыши нет, а пульт ДУ генерирует события клавиатуры со специальными кодами клавиш. Нужно постоянно следить за фокусом, за активным элементом и так далее. AJAX в виде XHR по сути не используется (либо вообще запрещен, как, например, в приставках Telsey, либо не работает по причине несовпадения доменов, если страничка грузится не по сети, а из внутреннего флеша приставки), поэтому остается только JSONP. Canvas есть и даже работает, но настолько медленно, что моя попытка сделать какой-нибудь скинсейвер для телевизора — не увенчалась успехом. :-)

                                                                    И так далее, и тому подобное. За пределами данной узкой сферы вся эта информация слабо пригодна, разве что иногда бывают некие полезные мелочи, слабо освещенные в интернете — типа, как точно проверить, что подключенный динамически CSS-файл полностью загружен и обработан, или как написать текстовое поле с вводом текста как на мобильниках через кнопки с цифрами и весь сопутствующий функционал…

                                                                    Вот такие дела. :-)
                                                                    • +1
                                                                      Очень интересно.
                                                                      Массовому хабраюзеру интересны новинки от Эппл и проблемы в России, но что уж тут поделаешь?
                                                                      уверен, если бы написали подробненько, с картинками и нюансами — слушателя нашли бы. я бы с удовольствием почитал.
                                                                      • +1
                                                                        1) Ну, помимо прочего, я в свободное от остальных вещей время пытаюсь на этом еще и делать свой маленький бизнес. :-) Решения IPTV от больших вендоров стоят по $100 тыс. за инсталляцию. Я вендор небольшой, а на территории РФ/Украины/Казахстана сейчас много мелких провайдеров, которые вводят IPTV/VOD и которым нужно дешевый и простой способ вывести свой мультикаст на телевизор. В этом направлении и работаю. :-) Рассказывать подробно всю подноготную — это рыть самому себе яму. :-) Так что, если есть конкретные вопросы — пишите лучше в личку/аську/скайп/почту — отвечу лично.

                                                                        2) Ну да, что-то типа фреймворка писал, конечно… Не совсем фреймворка — я не настолько хорошего о себе мнения… Просто для всяких мелких вещей немного расширил прототипы, сделал HAL, чтобы легко было портировать на разные приставки (API доступа к оборудованию у всех же разное) ну и что-то типа мини-GUI-библиотечки с основными элементами типа окон, пунктов меню, кнопок и так далее — оптимизированное для обозначенных целей и чтобы можно было достаточно быстро интерфейс рисовать…
                                                                      • 0
                                                                        кстати, свой фреймворк для этих дел писали?
                                                              • –1
                                                                не хватает документации просто которая есть на основном сайте… маловато примеров кода, но язык отличный имхо… изучение эрланга перевернуло для меня много в мире программирования…
                                                                вообще я задумываюсь о том как бы запустить внутри эрланга мой любимый (на текущий момент) php и получить все плюшки работы с событиями которые там есть…
                                                                • +1
                                                                  > изучение эрланга перевернуло для меня много в мире программирования…
                                                                  аналогично, функциональное программирование (и Эрланг в частности) это как поворот сознания на 90° — начинаешь видеть гораздо больше, и старые проблемы тоже видятся шире.
                                                                  Но сам язык будет жестковат для написания страничек, ему нужен какой-нибудь очень удобный скриптовой «компаньон»: php, js, особые эстеты вот lua вспоминают :)
                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                    • +2
                                                                      Думаю есть. Взять из каждой системы лучшее.
                                                                      Сам подумывал над чем-то подобным, но писать некогда.
                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                        • 0
                                                                          Если на одной машине, то общаться можно через unix domain socket (в просторечьи — pipe), в никсах с ними нормально.

                                                                          Я не великий спец по сервисам эрланга :), но каких-то особых проблем возникнуть не должно. Можно через вызов процесса (но тут это будет слишком медленно), пайпы, С-шный код можно скомпилить и вызывать внутри вирт. машины.
                                                                          • +3
                                                                            unix domain socket (в просторечьи — pipe)

                                                                            Что-ж вы, голубчик, юникс-сокеты и пайпы путаете?
                                                                      • +1
                                                                        Угу, и несчастному программеру нужно изучить и Erlang и Node… Ну и вообще не понятно что на эрланг переносит а что на ноде.

                                                                        На самом деле в Erlang вполне реально писать веб-приложения. Есть реализация Django шаблонов, есть прекраснейший на мой взгляд вебсервер MochiWeb, есть даже CMS на эрланге Zotonic… Так что есть над чем подумать.
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                        • +1
                                                                          Так ведь часто объединяют Node.JS + Riak, Node.JS + CouchDB, Node.JS + RabbitMQ.
                                                                      • +1
                                                                        У эрланга фишка в микропроцессах, которых можно миллионами создавать. А если в каждом из миллиона микропроцессов эрланга запустить интерпретатор PHP — сами понимаете что будет.

                                                                        Ну и в эрланге не приветствуется написание модулей на других языках. Там даже драйверы для MySQL и Postgre на самом эрланге написаны
                                                                        • 0
                                                                          понимаю, но можно запустить 1 процесс который будет держать php процесс который будет выполнять полученный php код (или название пользовательской функции, не важно что он там будет выполнять) (ну или через fcgi — но реализация сложнее) и выплевывать его результат в эрланг. это даст возможность легче «вьехать» в мир эрланга, не лишаясь так сказать привычных удобств…
                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                        • +1
                                                                          Вторая должна быть удобнее.
                                                                      • +3
                                                                        Что не пост про Node.js, то от «задумки» до «революции»)) Лет 10 назад около 30% веб-серверов работало на этой «революции». Так что это простое эволюционное развитие по спирали. Да сейчас JS более популярен, более развит, больше фреймворков и V8 лучше. Но хоть бы кто-то попробовал проанализировать, почему если JS на серверах не прижился тогда, он должен прижиться сейчас. Что мешало тогда, что изменилось сейчас и т.п.
                                                                        • +2
                                                                          Извините, я в общем то не в курсе, поэтому не было возможности проанализировать. О каких разработках идет речь? Ну и на вскидку могу вам выдать такой аргумент: 10 лет назад не было эффективных реализаций исполняющей среды и JS был еще довольно молодым языком (как следствие — отсутствие наработанных best practices и толковых специалистов).
                                                                          • 0
                                                                            Было или не было эффективных реализаций исполняющей среды нам трудно уже проверить. Netscape имел сервер-сайд JS в своих веб-серверах.
                                                                            • +2
                                                                              это было совсем-совсем не то. никакого non-blocking i/o там не было, документы выводились через document.write(). вообщем, полный отстой :)
                                                                          • +2
                                                                            Посмотрите доклады Крокфорда про Javascript www.yuiblog.com/crockford/. Во второй главе он достаточно подробно отвечает на ваш вопрос =)
                                                                          • +4
                                                                            >Если у вас, допустим, двухядерный процессор, то единственный способ по полной использовать его аппаратные ресурсы с Node.js — это запустить два экземпляра сервера (по одному на каждое ядро) и использовать reverse proxy (например, тот же nginx) для балансировки нагрузки между ними.

                                                                            Вполне все разруливается через socketpair + child_process.spawn с передачей одного сокета из пары в качестве stdin (лучше, конечно, добавить в node.js fork() — но пока его там нет, вполне себе выход).

                                                                            Как то так:

                                                                            var socketpair = process.binding('net').socketpair();

                                                                            var child = require(«child_process»).spawn(
                                                                            process.argv[0],
                                                                            [process.argv[1], '-/'],
                                                                            undefined,
                                                                            [socketpair[1], -1, -1]
                                                                            );

                                                                            child.stdin = new require('net').Stream(socketpair[0], 'unix');


                                                                            Здесь "-/" — служебный аргумент, означающий «работать как child».

                                                                            В самом чайлде создаем Stream для stdin, и с ним уже делаем что хотим — например, передаем в качестве аргумента (http.createServer()).listenFd.
                                                                            • +1
                                                                              Может проще Spark? Запускает сразу нужно кол-во процессов ноды.
                                                                              • +1
                                                                                Посмотрел, там так же сделано. Не знал о таком, изобрел велосипед. Ну, зато разобрался :)
                                                                              • +3
                                                                                Я все таки жду fork (т.к. люблю теплые ламповые нативные решения =)), т.к. Райна обещал в скором времени. Но тем не менее, спасибо вам за хинт.
                                                                              • +1
                                                                                А что будет если «обычное» веб приложение запустить на nginx? Он будет работать как апач генерируя каждую страничку и остальные будут его ждать, никаких плюшек от него получено не будет?
                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                  • +1
                                                                                    > единственное немного раздражает вложенные функции — callback в callback в callback'е

                                                                                    Решил вот так (mootools required, но спокойно без него переписывается). Пример использования — как-то так.

                                                                                    Этакий немного вывернутый chain of responsibility.
                                                                                    • +4
                                                                                      Ох уж это слово-которое-не-произносят-вслух.

                                                                                      Ссылки:

                                                                                      1. pastebin.com/twb4Zghs
                                                                                      2. pastebin.com/DtvHfrhD
                                                                                    • +4
                                                                                      callback в callback в callback'е — это известный анти-паттерн JS

                                                                                      JSDeferred — одно из решений проблемы
                                                                                      cho45.stfuawsc.com/jsdeferred/doc/intro.en.html
                                                                                    • 0
                                                                                      654 request per second.
                                                                                      Тот же синтетический тест без базы — ~3000 RPM :)
                                                                                      Без базы медленнее, выходит? ;)
                                                                                      • 0
                                                                                        Нет, быстрее.
                                                                                        • +2
                                                                                          Адмирал очевидность сообщает, что rpm — это requests per minute и 3000 rpm это 500 requests per second, что меньше, чем 654.

                                                                                          Генералисимус подсказывает, что чем меньше запросов в секунду обрабатывается, тем медленнее считается сервис.
                                                                                          • 0
                                                                                            Судя по цифрам, там везде request per second :-)
                                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                                    • +3
                                                                                      Огромное спасибо автору за статью, хотелось бы еще увидеть примеры работы с node.js
                                                                                    • +2
                                                                                      Ваня, респект Марианне за такие красивые картинки!
                                                                                      • +4
                                                                                        Plurk (ссылка на него дана в конце статьи, «уже имеются прецеденты») недавно переехал назад на Java NIO — amix.dk/blog/post/19577#Is-node-js-best-for-Comet
                                                                                        • +3
                                                                                          Давайте покажу еще один момент который node.js(Twisted,phpDaemon и другие, нужный подчеркнуть) решают более менее походя.

                                                                                          Вам надо — показать шапку сайта, показать список топиков, показать последние топики, и картинки аватар. С кешированием.
                                                                                          Как это работает — запрос в кеш -> в бд ->запись в кеш -> отображение -> next
                                                                                          если каждый пункт занимает секунду — это займет 4 секунды. N чтений из кеша, N запросов в бд и N записей в кеш(образно)

                                                                                          Подход номер 1 — работать пачкой — мы сделаем 1 запрос в кеш, N запросов в БД и 1 запись в кеш.
                                                                                          Это, будем считать, займет 3 секунды.
                                                                                          Первое и последнее — пачкой. Запросы в бд очень сложно правильно «запачковать»

                                                                                          Теперь давайте скажем что у нас асинхнонный(ивентный) запрос что в кеш, что в бд.
                                                                                          Если кто не понимает — мы отправляем запрос, говоря что надо сделать при ответе и идем ДАЛЬШЕ.
                                                                                          Приступая к след пункту.
                                                                                          В данном случае работает правило крайсерской скорости — все едет со скоростью самого медленного.
                                                                                          И запрос будет отработан за 1 секунду. В том числе, технически, генерацию разных блоков можно выполнять на разных процах или машинах.
                                                                                          Ну а если на хвост армаде сядут подлодки — можно отдать клиенту 3 блока из 4х, а последний дотянуть в клиент уже после загрузки( чисто технически — влет )

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

                                                                                          И из «ничего» ускоряем генерацию во столько раз, насколько блоков( узлов, в общем ранг ноды дерева ) мы раздербанили генерацию кода.
                                                                                          +малек доп расходов и идеалогическое требование к железу дать возможность выдержать паралельные запросы — ведь если у вашей БД только один проц, а к ней приходят запросы не последовательно а, прям таки, обновременно — она обидиться.

                                                                                          Все это также делается и без разных демонических нод, как говориться — кому как нравиться(правда два года назад я описал свои мысли малек более сумбурно)
                                                                                          • +3
                                                                                            Асинхронность есть и в других ЯП — EventMachine для Ruby и Twisted для Python. Так что основной фишкой node.js всё так же и остаётся лишь программирование на JS.
                                                                                            • +2
                                                                                              Основной фишкой node.js является отсутствие возможности писать код с синхронным вводом/выводом, причем писать на языке знакомом и PHP, и Python, и Ruby, и ASP и вообще любому веб-разработчику.
                                                                                              • 0
                                                                                                Ну опять же, плюсы в том, что это JS — lingua franca Веба. Хотя можно заметить, что JS — довольно жестокий язык и лучше его украсить хотя бы синтаксисом Coffeescript.
                                                                                                • +1
                                                                                                  да, но мне кажется, что большая часть разработчиков программирует на JS, как на паскале (без прототипов, коллбэков и т.д.). Мало кто действительно умеет писать умный JS
                                                                                                  • +1
                                                                                                    Да, есть такое :). Плюс люди программирую на JS не потому, что любят этот язык, а потому что ничего другое в браузере не работает. После Ruby немного злишься на странности перекосы JS (хотя бы отсутствие foreach, нормального, быстрого, без-лишнего-кода-для-IE ).
                                                                                                    • +1
                                                                                                      ну, на основе JS есть и экзотические варианты — вроде ru.wikipedia.org/wiki/Objective-J :)

                                                                                                      фанатам Objective-C должно нравится.

                                                                                                      вообще жаль, что cappuccino.org/ была куплена Моторолой, а не Эппл. По-моему, очень хороший проект

                                                                                                      (но я сваливаюсь в оффтопик)
                                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                                              • +1
                                                                                                Ну да, опять же JS. V8 — отличный интерпретатор, я слышал он работает в 3 раза быстрее Python. Но потребление ресурсов не отличается на порядок:
                                                                                                1. Интерпретатор Руби и Питона кушают больше, но основная потеря — это данные, так что дополнительные 10 МБ не масштабируются при росте данных.
                                                                                                2. Скорость вычислений в JS больше, но мы все знаем, что основное время в вебе мы просто ждём данных от базы, поэтому, например, применение более быстрой [чем JS] Java не даст существенного роста производительности.
                                                                                                • +1
                                                                                                  Хотя да, я согласен, что V8 — отличная ВМ, мой комментарий был больше посвящён тому, что async — это не фишка node.js — async есть уже практически в любой быстро развивающейся платформе. И разница между async на разных платформах упирается чисто с разницу между ЯП и качеством ВМ.
                                                                                                  • +1
                                                                                                    async есть в платформах которым уже 10 лет, вот например ASP.NET…
                                                                                                    • +1
                                                                                                      Можно более подробно. Я понимаю, что async можно сделать руками на любой платформе, но интересно, зачем идея неблокирующего API была нужна 10 лет назад и как она реализовалась средствами первых C#, где нельзя было коротко объявить callback (максимум — создавать анонимный класс, реализующий какой-то интерфейс).
                                                                                                      • 0
                                                                                                        IHttpAsyncHandler — это асинхронная работа с HTTP запросами. Весь BCL содержит асинхронные, неблочащие методы Begin/End XXXX для IO, доступа к базам данных, короч для всего. Для сгенеренного юзерского кода (например веб сервисы) тоже есть асинхронные пары. Можно почитать больше про IAsyncResult.

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

                                                                                                        Ну а на текущий момент в C# появилось ключевое слово async. Там уже можно писать аинхронный, неблочащий код ввиде нормального синхронного кода. Без всяких уродских колбеков. ( неплохое описание blog.functionalfun.net/2010/10/c-50-asynchronous-revolution.html ).
                                                                                                        • 0
                                                                                                          Неплохо. Но справедливости ради, скажу, что в Ruby это тоже есть, при этом без всякой модификации языка — гибкости стандартного Ruby 1.9 более чем достаточно, чтобы реализовать аналог await: https://github.com/brainopia/em-easy
                                                                                                            • 0
                                                                                                              Я знаю про раби. Но мы же щас про ASP.NET говорим. Если уже прескакивать на другие языки то стоит упомянуть F#. Там такой код изначально можно было делать средствами языка (Async Workflow — это обычный computation expression). Вопрос наверное больше в фреймворке, а не языке. Правда же класно что обычном .NET async/non blocking API реализовано уже 10 лет?
                                                                                                              • 0
                                                                                                                Да, это было весьма дальновидно.