Skip to content

Instantly share code, notes, and snippets.

@ferozed
Created December 11, 2016 03:12
Show Gist options
  • Save ferozed/eb555f8b1d1ad6aad978dd34a4b4dc43 to your computer and use it in GitHub Desktop.
Save ferozed/eb555f8b1d1ad6aad978dd34a4b4dc43 to your computer and use it in GitHub Desktop.
Socket.SendFile performance benchmark
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Net.Cache;
using System.Threading;
namespace socket_sendfile
{
delegate TimeSpan SendFileDelegate(Socket client, String filename, long fileSize);
class Header
{
public long FileSize { get; set; }
public int FileNumber { get; set; }
public void Serialize(Stream stream)
{
byte[] buffer = BitConverter.GetBytes(this.FileNumber);
stream.Write(buffer, 0, buffer.Length);
buffer = BitConverter.GetBytes(this.FileSize);
stream.Write(buffer, 0, buffer.Length);
}
public static Header Deserialize(Stream stream)
{
Header header = new Header();
byte[] buffer = new byte[4];
int read = stream.Read(buffer, 0, buffer.Length);
header.FileNumber = BitConverter.ToInt32(buffer, 0);
buffer = new byte[sizeof(long)];
read = stream.Read(buffer, 0, buffer.Length);
header.FileSize = BitConverter.ToInt64(buffer, 0);
return header;
}
}
class Program
{
private Random rand = new Random();
static void Main(string[] args)
{
Program prog = new Program();
try
{
prog.StartServer();
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
client.Bind(new IPEndPoint(0, 0));
client.Connect(new IPEndPoint(IPAddress.Loopback, 8080));
prog.Run(client, new SendFileDelegate(prog.SendFile1));
Console.WriteLine();
prog.Run(client, new SendFileDelegate(prog.SendFile2));
}
}
catch (Exception e)
{
Console.Error.WriteLine(e);
}
}
void StartServer()
{
Thread serverThread = new Thread(new ThreadStart(this.Server));
serverThread.Start();
}
void Run(Socket client, SendFileDelegate sendFileMethod)
{
foreach (long size in this.GetNextSize())
{
String filename = Path.GetTempFileName();
this.CreateFile(filename, size);
for (int i = 0; i & lt; 10; i++)
{
TimeSpan ts = sendFileMethod(client, filename, size);
Console.WriteLine("{0} {1} {2}", i, size, ts.TotalMilliseconds);
}
}
}
IEnumerable<ulong> GetNextSize()
{
ulong[] sizes = { 1024, 4096, 8192, 16385, 65536, 1048576 };
for (int i = 0; i & lt; sizes.Length; i++)
{
yield return sizes[i];
}
}
void CreateFile(string filename, long size)
{
byte[] buffer = new byte[16384];
// first write out the file.
using (FileStream tempStream = File.OpenWrite(filename))
using (BinaryWriter bw = new BinaryWriter(tempStream))
{
long remaining = size;
while (remaining & gt; 0)
{
rand.NextBytes(buffer);
int writeSize = buffer.Length;
if (writeSize & gt; (int)remaining)
{
writeSize = (int)remaining;
}
bw.Write(buffer, 0, writeSize);
remaining -= writeSize;
}
}
}
TimeSpan SendFile1(Socket client, String filename, long fileSize)
{
Stopwatch timer = new Stopwatch();
timer.Start();
using (NetworkStream ns = new NetworkStream(client))
{
Header header = new Header();
header.FileSize = fileSize;
header.FileNumber = 1;
// send the header
header.Serialize(ns);
using (FileStream fs = File.OpenRead(filename))
{
byte[] buffer = new byte[1024];
int read = fs.Read(buffer, 0, buffer.Length);
while (read & gt; 0)
{
ns.Write(buffer, 0, read);
read = fs.Read(buffer, 0, buffer.Length);
}
}
}
timer.Stop();
return timer.Elapsed;
}
TimeSpan SendFile2(Socket client, String filename, long fileSize)
{
Stopwatch timer = new Stopwatch();
timer.Start();
using (NetworkStream ns = new NetworkStream(client))
{
Header header = new Header();
header.FileSize = fileSize;
header.FileNumber = 1;
byte[] headerBuffer = null;
using (MemoryStream ms = new MemoryStream())
{
header.Serialize(ms);
ms.Seek(0, SeekOrigin.Begin);
headerBuffer = ms.ToArray();
}
// send the header
client.SendFile(filename, headerBuffer, null, TransmitFileOptions.UseDefaultWorkerThread);
}
timer.Stop();
return timer.Elapsed;
}
void Server()
{
byte[] buffer = new byte[1024];
TcpListener listener = new TcpListener(8080);
listener.Start();
using (TcpClient client = listener.AcceptTcpClient())
using (NetworkStream ns = client.GetStream())
{
bool hasData = true;
while (hasData)
{
// first get the header. Header has the file size.
Header header = Header.Deserialize(ns);
long remaining = header.FileSize;
while (remaining & gt; 0)
{
int readSize = buffer.Length;
if ((long)readSize & gt; remaining)
readSize = (int)remaining;
int read = ns.Read(buffer, 0, readSize);
remaining -= read;
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment