Skip to content

Instantly share code, notes, and snippets.

@terite
Last active January 28, 2021 20:03
Show Gist options
  • Save terite/3506da1ac8064cdb1f8f11e81661a59f to your computer and use it in GitHub Desktop.
Save terite/3506da1ac8064cdb1f8f11e81661a59f to your computer and use it in GitHub Desktop.
SharpPcap Span<T> benchmark
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Attributes;
using System;
using SharpPcap.LibPcap;
using SharpPcap;
namespace SomeProject.Benchmarks
{
public class Program
{
static readonly bool BENCHMARK = true;
public static void Main(string[] args)
{
if (BENCHMARK)
{
var summary = BenchmarkRunner.Run<WholeFileBenchmark>();
Console.WriteLine(summary);
}
else
{
var benchmark = new WholeFileBenchmark();
var alloc = benchmark.ReadFileAlloc();
Console.WriteLine("Alloc:");
Console.WriteLine($"Read {alloc.packetsRead} packets");
Console.WriteLine($"Read {alloc.bytesRead} bytes");
var noAlloc = benchmark.ReadFileNoAlloc();
Console.WriteLine("\nNo Alloc:");
Console.WriteLine($"Read {noAlloc.packetsRead} packets");
Console.WriteLine($"Read {noAlloc.bytesRead} bytes");
}
}
}
[MemoryDiagnoser]
public class WholeFileBenchmark
{
static readonly string filename = @"<your-file-path-here>";
public WholeFileBenchmark()
{
if (!System.IO.File.Exists(filename))
throw new Exception($"File does not exist {filename}");
}
[Benchmark]
public (uint packetsRead, uint bytesRead) ReadFileAlloc()
{
var device = new NoAllocCaptureFileReaderDevice(filename);
device.Open();
if (!device.Opened) throw new Exception("Device not opened?");
uint packetsRead = 0;
uint bytesRead = 0;
RawCapture rawCapture;
while ((rawCapture = device.GetNextPacket()) != null) {
++packetsRead;
bytesRead += (uint) rawCapture.Data.Length;
}
return (packetsRead, bytesRead);
}
[Benchmark]
public (uint packetsRead, uint bytesRead) ReadFileNoAlloc()
{
var device = new NoAllocCaptureFileReaderDevice(filename);
device.Open();
if (!device.Opened) throw new Exception("Device not opened?");
uint packetsRead = 0;
uint bytesRead = 0;
while (device.TryGetNextPacketNoAlloc(out PcapHeader pcapHeader, out Span<byte> rawData))
{
++packetsRead;
bytesRead += (uint) rawData.Length;
}
return (packetsRead, bytesRead);
}
}
public class NoAllocCaptureFileReaderDevice : CaptureFileReaderDevice
{
public NoAllocCaptureFileReaderDevice(string fileName) : base(fileName) { }
public unsafe bool TryGetNextPacketNoAlloc(out PcapHeader header, out Span<byte> data)
{
IntPtr headerPtr = IntPtr.Zero;
IntPtr dataPtr = IntPtr.Zero;
int res = GetNextPacketPointers(ref headerPtr, ref dataPtr);
if (res > 0)
{
header = PcapHeader.FromPointer(headerPtr);
data = new Span<byte>(dataPtr.ToPointer(), (int)header.CaptureLength);
return true;
}
else
{
header = default;
data = Span<byte>.Empty;
return false;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment