首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Node js聊天应用程序比Java慢的原因是什么?

问Node js聊天应用程序比Java慢的原因是什么?
EN

Stack Overflow用户
提问于 2019-11-09 19:35:42
回答 1查看 378关注 0票数 0

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

然而,使用JMeter (5秒内N个请求)测试应用程序显示,对于较低的N (50-100),Node js应用程序会稍微慢一些,而对于较高的N (400),则会变得更慢。

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

代码语言:javascript
复制
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实现中完全相同。

代码语言:javascript
复制
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参数(设置为10,20,50,100),但这主要会使速度变慢。

有没有可能聊天应用的node js实现比java慢?这可能是什么原因呢?我是不是写错了异步部分?

rest请求的Java实现:

代码语言:javascript
复制
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处理该文件,结果如下:

代码语言:javascript
复制
 [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呢?我的代码可以通过任何方式进行优化吗?

EN

回答 1

Stack Overflow用户

发布于 2019-11-09 23:34:43

node通过异步机制和非阻塞is (就像你的例子中的MongoDB查询)明显很快,使用同步代码Java可以击败JS。

首先,没有Java源代码,您的JS使用的是push,这是同步的。根据消息的数量,可能已经花费了相当长的时间(1M推送可能需要~20ms),再乘以50个并发就会出现问题)

其次,至于为什么更大的池更慢,这可能是因为MongoClient池懒惰地初始化连接,这意味着只有在每个连接的第一次查询时才初始化连接。对于更大的池,需要先初始化更多的连接。例如,如果池大小为100,则前100个查询将很慢,因为这些查询将等待连接建立。但随后,池大小为100的池应该能够在高并发情况下提供较低的平均响应时间。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58778850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档