Когда речь идет о реализации некоторого встроенного средства неблокирующим образом, в первую очередь следует обратить внимание на 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