Created
December 11, 2016 03:12
-
-
Save ferozed/eb555f8b1d1ad6aad978dd34a4b4dc43 to your computer and use it in GitHub Desktop.
Socket.SendFile performance benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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