![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Задачка с эмуляцией JS-энджина CouchDB внутри моей волшебной библиотечки решилась в одно соображение. Там суть задачи – воссоздание для JS-функции довольно необычного scope, такого же, как внутри CouchDB. Сложность в том, что часть этого scope – это «системные» функции CouchDB, а часть – итераторы, зависящие от параметров конкретного запроса и результата работы map-функции.
«В лоб» задача решается просто – в каждом запросе к reduce делаем кусок исходника со всеми этими функциями и превращаем это все в исполняемый код рефлектором. Это очень просто, но совсем плохо по скорости и памяти, да и вообще довольно стрёмно. Первый же подход к снаряду показал, что это тупик – это примерно полгода назад было, и я задачку отложил.
А потом я как-то вспомнил про curried constructor в Scala. Сам по себе аналог в js никак специально не называется, но мне подумалось, что если этот концепт немного дополнить, то выходит как раз нужный мне функционал.
В результате получилось, что на каждую reduce-функцию у меня есть наполовину инстанцированный конструктор, в некотором смысле sсope-полуфабрикат. При каждом запросе reduce клиентом я этот полуфабрикат инжектирую итераторы, зависимые от параметров запроса, и исполняю. Такие конструкции V8 прекрасно оптимизирует – сама reduce-функция получается инстанцированной однократно, вызывается часто и оптимизируется в этой связи компилятором по-полной.
Выложил вчера на гитхаб, а сегодня ночью тесты гонял. Летает )
«В лоб» задача решается просто – в каждом запросе к reduce делаем кусок исходника со всеми этими функциями и превращаем это все в исполняемый код рефлектором. Это очень просто, но совсем плохо по скорости и памяти, да и вообще довольно стрёмно. Первый же подход к снаряду показал, что это тупик – это примерно полгода назад было, и я задачку отложил.
А потом я как-то вспомнил про curried constructor в Scala. Сам по себе аналог в js никак специально не называется, но мне подумалось, что если этот концепт немного дополнить, то выходит как раз нужный мне функционал.
В результате получилось, что на каждую reduce-функцию у меня есть наполовину инстанцированный конструктор, в некотором смысле sсope-полуфабрикат. При каждом запросе reduce клиентом я этот полуфабрикат инжектирую итераторы, зависимые от параметров запроса, и исполняю. Такие конструкции V8 прекрасно оптимизирует – сама reduce-функция получается инстанцированной однократно, вызывается часто и оптимизируется в этой связи компилятором по-полной.
Выложил вчера на гитхаб, а сегодня ночью тесты гонял. Летает )