Уменьшена пропускная способность именованного канала (fifo) с потребителем nodejs - PullRequest
0 голосов
/ 17 октября 2018

Я пытаюсь использовать именованный канал для передачи потока изображений из процесса Python в процесс nodejs, в идеале со скоростью 60 кадров в секунду для изображений размером 1 мегабайт.Пропускная способность, которую я получаю, составляет всего около 25 кадров в секунду.Я был удивлен, что это было так медленно, поэтому я протестировал перенос кадров из одного процесса python во второй процесс python.Мне удалось достичь скорости передачи около 500 кадров в секунду.Я новичок в nodejs, поэтому могу легко что-то упустить, но я думал, что скорость будет сравнима.Почему моя программа nodejs намного медленнее использует данные из именованного канала?

Я использую поток для чтения с узла nodejs и читаю событие 'readable':

reader.js

const fs = require('fs');

fifo = fs.createReadStream(process.argv[2], { highWaterMark: 4*2, });

let t0 = Date.now();
fifo.on('readable', () => {
  const chunk = fifo.read(1024 ** 2);
  if (chunk !== null) {
    let t1 = Date.now();
    process.stdout.write(`${(t1 - t0)/1000.}s, ${1000./(t1 - t0)}fps\n`);
    t0 = t1;
  }

});

fifo.on('end', () => {
  process.stdout.write('end');
});

Мой производитель Python просто записывает байты в именованный канал, как если бы это был файл:

provider.py

import sys
import numpy as np

im = np.random.randint(0, 255, size=(1024, 1024)).astype(np.uint8).ravel()

with open(sys.argv[1], 'wb') as f:
    while True:
        f.write(im.tobytes())
        f.flush()

Читатель Python просто читает из именованного каналатруба, как если бы это был файл:

reader.py

import sys
import numpy as np
import time

l = 1024 ** 2
t0 = time.time()
with open(sys.argv[1], 'rb') as f:
    while True:
        im = f.read(l)
        t1 = time.time()
        print('{}s, {}fps'.format(t1 - t0, 1/(t1 - t0)))
        t0 = t1

Чтобы проверить передачу с python на javascript:

mkfifo /tmp/video; python producer.py /tmp/video & node reader.js /tmp/video

И проверить с python на pythonпередача:

mkfifo /tmp/video; python producer.py /tmp/video & python reader.py /tmp/video

Я использую Mac (ОС 10.13.6, Intel Core i5 с частотой 2,7 ГГц).Python 3.7.0.Узел v8.9.1. *1024*

Я также пытался использовать событие «data» для считывателя nodejs, и оно было таким же медленным.Могут ли события nodejs иметь достаточные накладные расходы, чтобы замедлить чтение?

Любые идеи будут высоко оценены!

1 Ответ

0 голосов
/ 17 октября 2018

Это выглядит как ограничение macOS.

Насколько я знаю, именованные каналы в macOS имеют фиксированный размер буфера, который не может быть изменен (где-то вдоль строк 16 или 64 КБ), тогда какв Linux размер может быть изменен до 1 м.

Я тестировал, и производительность reader.js в Linux намного лучше, примерно на уровне reader.py.

Быстрый тест предполагаетчто запуск процесса Python как дочернего процесса значительно повышает скорость чтения:

// reader.js
const { spawn } = require('child_process');
const fifo = spawn('python', ['producer.py']).stdout; // (instead of fs.createReadStream(...))
...

// producer.py
...
f = sys.stdout.buffer
while True:
    f.write(im.tobytes())
    f.flush()
...