Medir la velocidad de un Stream

by Valeriano Tortola 28. septiembre 2007 20:46

Cosilla curiosa que nunca había hecho antes, medir la velocidad de lectura de un Stream, por ejemplo para saber a que velocidad en Bytes/s descargamos de un NetworkStream, ó de un FtpDataStream, ó para saber como de rápido lee nuestro disco duro ... ya sea con fines meramente estadísticos ó para encontrar el tamaño de buffer adecuado ... Es un procedmiento muy sencillo, se trata de dividir los bytes descargados entre los milisegundos transcurridos (cuantos bytes por milisegundo) y multiplicarlo por 1000 (un segundo). Para ello nos apoyamos en la clase para realizar mediciones de tiempo con precisión, StopWatch.

En este ejemplo de una descarga FTP, tenemos un FtpDataStream de donde leemos los datos y un FileStream donde los guardamos. Se podría hacer con practicamente cualquier Stream. Adicionalmente declaramos una variable global a la clase Int64 donde almacenar la cantidad de Bytes leidos y un StopWatch global también para poder consultarlos desde otros métodos:

private Stopwatch downloadStopWatch = new Stopwatch();
private Int64 downloadedBytes=0;

Cuando vamos a iniciar la lectura, iniciamos el StopWatch y vamos incrementando los bytes leídos:

using (FileStream fs = new FileStream(this.localDirectory, 
       FileMode.Create,FileAccess.Write, FileShare.None))
using (Stream strm = ftp.GetResponse().GetResponseStream())
{
  // Inicio el cronómetro
  downloadStopWatch.Start();
 
  contentLen = strm.Read(buff, 0, this.bufferLength);
  
  // Incremento los bytes leidos.
  downloadedBytes += contentLen;
  while (contentLen != 0)
  {
    fs.Write(buff, 0, contentLen);
    contentLen = strm.Read(buff, 0, this.bufferLength);
    
    // Incremento los bytes leidos.
    downloadedBytes += contentLen;
  }
 
  // Paro el cronómetro.
  downloadStopWatch.Stop();
}

Cuando queramos saber la velocidad, por ejemplo en KBytes/s podemos invocar a un metodo/propiedad-get tal que así:

public Single DownloadSpeed
{
  get
  {
    Double bytesPerSecond;
    try
    {
      bytesPerSecond = (this.downloadedBytes / 
                        downloadStopWatch.ElapsedMilliseconds) * 1000;
    }
    catch (DivideByZeroException)
    {
      // El StopWatch marcaba 0 milisegundos.
      bytesPerSecond = this.downloadedBytes;
    }
    return (Single)(bytesPerSecond / 1024);
  }
}

Nota: Ojo, se puede dar el caso de que consultemos la velocidad y la descarga no se haya iniciado aún ... ó que ni siquiera haya pasado 1ms ... por lo que debemos controlar la división por cero y devolver en dicho caso los bytes transferidos hasta el momento, que serán 0 si la descarga no ha comenzado y X si ha comenzado ya :D ... Yo siempre me pongo en el peor de los supuestos por si acaso !!!! xD

Tags: , ,

.NET 2.0 | C# 2.0

Comentarios

28/09/2007 20:49:22 #

trackback

Trackback from vtortola

Medir la velocidad de un Stream

vtortola |

Comentarios no permitidos