【问题标题】:JSON streaming with Oboe.js, MongoDB and Express.js使用 Oboe.js、MongoDB 和 Express.js 进行 JSON 流式传输
【发布时间】:2014-11-01 00:00:47
【问题描述】:

我正在尝试使用 Oboe.js、MongoDB 和 Express.js 通过 HTTP 流式传输 JSON。

重点是在MongoDB(Node.js 的 mongodb 原生驱动器)中进行查询,将它(一个 JavaScript 数组)通过管道传输到 Express.js,然后在浏览器中使用 Oboe.js 解析它。

我在 MongoDB 查询服务器端和客户端的 JSON 解析中比较了 streamingblocking 的基准。

这是两个基准测试的源代码。 first number100 items(分页)中10 million documents collection1000 queries 的毫秒数,括号之间的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);
});

这些结果真的让我感到惊讶,因为我会认为:

  1. Streaming 每次都会比 blocking 快。
  2. 与原生 JSON.parse 方法相比,Oboe.js 解析整个 JSON 数组会更快。
  3. 与原生 JSON.parse 方法相比,Oboe.js 解析数组中的第一个元素会更快。

有人解释一下吗? 我做错了什么?

这也是两个客户端基准测试的源代码。

流式基准测试客户端:

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);

提前致谢!

【问题讨论】:

    标签: json node.js mongodb node.js-stream jsonstream


    【解决方案1】:

    我在“为什么选择双簧管?”的结尾处的双簧管文档中找到了这些 cmets部分:

    因为是纯 Javascript 解析器,所以 Oboe.js 比 JSON.parse 需要更多的 CPU 时间。 Oboe.js 对于加载非常快的小消息的工作速度稍慢,但对于大多数实际情况,使用 i/o 有效地优化 CPU 时间。 SAX 解析器比 Oboe 的基于模式的解析模型需要更少的内存,因为它们不构建解析树。请参阅 Oboe.js 与 SAX 与 DOM。 如果有疑问,请进行基准测试,但不要忘记使用真实的互联网,包括移动设备,并考虑感知性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-11
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      • 2011-12-04
      • 1970-01-01
      相关资源
      最近更新 更多