2013-03-17 21 views
21

Come si confronta la libreria Requests con le prestazioni PyCurl?Python Requests vs PyCurl Performance

La mia comprensione è che Requests è un wrapper python per urllib mentre PyCurl è un wrapper python per libcurl che è nativo, quindi PyCurl dovrebbe ottenere prestazioni migliori, ma non è sicuro di quanto.

Non riesco a trovare alcun benchmark comparativo.

risposta

52

I wrote you a full benchmark, utilizzando un'applicazione Flask banale sostenuta da gUnicorn/meinheld + nginx (per le prestazioni e HTTPS), e vedere quanto tempo ci vuole per completare 10.000 richieste. I test vengono eseguiti in AWS su una coppia di istanze c4.large non caricate e l'istanza del server non è stata limitata dalla CPU.

TL; Riepilogo DR: Se si sta facendo un sacco di networking, utilizzare PyCurl, altrimenti utilizzare le richieste. PyCurl termina le piccole richieste 2x-3x più velocemente delle richieste finché non raggiungi il limite di larghezza di banda con grandi richieste (circa 520 MBit o 65 MB/s qui) e utilizza da 3 a 10 volte meno potenza della CPU. Queste cifre confrontano i casi in cui il comportamento del pooling delle connessioni è lo stesso; per impostazione predefinita, PyCurl utilizza il pool di connessioni e le cache DNS, dove le richieste no, quindi un'implementazione ingenua sarà 10 volte più lenta.

Combined-chart-RPS CPU Time by request size detailed

Just HTTP throughput Just HTTP RPS

Nota che trame doppie di registro vengono utilizzati solo per il grafico sottostante, a causa degli ordini di grandezza coinvolti HTTP & HTTPS throughput HTTP & HTTPS RPS

  • pycurl dura circa 73 CPU-microsecondi ad emettere una richiesta quando si riutilizza una connessione
  • richieste richiede circa 526 CPU-microsecondi di emettere una richiesta quando si riutilizza una connessione
  • pycurl richiede circa 165 CPU-microsecondi un aperto nuova connessione e inviare una richiesta (nessuna connessione riutilizzo), o ~ 92 microsecondi per aprire
  • richieste è di circa CPU-microsecondi ad aprire una nuova connessione e inviare una richiesta (nessuna connessione riutilizzo), o ~ 552 microsecondi da aprire

Full results are in the link, insieme alla metodologia di riferimento e alla configurazione del sistema.

Avvertenze: anche se ho preso la briga di garantire i risultati sono raccolti in modo scientifico, è solo testando un tipo di sistema e di un sistema operativo, e un sottoinsieme limitato di prestazioni e in particolare le opzioni HTTPS.

+2

Il benchmark è piacevole, ma localhost non ha alcun overhead di livello di rete. Se si potesse limitare la velocità di trasferimento dei dati alle effettive velocità di rete, utilizzando dimensioni di risposta realistiche ('pong' non è realistico) e includendo un mix di modalità di codifica del contenuto (con e senza compressione), e * then * producono tempi basati su quello, quindi avresti dati di riferimento con significato reale. –

+0

Nota anche che hai spostato il setup di pycurl fuori dal loop (impostando l'URL e writtedata target dovrebbe essere parte del loop), e non leggere il buffer 'cStringIO'; i test non pycurl devono tutti produrre la risposta come oggetto stringa Python. –

+1

@MartijnPieters La mancanza di overhead di rete è intenzionale; l'intento qui è di testare il cliente da solo. L'URL è inseribile lì, quindi puoi testarlo su un server reale di tua scelta (di default non lo fa, perché non voglio martellare il sistema di qualcuno). ** Nota chiave: ** il test successivo di pycurl legge il corpo della risposta tramite body.getvalue e le prestazioni sono molto simili. I PR sono benvenuti per il codice se puoi suggerire miglioramenti. – BobMcGee

12

In primo luogo, requests è costruito in cima alla urllib3 library, la stdlib urllib o urllib2 librerie non vengono utilizzati affatto.

Non ha molto senso confrontare requests con pycurl sulle prestazioni. pycurl potrebbe utilizzare il codice C per il suo funzionamento, ma come tutte le programmazioni di rete, la velocità di esecuzione dipende in gran parte dalla rete che separa la macchina dal server di destinazione. Inoltre, il server di destinazione potrebbe essere lento a rispondere.

Alla fine, requests ha un'API molto più amichevole con cui lavorare, e scoprirai che sarai più produttivo usando quell'API più amichevole.

+0

Sono d'accordo che per la maggior parte delle applicazioni l'API pulita delle richieste è la cosa più importante; ma per le applicazioni ad alta intensità di rete, non ci sono scuse * e * per usare pycurl. Il sovraccarico può essere importante (specialmente all'interno di un centro dati). – BobMcGee

+0

@BobMcGee: se la velocità della rete è così alta che il sovraccarico avrà importanza, non dovresti più usare Python per l'intera applicazione. –

+0

@Martijn_Pieters Non sono d'accordo - le prestazioni di Python non sono male, e in generale è abbastanza facile delegare i bit sensibili alle prestazioni alle librerie native (che pycurl è un perfetto esempio di). DropBox può farlo funzionare, e yum utilizza internamente pycurl (dal momento che molto del suo lavoro è semplicemente il recupero della rete, che deve essere il più veloce possibile). – BobMcGee

0

Particolare attenzione sul Dimensioni -

  1. Sul mio Mac Book Air con 8GB di RAM e uno SSD da 512GB, per un file di 100 MB attestandosi a 3 kilobyte al secondo (da internet e wi-fi), pycurl, arricciatura e la funzione get della libreria delle richieste (indipendentemente da chunking o streaming) sono praticamente le stesse.

  2. Su un più piccolo Quad core Intel Linux box con 4 GB di RAM, su localhost (da Apache nella stessa casella), per un file da 1 GB, curl e pycurl sono 2,5 volte più veloci della libreria 'richieste'. E per le richieste di chunking e streaming insieme si ottiene un aumento del 10% (dimensioni del blocco superiore a 50.000).

ho pensato che stavo per avere scambiare richieste fuori per pycurl, ma non così come l'applicazione che sto facendo non sta per avere client e server che chiudono.