Я экспериментирую с потоком JSON через HTTP с Oboe.js, MongoDB и Express.js.JSON потоковая передача с Oboe.js, MongoDB и Express.js
Дело в том, чтобы сделать запрос в MongoDB
(MongoDB родной диск Node.js в), трубы его (массив JavaScript) для Express.js
и разобрать его в браузере с Oboe.js
.
Тесты, которые я сравнивал с streaming
по сравнению с blocking
как на стороне сервера MongoDB, так и на JSON-анализе на стороне клиента.
Вот исходный код для двух эталонных тестов. first number
- это количество миллисекунд для 1000 queries
из 100 items
(pagination) в 10 million documents collection
и second number
между скобками, представляет собой количество миллисекунд до того, как проанализирован самый первый элемент в массиве результатов MongoDB.
Потоковый тест на стороне сервера:
// Oboe.js - 20238 (16.887)
// Native - 16703 (16.69)
collection
.find()
.skip(+req.query.offset)
.limit(+req.query.limit)
.stream()
.pipe(JSONStream.stringify())
.pipe(res);
Блокирующий тест на стороне сервера:
// Oboe.js - 17418 (14.267)
// Native - 13706 (13.698)
collection
.find()
.skip(+req.query.offset)
.limit(+req.query.limit)
.toArray(function (e, docs) {
res.json(docs);
});
Эти результаты действительно удивило меня, потому что я бы подумал, что:
Streaming
будет быстрее, чемblocking
раз за разом.Oboe.js
будет быстрее проанализировать весь массив JSON по сравнению с нативным методомJSON.parse
.Oboe.js
будет быстрее проанализировать первый элемент массива по сравнению с нативным методомJSON.parse
.
У кого-нибудь есть объяснение? Что я делаю неправильно?
Вот исходный код для двух клиентских тестов.
Потоковый тест на стороне клиента:
var limit = 100;
var max = 1000;
var oboeFirstTimes = [];
var oboeStart = Date.now();
function paginate (i, offset, limit) {
if (i === max) {
console.log('> OBOE.js time:', (Date.now() - oboeStart));
console.log('> OBOE.js avg. first time:', (
oboeFirstTimes.reduce(function (total, time) {
return total + time;
}, 0)/max
));
return true;
}
var parseStart = Date.now();
var first = true;
oboe('/api/spdy-stream?offset=' + offset + '&limit=' + limit)
.node('![*]', function() {
if (first) {
first = false;
oboeFirstTimes.push(Date.now() - parseStart);
}
})
.done(function() {
paginate(i + 1, offset + limit, limit);
});
}
paginate(0, 0, limit);
Блокирующий тест на стороне клиента:
var limit = 100;
var max = 1000;
var nativeFirstTimes = [];
var nativeStart = Date.now();
function paginate (i, offset, limit) {
if (i === max) {
console.log('> NATIVE time:', (Date.now() - nativeStart));
console.log('> NATIVE avg. first time:', (
nativeFirstTimes.reduce(function (total, time) {
return total + time;
}, 0)/max
));
return true;
}
var parseStart = Date.now();
var first = true;
var req = new XMLHttpRequest();
req.open('GET', '/api/spdy-stream?offset=' + offset + '&limit=' + limit, true);
req.onload = function() {
var json = JSON.parse(req.responseText);
json.forEach(function() {
if (first) {
first = false;
nativeFirstTimes.push(Date.now() - parseStart);
}
});
paginate(i + 1, offset + limit, limit);
};
req.send();
}
paginate(0, 0, limit);
Заранее спасибо!