Ir al contenido principal

Comparación de diferentes clientes que pueden realizar una petición http (file-get-contents, curl, guzzle ybuzz).



Para un proyecto que vamos a comenzar dentro de la compañía, y para el cual el rendimiento es muy importante, hemos realizado una comparación entre diferentes clientes que pueden realizar una petición http.
Nuestra idea original era usar guzzle, pero como digo el rendimiento es importante, por lo que antes de usarlo, decidimos realizar algunos test de rendimiento.
Los requisitos que tiene que cumplir nuestro cliente son:
  • Poder comprobar códigos de estado en las respuestas.
  • Gestión avanzada de cabeceras ( petición y respuesta ).
  • Poder configurar timeouts.
  • En la medida de lo posible, que sea rápido y consuma poca memoria.
Las pruebas se realizadan contra un servidor local, el código para las pruebas es este.
<?php
/*
 * This file is part of the XXX package.
 *
 * (c) Daniel González <daniel@desarrolla2.com>
  *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

require __DIR__.'/vendor/autoload.php';

use Desarrolla2\Timer\Timer;
use Desarrolla2\Timer\Formatter\Human;

$url = 'http://localhost/';
$times = 1000;
$repeat = 5;
$timer = new Timer();
for ($r = 1; $r <= $repeat; $r++) {
    for ($i = 1; $i <= $times; $i++) {
        $currentUrl = $url.'?id='.$r.$i;
        file_get_contents($url);
    }
    $mark = $timer->mark('file_get_contents');
    for ($i = 1; $i <= $times; $i++) {
        $currentUrl = $url.'?id='.$r.$i;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        $output = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    }
    $mark = $timer->mark('curl_exec');
    for ($i = 1; $i <= $times; $i++) {
        $currentUrl = $url.'?id='.$r.$i;
        $client = new GuzzleHttp\Client();
        $response = $client->get($currentUrl);
        $code = $response->getStatusCode();
    }
    $mark = $timer->mark('Guzzle');
    for ($i = 1; $i <= $times; $i++) {
        $currentUrl = $url.'?id='.$r.$i;
        $browser = new Buzz\Browser();
        $response = $browser->get($currentUrl);
    }
    $mark = $timer->mark('Buzz');
}
$marks = $timer->getAll();
$results = [];
foreach ($marks as $mark) {
    if (!isset($results[$mark['text']])) {
        $results[$mark['text']] = [
            'time' => 0,
            'memory' => 0
        ];
    }
    $results[$mark['text']]['time'] += $mark['time']['from_previous'];
    $results[$mark['text']]['memory'] += $mark['memory']['from_previous'];
}

$formmater = new Human();
foreach ($results as $key => $value) {
    $results[$key]['time'] = $formmater->time($value['time']);
    $results[$key]['time_by_request'] = $formmater->time($value['time']/$repeat/ $times);
    $results[$key]['memory'] = $formmater->memory($value['memory']);
}

var_dump($results);
El script realiza 10,000 peticiones con cada uno de los métodos, sucesivamente, repitiendo la operación 5 veces, es decir 10,000 * 5 * 5 = 250,000 peticiones en total.
En cada request inicializamos el cliente y realizamos una petición, repitiend la operación 10,000 veces con cada método. La petición se realiza a un servidor en local que regresa un documento pequeño en torno a 12K, de esta forma podemos ver exactamente cual es el performance del cliente.

EJEMPLO 1: FILE_GET_CONTENTS

file_get_contents, es la forma más sencilla de ejecutar una petición http, aunque no cumple los requisitos ya que necesitamos poder comprobar códigos de estado, y añadir timeouts por lo que este método no era válido. Aún así lo añadimos, por simple curiosidad.
tiempo por 10,000
1.52s
tiempo medio por request
0.3ms
consumo de memoria
0

CONCLUSIONES:

No incrementa el consumo de memoria, y funciona muy rápido, por debajo del milisegundo por petición.

EJEMPLO 2: CURL

Es una forma muy simple de realizar peticiones HTTP, pero además nos permite hacer una gestión avanzada de cabeceras y códigos de estado, lo cual era un requisito indispensable para nosotros.
tiempo por 10,000
1.3s
tiempo medio por request
0.26ms
consumo de memoria
0

CONCLUSIONES:

Funciona aún más rápido que el ejemplo anterior, tampoco añade consumo de memoria, y además cumple los requisitos, por lo que parece un gran candidato.

EJEMPLO 3, GUZZLE

Vamos a usar la última versión estable la 5.1. Usar Guzzle era nuestra idea original, cumple todos los requisitos y además ofrece una API con la que estamos muy familiarizados para trabajar con peticiones HTTP.
tiempo por 10,000
3.29s
tiempo medio por request
0.66ms
consumo de memoria
1.25MB

CONCLUSIONES:

Es un poco más lento pero aún así sigue el tiempo de ejecución de cada petición está por debajo del milisegundo, por lo que también parece un buen candidato, lo peor en comparación con curl es que si añade consumo de memoria. En el entorno en el que tenemos previsto ese 1,25M por request puede ser un gran consumo de memoria.

EJEMPLO 4, BUZZ

Hemos querido añadir también este popular cliente para ver que tal se comporta. Aunque en realidad parece que está un poco abandonado, además no permite de manera sencilla recuperar los códigos de estado http, por lo que tampoco cumple los requisitos.
tiempo por 10,000
1.74s
tiempo medio por request
0.35ms
consumo de memoria
256KB

CONCLUSIONES:

Es rápido y apenas aumenta el consumo de memoria.

CONCLUSIONES FINALES

Para nuestro caso concreto tendremos que decidir, entre usar curl o guzzle ya que son los que cumplen nuestros requisitos, quizá ese 1.25M de más en memoria que ocupa guzzle sea lo que finalmente mueva la balanza de un lado a otro.
En una plataforma donde el performance no sea crítico creemos que no merece la pena usar curl y si usar guzzle por la elegante API que facilita y la poca diferencia en el rendiemiento entre ambas. DRY.
FUENTE :

Comentarios

Entradas populares de este blog

Laravel 5Subir archivos con Laravel 5

En esta entrada vamos a ver cómo  subir archivos con  Laravel 5 , de paso repasaremos algunos otros temas, enrutar controladores, crear modelos y definir algunas de sus propiedades, utilizar blade y su sistema de herencia y cómo guardar el registro del archivo en base de datos comprobando el tipo de extensión. Antes de comenzar debemos recordar que para utilizar las clases HTML y FORM en  laravel 5  debemos hacer la instalación con composer, a continuación dejo una entrada donde puedes revisar un poco más en profundidad sobre este tema . Laravel 5: Las clases HTML y FORM Añadir las clases Html y Form en Laravel 5 Simplemente debemos añadir la siguiente línea al archivo composer.json, justamente en la clave require. JavaScript 1 "illuminate/html" : "5.*" Ahora para que las dependencias se instalen ejecuta el siguiente comando situado en tu proyecto. Shell 1 composer update

12 Razones para usar Kotlin en tu proximo proyecto Android.

1. El lenguaje y el entorno están maduros A diferencia de otros lenguajes como Swift, el lanzamiento de  Kotlin ha pasado por muchas etapas de maduración antes de liberar la versión 1.0 final . Esto quiere decir que no vas a encontrarte problemas al trabajar con Kotlin, todo funciona como cabría esperar. El plugin del IDE funciona perfectamente , y ya permite muchas de las funcionalidades que existen para Java. Por ello, trabajar con Kotlin es un maravilla en ese sentido. Es interesante saber que antes de salir a producción, el lenguaje pasó varios años en alpha y luego en beta, y que ya antes de que saliera la beta había gente que lo estaba utilizando en proyectos reales. 2. Facilita mucho el desarrollo en Android Si has estado leyendo todos estos artículos, lo habrás visto claro en muchas ocasiones. Kotlin es simplicidad mezclada con potencia , por lo que tienes un mundo abierto de posibilidades si venías de Java que antes ni podías imaginar. Sinceramente creo que