Как мне разработать и реализовать модуль отображения неблокирующей памяти для node.js

Для node.js существует модуль mmap: https://github.com/bnoordhuis/node-mmap/

Как отмечает автор Ben Noordhuis, доступ к отображаемой памяти может блокироваться, поэтому он больше не рекомендует его и прекратил использовать.

Итак, мне интересно, как мне разработать модуль отображения неблокирующей памяти для node.js? Заправка нитей, волокна,?

Очевидно, что это рядом поднимает вопрос, будет ли поток в node.js происходить где-то еще, а не в обработчике запросов.


person citykid    schedule 19.05.2014    source источник


Ответы (1)


Когда речь идет о реализации некоторого встроенного средства неблокирующим образом, в первую очередь следует обратить внимание на libuv . Это то, как базовые модули узла взаимодействуют с базовой платформой. Особый интерес представляет API рабочей очереди.

Если мы быстро взглянем на источник node-mmap, мы видим, что на самом деле это очень просто. Он вызывает mmap и возвращает узел Buffer, который обертывает отображенную область памяти.

Чтение этого Buffer - вот что приводит к тому, что ОС выполняет ввод-вывод. Поскольку это обязательно произойдет в потоке JS, мы в конечном итоге блокируем поток JS с помощью дискового ввода-вывода.

Вместо того, чтобы возвращать Buffer, который разрешает прямой доступ JS к отображаемой памяти, вы должны написать класс-оболочку на C ++, который маршалирует операции чтения и записи через рабочую очередь. Таким образом, дисковый ввод-вывод будет происходить в отдельном потоке.

В JS вы бы использовали это примерно так:

fs.open('/path/to/file', 'r', function(err, fd) {
    fs.fstat(fd, function(err, stats) {
        var mapped = mmap.map(stats.size, mmap.PROT_READ, mmap.MAP_SHARED, fd, 0);
        mapped.read(start, len, function(err, data) {
            // ...
        });
    });
});

А в C функция read создаст рабочий запрос libuv и поставит его в очередь работы. Затем рабочая функция C будет читать отображаемый диапазон памяти (на основе спецификаций вызывающего), что может вызвать дисковый ввод-вывод, но это безопасно, потому что это происходит в отдельном потоке.

Что будет дальше, интересно. Безопасным подходом для рабочего будет alloc новый кусок памяти и memcpy из отображаемой памяти. Затем рабочий передает указатель на копию, и обратный вызов C помещает его в Buffer для возврата в JS-land.

Вы также можете попробовать прочитать диапазон (чтобы любой необходимый ввод-вывод происходил в рабочем потоке), но на самом деле ничего не делать с данными, а затем с помощью обратного вызова C просто оберните диапазон отображаемой памяти в Buffer. Теоретически части файла, которые прочитал рабочий, останутся в ОЗУ, поэтому доступ к этой части отображаемой памяти не будет заблокирован. Однако, честно говоря, я недостаточно знаю отображаемую память, чтобы сказать, может ли это вас укусить.


Наконец, я сомневаюсь, что это действительно обеспечит дополнительную производительность по сравнению с обычными fs методами узла. Я бы пошел по этому пути, только если бы делал что-то, что действительно оправдывает использование mmap.

person josh3736    schedule 19.05.2014