【问题标题】:What could be the reason for Node js chat application being slower than Java?Node js 聊天应用程序比 Java 慢的原因可能是什么?
【发布时间】:2019-11-09 11:35:42
【问题描述】:

我是 Node js 的新手,我已经在 Node js(使用 socket.io 库和 express)和 Java(来自 Javalin.io 库的 websockets)中使用 Mongodb 构建了一个非常简单的群聊应用程序。他们基本上做同样的事情,所以我希望 Node js 比 Java 快,因为这可能是基于实时和 I/O 的应用程序的最佳示例。

但是,使用 JMeter 测试应用程序(N 个请求在 5 秒内)表明 Node js 应用程序对于较低的 N (50-100) 稍慢,对于较高的 N (400) 变得更慢。

我正在测试的请求是对 api 的 HTTP 请求,返回一个包含 mongodb 中所有消息的 Json 数组:

app.all('/chats', function (req, res) {
res.setHeader("Content-Type", "application/json");
res.statusCode = 200;

thechatsCollection.find({}).toArray ( (err, chats) => {
    var jsonArr = [];
    for (var i = 0; i < chats.length; i++) {
        jsonArr.push({
        sender: chats[i].sender,
        message: chats[i].message,
        createdAt: chats[i].createdAt
        });
    }
    res.json(jsonArr);
    });
});

我初始化 thechatsCollection 一次,当服务器启动并且我知道它应该打开一个动态连接池(从 5 开始),这在 Java 实现中完全相同。

MongoClient.connect("mongodb://127.0.0.1:27017/chat", { useNewUrlParser: true, /*poolSize: 100*/ }, (err, client) => {
    if(err) throw err;
    client.db('chat').collection('thechats', (err, collection) => {
        thechatsCollection = collection;
        console.log("connected to the db");
    });                    
});

另外,我注意到第二次运行测试导致响应时间的平均值较低,我认为这是由于与数据库的连接池增加了,所以我尝试在打开时设置 poolSize 参数db 连接(到 10,20,50,100),但它主要是让事情变慢。

聊天应用程序的节点 js 实现是否可能比 java 慢?这可能是什么原因?我是不是写错了异步部分?

其余请求的Java实现:

app.get("/chats", ctx -> {
        JSONArray messageArray = getMessageArray();
        ctx.contentType("application/json");
        ctx.result(messageArray.toString());
    });

// Builds a JSON array containing all the messages in the db
private static JSONArray getMessageArray() {
    JSONArray messageArray = new JSONArray();
    for (Document doc : thechatsCollection.find()) {
        JSONObject message = new JSONObject();
        message.put("message", doc.get("message"));
        message.put("sender", doc.get("sender"));
        message.put("createdAt", doc.get("createdAt"));
        messageArray.put(message);
    }
    return messageArray;
}

我尝试使用内置的 --prof 进行分析,调用 ab -c 20 -n 250 "http://localhost:5000/chats",它应该一次执行 250 个请求 20,并使用 --prof-process 处理文件,这就是我得到的:

 [Summary]:
   ticks  total  nonlib   name
    606    2.2%   78.3%  JavaScript
      0    0.0%    0.0%  C++
    298    1.1%   38.5%  GC
  26331   97.1%          Shared libraries
    168    0.6%          Unaccounted
 [Shared libraries]:
   ticks  total  nonlib   name
  23282   85.9%          C:/Windows/SYSTEM32/ntdll.dll
   3026   11.2%          C:/Program Files/nodejs/node.exe
...
 [JavaScript]:
   ticks  total  nonlib   name
    122    0.5%   15.8%  LazyCompile: *deserializeObject C:/Users/apon9/OneDrive/Node js/chatApplication_nodejs/node_modules/bson/lib/bson/parser/deserializer.js:41:33
     82    0.3%   10.6%  Builtin: KeyedStoreIC_Megamorphic
     35    0.1%    4.5%  Builtin: InterpreterEntryTrampoline
...

C:/Program Files/Nodejs/Node.exe 对我来说似乎是合理的,但我不知道 C:/Windows/SYSTEM32/ntdll.dll 是否应该有 86%,也许与内核有关?

deserializeObject 怎么样?我的代码可以以任何方式优化吗?

【问题讨论】:

  • 这个rest请求的Java实现是什么样的?
  • 添加了java实现

标签: node.js mongodb socket.io jmeter performance-testing


【解决方案1】:

节点显然速度很快,具有异步机制和非阻塞 IO(如您的情况下的 MongoDB 查询),使用同步代码 Java 可以击败 JS。

首先,如果没有 Java 源代码,您的 JS 使用的是push,这是同步的。根据消息的数量,它可能已经花费了相当长的时间(1M 推送可能需要大约 20 毫秒),然后将其乘以 50 并发就会成为问题)

其次,为什么更大的池更慢,这可能是因为MongoClient池正在延迟初始化连接,这意味着只有在每个连接的第一次查询时才会初始化连接。使用更大的池,首先需要初始化更多的连接。因此,例如,池大小为 100,您的前 100 个查询会很慢,因为这些查询将等待连接建立。但是随后池大小为 100 的那个应该能够在高并发下提供更低的平均响应时间

因此,与 Java 相比,尤其是您的实现。如果您的实现不使用push,并且您的 Mongo 客户端在池初始化期间主动创建连接,那么您的 Java 很可能能够击败 此 JS 实现,尤其是在早期请求期间。

【讨论】:

  • 1) push 是如何同步操作的?将项目添加到数组的异步方式是什么? 2)有什么方法可以以一种急切的方式而不是懒惰的方式来初始化连接池的连接?设置poolSize 有什么意义?
  • 没有异步方法可以添加到数组中,如果这样做也不会更快。更重要的是,您的代码在这里做一些数学运算,构建这些数组,而 Java 可能会更快。可能是,因为它是强类型的。但这真的是时间的流逝吗?没有人真正知道,在你开始分析代码之前没有人会知道。
  • 哦,谢谢,我明白了。我刚刚尝试使用内置分析器分析我的节点 js 应用程序,但我遇到了一些麻烦......如果有任何想法,我将立即编辑操作
猜你喜欢
  • 1970-01-01
  • 2019-05-31
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 2012-12-04
  • 2016-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多