2013-05-24 7 views
5

Ho notato uno strano comportamento delle prestazioni del seguente codice in node.js. Quando la dimensione di content è 1,4 KB, il tempo di risposta della richiesta è di circa 16 ms. Tuttavia, quando la dimensione del content si trova a soli 988 byte, il tempo di risposta della richiesta è stranamente molto più lungo, circa 200ms :node.js response.write (dati) richiede molto tempo quando la dimensione dei dati è piccola

response.writeHead(200, {"Content-Type": "application/json"}); 
response.write(JSON.stringify(content, null, 0)); 
response.end(); 

Questo non sembra intuitivo. Guardando nella scheda di rete di Firebug, l'aumento/differenza deriva tutto dalla ricezione (in attesa invece è 16ms per entrambi).

ho fatto la seguente modifica per risolvere il problema in modo che entrambi i casi hanno 16 ms tempo di risposta:

response.writeHead(200, {"Content-Type": "application/json"}); 
response.end(JSON.stringify(content, null, 0)); 

Ho guardato attraverso node.js doc ma finora non ho trovato informazioni correlate. La mia ipotesi è relativa al buffering, ma potrebbe node.js preempt tra write() e end()?

Aggiornamento:

Questo è stato testato su v0.10.1 su Linux.

Ho provato a dare un'occhiata a source e ho identificato la differenza tra il 2 percorso. La prima versione ha 2 chiamate Socket.write.

writeHead(...) 
write(chunk) 
    chunk = Buffer.byteLength(chunk).toString(16) + CRLF + chunk + CRLF; 
    ret = this._send(chunk); 
    this._writeRaw(chunk); 
     this.connection.write(chunk); 
end() 
    ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk. 
    this._writeRaw(chunk); 
     this.connection.write(chunk); 

La seconda, buona versione ha solo 1 Socket.write chiamata:

writeHead(...) 
end(chunk) 
    var l = Buffer.byteLength(chunk).toString(16); 
    ret = this.connection.write(this._header + l + CRLF + 
           chunk + '\r\n0\r\n' + 
           this._trailer + '\r\n', encoding); 

Ancora non è sicuro di quello che fa la prima versione non funziona bene con la dimensione più piccola risposta.

+1

A quanto ne so, questi dovrebbero fare essenzialmente la stessa cosa e non posso riprodurlo localmente. Puoi provare a inventare un caso di test completo e riproducibile e gettarlo in un fiddle o in un sommario per noi per il check-out? Stai facendo tutto questo a livello locale? – loganfsmyth

+0

Inoltre, puoi chiarire il tuo ambiente? finestre? osx? Linux? – bryanmac

+1

possibile duplicato di http://stackoverflow.com/questions/15422411/node-js-response-time –

risposta

9

Risposta breve:

è possibile impostare in modo esplicito l'intestazioneContent-Length. Ridurrà il tempo di risposta da circa 200ms a 20ms.

var body = JSON.stringify(content, null, 0); 
response.writeHead(200, { 
    "Content-Type": "application/json", 
    'Content-Length': body.length 
}); 
response.write(content); 
response.end(); 

Fatti:

Dopo alcuni esperimenti, ho scoperto che se ilcontentè abbastanza piccolo (nel mio caso, a meno di 1310 byte) per un singolo MTU per portare avanti, il tempo di risposta sarebbe intorno a 200 ms. Tuttavia, per qualsiasi content superiore a tale valore, il tempo di risposta sarebbe di circa 20ms.

Quindi ho utilizzato wireshark per acquisire i pacchetti di rete del lato server.Qui di seguito è un risultato tipico:

Per piccoli content:

  • [0000ms] response.write(content)
  • [0200ms] ha ricevuto il pacchetto ACK dal client
  • [0201ms] response.end()

Per più grande content:

  • [0000ms] response.write(content) // Il primo MTU viene inviato
  • [0001ms] secondo MTU è inviato
  • [0070ms] ha ricevuto il pacchetto ACK dal client
  • [0071ms] response.end()

Spiegazione possibile:

Se l'intestazione Content-Length non è impostata, i dati verrebbero trasferiti in modalità "Chunked". Nella modalità "Chunked", né il server né il client conoscono esattamente la lunghezza dei dati, quindi il client aspetterebbe (200 ms) per vedere se ci sono i seguenti pacchetti.

Tuttavia, questa spiegazione sollevare un'altra questione: perché nel più ampiocontentcaso, il cliente non attese per 200 ms (invece, ha aspettato solo circa 50 ms)?

+0

ma nella codifica di trasferimento Chunked, c'è un segnale di fine esplicito, quindi "Chunked" non può spiegare questo problema. – vilicvane

Problemi correlati