Mam prosty serwer Nodejs Express, gdzie biegnął w kwestii, w którym pierwszy wniosek po długim czasie bezczynności jest niezwykle powolny. Np. - 3-4 min. Ten sam lub podobny wniosek o 2 i trzeci raz zajmuje kilka milisekund.

Spojrzałem na tę stronę - https://expressjs.com/en/ Advanced / Best-Practice-Performance.Html i wykonaliśmy następujące rzeczy -

  1. Użyj kompresji GZIP.
  2. Ustaw node_env do produkcji

Ale nadal wpadam w ten problem, w którym pierwsza prośba jest niezwykle powolna.

Serwer wykonuje następujące czynności -

  1. Na uruchomieniu czytałem z dużego pliku tekstowego zawierającego listę ciągów. Każda z tych ciągów jest dodawana do tablicy. Rozmiar tablicy jest zwykle około 3,5 miliona wpisów.

  2. Użytkownicy zapewniają wejście ciągów i pętlę nad wszystkimi wpisami w tablicy i wyszukaj mecze za pomocą indexof i zwróć mecze.

Próbowałem również zwiększyć pamięć dla serwera - Max-Old-Space-Size z 4096 do 8192, ale to nie pomaga. Jestem nowy w użyciu NodeJs / Express, daj mi znać, jeśli jest coś jeszcze, do czego muszę rozważyć / spojrzeć.

Dzięki.

Oto źródło -

var compression = require('compression')
const express = require('express')
var cors = require('cors')
var bodyParser = require('body-parser')
const fs = require('fs') 

// Get command line arguments

const datafile = process.argv[2];
const port = Number(process.argv[3]);

if(process.env.NODE_ENV === 'production') {
  console.log("Starting in production mode");
}

// Init

const app = express()

app.use(cors());
app.use(bodyParser.text());
app.use(compression());

app.post('/', (request, response) => {
  var query = JSON.parse(request.body).query;
  var results = SearchData(query);
  response.send(results);
})

// Init server

app.listen(port, (err) => {
  if (err) {
    return console.log('Something bad happened', err)
  }
  console.log(`server is listening on port ${port}`)
})

console.log('Caching Data');

var data = fs.readFileSync('/datafile.txt', 'utf8');
var datalist = data.toString().split('\n');

var loc = [];
for (var i = 0; i < datalist.length; i++) {
  const element = datalist[i];
  const dataRaw = element.split(',');
  const dataStr = dataRaw[0];
  const dataloc = processData(dataRaw[1]); 
  datalist[i] = dataStr;
  loc.push(dataloc);
}

console.log('Cached ' + datalist.length + ' entries');

function SearchData (query) {
  const resultsLimit = 32;
  var resultsCount = 0;
  var results = [];
  for (var i = 0; i < datalist.length; i++) {
    if (datalist[i].indexOf(query) === -1) {
      contiue;
    }
    results.push(datalist[i] + loc[i]);
    resultsCount++;
    if (resultsCount == resultsLimit) break;
  }
  return results;
}

Więcej szczegółów po korzystaniu z flagi - Flaga -Trace-GC.

Uruchomił proces i czekał, aż wszystkie ciągi zostały załadowane do pamięci.

Wniosek z konkretnym ciągiem zapytania o 17:48 zajęło około 520 ms.

Ten sam prośba o godzinę 20:11 wygląda około 157975 ms. Serwer był bezczynny pomiędzy.

Widzę wiele wiadomości, takich jak następujące podczas uruchamiania -

[257989:0x3816030] 33399 ms: Scavenge 1923.7 (1956.9) -> 1921.7 (1970.9) MB, 34.2 / 0.0 ms (average mu = 0.952, current mu = 0.913) allocation failure

Ostatnia wiadomość z dzienników GC pokazała coś takiego -

[257989:0x3816030] 60420 ms: Mark-sweep 1927.9 (1944.9) -> 1927.1 (1939.1) MB, 164.0 / 0.0 ms (+ 645.6 ms in 81 steps since start of marking, biggest step 123.0 ms, walltime since start of marking 995 ms) (average mu = 0.930, current mu = 0.493) finalize incremental marking via task GC in old space requested

Nie widziałem nic innego z GC, gdy odpowiedź była naprawdę wolna. Daj mi znać, jeśli ktoś może wywnioskować coś z tych dzienników.

Są to wersje Nodejs i Express Server -

  1. węzeł --version -> 12.20.0
  2. Express --version -> 4.16.4

Wygląda na to, że serwer idzie spać i zajmuje dużo czasu na obudzenie.

1
Hari Reddy 18 styczeń 2021, 22:23

1 odpowiedź

Najlepsza odpowiedź

Udało mi się znaleźć rozwiązanie tego problemu za pomocą implementacji opartej na rdzewieniu, ale główną przyczyną tego zachowania nie był serwer Nodejs / Express, ale maszyna, w której wdrażałem ten kod.

Najpierw przeniosłem się do wdrożenia oparte na rdzy za pomocą Actix-Web Ramy i zauważyłem podobne problemy z wydajnością, które widziałem za pomocą Nodejs / wyrazić.

Następnie użyłem rdzy Rayon biblioteka, aby przetworzyć duże macierze równolegle i rozwiązano Problemy z wydajnością, które widziałem.

Myślę, że główną przyczyną tego problemu było to, że serwer, do którego wdrażałem ten kod, miał mniejszy procesor i nie prowadziłem do tego problemu na mojej maszynie deweloperskiej, ponieważ ma lepszy procesor -

Maszyna serwerowa - procesor Intel Core 2100 MHz 8 rdzeni 16 wątki

Maszyna dev - procesor Intel Xeon 3,50 GHz 6 rdzeni 12 wątków

Prawdopodobnie za pomocą dowolnej biblioteki przetwarzania równoległej z wdrażaniem Nodejs / Express zostałby również rozwiązany ten problem.

0
Hari Reddy 13 marzec 2021, 18:53