我是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数组:
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参数(设置为10,20,50,100),但这主要会使速度变慢。
有没有可能聊天应用的node js实现比java慢?这可能是什么原因呢?我是不是写错了异步部分?
rest请求的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呢?我的代码可以通过任何方式进行优化吗?
发布于 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实现,特别是在早期请求期间。
https://stackoverflow.com/questions/58778850
复制相似问题