【问题标题】:JSON string directly from node mongodb直接来自节点 mongodb 的 JSON 字符串
【发布时间】:2014-05-02 07:00:00
【问题描述】:

我一直在一个简单的服务器上进行一系列负载测试,试图确定是什么对我更复杂的 node/express/mongodb 应用程序的负载产生了负面影响。一直出现的一件事是字符串操作需要在快速响应中将内存中的对象转换为 JSON。

我通过节点从 mongodb 提取并通过线路发送的数据量约为 200/300 KB 未压缩。 (Gzip 会把它变成 28k,这样会好很多。)

有没有办法让本机 nodejs mongodb 驱动程序为我字符串化结果?现在,对于使用标准 .toArray() 的每个请求,我们正在执行以下操作:

  1. 查询数据库,找到结果并将其传输到节点本机驱动程序
  2. 本机驱动程序然后将它们转换为内存中的 javascript 对象
  3. 然后我的代码将内存中的对象传递给表达
  4. Express 然后使用 JSON.stringify() 将其转换为节点的 http response.send 的字符串(我阅读了源 Luke。)

我希望在 c++/native 层完成字符串化工作,这样它就不会增加我的事件循环的处理时间。有什么建议么?

编辑 1:

一个已证实的瓶颈。

可能还有其他可以优化的东西,但这就是负载测试所显示的内容。

我们在几秒钟内通过 500 个请求访问了同一个网络服务器。使用此代码:

app.get("/api/blocks", function(req, res, next){
    db.collection('items').find().limit(20).toArray(function(err, items){
        if(err){
            return next(err);
        }
        return res.send(200, items);
    });
});

总体平均值:323 毫秒,95% 为 820 毫秒

如果我换出 json 数据:

var cached = "[{... "; //giant json blob that is a copy+paste of the response in above code.
app.get("/api/blocks", function(req, res, next){
    db.collection('items').find().limit(20).toArray(function(err, items){
        if(err){
            return next(err);
        }
        return res.send(200, cached);
    });
});

平均值为 164 毫秒,95% 为 580

现在你可能会说,“天哪,平均 323 毫秒太棒了,你的问题是什么?”我的问题是,这是一个 stringify 导致响应时间加倍的示例。

从我的测试中我还可以告诉你这些有用的东西:

  • Gzip 的响应时间提高了 2 倍或更好。以上是带gzip的
  • 与通用 nodejs 相比,Express 增加了几乎无法察觉的开销
  • 通过 cursor.each 对数据进行批处理,然后将每个单独的项目发送到响应中会更糟

更新 2:

使用分析工具:https://github.com/baryshev/look 这是在我的生产代码一遍又一遍地在同一个数据库密集型进程上运行的时候。该请求包含一个 mongodb 聚合并发回约 380KB 数据(未压缩)。

该函数非常小,包含var body = JSON.stringify(obj, replacer, spaces); 行。

【问题讨论】:

  • 您是否有证据表明JSON.stringify() 正在花费大量时间?此外,JSON.stringify 在 node.js 的 V8 引擎中的实现很可能是在 C++ 中。
  • 我同意 JohnnyHK 的观点。这看起来像是过早优化的情况,只有在您证明它是您的特定应用程序的瓶颈之后才应该修复它。可能还有更多关于性能问题的示例,它们会让您获得更大的收益来解决。
  • 听起来像是 Streams 的典型用例。

标签: javascript node.js mongodb express


【解决方案1】:

听起来您应该直接从 Mongo 流式传输到 Express。

this question that asks exactly this:

cursor.stream().pipe(JSONStream.stringify()).pipe(res);

【讨论】:

  • 在我的测试工具中,响应时间减少了近 50%。哇!
猜你喜欢
  • 2017-08-31
  • 1970-01-01
  • 2020-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多