В чем причина того, что приложение Node js chat работает медленнее, чем Java? - PullRequest
0 голосов
/ 09 ноября 2019

Я новичок в Node js и создал очень простое приложение для группового чата с Mongodb как для узла js (с использованием библиотеки socket.io и express), так и для Java (веб-сокеты из библиотеки Javalin.io). По сути, они выполняют одни и те же действия, поэтому я ожидаю, что Node js будет быстрее, чем Java, так как это, вероятно, лучший пример приложения на основе реального времени и ввода / вывода.

Однако тестированиеприложения с JMeter (N запросов за 5 секунд) показывают, что приложение Node js немного медленнее для меньшего N (50-100), и становится намного медленнее для большего N (400).

Тестируемый мной запрос - это HTTP-запрос к API, возвращающему массив Json, содержащий все сообщения в mongodb:

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), но это в основном замедляло работу.

Возможно, реализация узла чата в приложении чата медленнее, чем в 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? Можно ли оптимизировать мой код?

1 Ответ

0 голосов
/ 09 ноября 2019

узел , по-видимому, быстро с асинхронным механизмом и неблокирующими операциями ввода-вывода (как в случае запросов MongoDB в вашем случае), с синхронным кодом Java может превзойти JS.

Во-первых, без источника Javaкод, ваш JS использует push, и это синхронно. В зависимости от количества сообщений, это может занять некоторое время (1M push может занять ~ 20 мс), и умножить это на 50 одновременностей, это становится проблемой)

Во-вторых, почему большой пул медленнее,это вероятно потому, что пул MongoClient инициализирует соединение лениво, то есть соединение инициализируется только при первом запросе каждого соединения. При большем пуле необходимо сначала инициализировать больше соединений. Например, при размере пула 100 ваши первые 100 запросов будут медленными, потому что эти запросы будут ожидать установления соединения. Но затем тот, у которого размер пула 100, должен иметь более низкое среднее время отклика при высоком параллелизме .

По сравнению с Java, в частности с вашей реализацией. Если ваша реализация не использует push, и ваш клиент Mongo активно создает соединение во время инициализации пула, ваша Java вполне может превзойти эту реализацию JS , особенно во время ранних запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...