-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add skeleton ring perf microbenchmark
- Loading branch information
Showing
5 changed files
with
278 additions
and
1 deletion.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
// | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
// | ||
|
||
#include <afxdp_helper.h> | ||
#include <intsafe.h> | ||
#include <malloc.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
CONST CHAR *UsageText = "Usage: ringperf"; | ||
#define REQUIRE(expr) \ | ||
if (!(expr)) { printf("("#expr") failed line %d\n", __LINE__); exit(1);} | ||
|
||
typedef struct _RING_SHARED { | ||
XSK_RING Ring; | ||
XSK_RING CompRing; | ||
UINT64 MaxIterations; | ||
UINT32 ProdBatchSize; | ||
UINT32 ConsBatchSize; | ||
} RING_SHARED; | ||
|
||
VOID | ||
Usage( | ||
CHAR *Error | ||
) | ||
{ | ||
fprintf(stderr, "Error: %s\n%s", Error, UsageText); | ||
} | ||
|
||
DWORD | ||
WINAPI | ||
ProdRoutine( | ||
VOID *Context | ||
) | ||
{ | ||
RING_SHARED *RingShared = (RING_SHARED *)Context; | ||
UINT64 Iterations = RingShared->MaxIterations; | ||
static const UINT32 ProdBaseAddress = 0x12345678; | ||
|
||
while (Iterations > 0) { | ||
UINT32 ProdIndex; | ||
UINT32 ProdAvailable; | ||
UINT32 ConsIndex; | ||
UINT32 ConsAvailable; | ||
|
||
ProdAvailable = | ||
XskRingProducerReserve(&RingShared->Ring, RingShared->ProdBatchSize, &ProdIndex); | ||
for (UINT32 i = 0; i < ProdAvailable; i++) { | ||
XSK_FRAME_DESCRIPTOR *Frame = XskRingGetElement(&RingShared->Ring, ProdIndex + i); | ||
|
||
Frame->Buffer.Address.BaseAddress = ProdBaseAddress; | ||
Frame->Buffer.Address.Offset = 2; | ||
Frame->Buffer.Length = 3; | ||
Frame->Buffer.Reserved = 0; | ||
} | ||
XskRingProducerSubmit(&RingShared->Ring, ProdAvailable); | ||
|
||
ConsAvailable = | ||
XskRingConsumerReserve(&RingShared->CompRing, RingShared->ProdBatchSize, &ConsIndex); | ||
for (UINT32 i = 0; i < ConsAvailable; i++) { | ||
UINT64 *Completion = XskRingGetElement(&RingShared->CompRing, ConsIndex + i); | ||
|
||
REQUIRE(*Completion == ProdBaseAddress) | ||
} | ||
XskRingConsumerRelease(&RingShared->CompRing, ConsAvailable); | ||
|
||
Iterations -= ConsAvailable; | ||
} | ||
|
||
return NO_ERROR; | ||
} | ||
|
||
DWORD | ||
WINAPI | ||
ConsRoutine( | ||
VOID *Context | ||
) | ||
{ | ||
RING_SHARED *RingShared = (RING_SHARED *)Context; | ||
UINT64 Iterations = RingShared->MaxIterations; | ||
static const UINT32 ProdBaseAddress = 0x12345678; | ||
|
||
while (Iterations > 0) { | ||
UINT32 ConsIndex; | ||
UINT32 ProdIndex; | ||
UINT32 Available; | ||
|
||
Available = | ||
XskRingConsumerReserve(&RingShared->Ring, RingShared->ConsBatchSize, &ConsIndex); | ||
Available = | ||
XskRingProducerReserve(&RingShared->CompRing, Available, &ProdIndex); | ||
|
||
for (UINT32 i = 0; i < Available; i++) { | ||
XSK_FRAME_DESCRIPTOR *Frame = XskRingGetElement(&RingShared->Ring, ConsIndex + i); | ||
UINT64 *Completion = XskRingGetElement(&RingShared->CompRing, ProdIndex + i); | ||
|
||
*Completion = Frame->Buffer.Address.BaseAddress; | ||
} | ||
|
||
XskRingConsumerRelease(&RingShared->Ring, Available); | ||
XskRingProducerSubmit(&RingShared->CompRing, Available); | ||
|
||
Iterations -= Available; | ||
} | ||
|
||
return NO_ERROR; | ||
} | ||
|
||
#pragma warning(push) | ||
#pragma warning(disable:4324) // structure was padded due to alignment specifier | ||
|
||
// | ||
// This is based on the shared rings layout provided by xsk.c. | ||
// | ||
typedef struct _RINGPERF_SHARED_RING { | ||
DECLSPEC_CACHEALIGN UINT32 ProducerIndex; | ||
DECLSPEC_CACHEALIGN UINT32 ConsumerIndex; | ||
DECLSPEC_CACHEALIGN UINT32 Flags; | ||
// | ||
// Followed by power-of-two array of ring elements, starting on 8-byte alignment. | ||
// XSK_FRAME_DESCRIPTOR[] for rx/tx, UINT64[] for fill/completion | ||
// | ||
} RINGPERF_SHARED_RING; | ||
|
||
#pragma warning(pop) | ||
|
||
static | ||
VOID | ||
AllocateRing( | ||
_Out_ XSK_RING *Ring, | ||
_In_ UINT32 ElementSize, | ||
_In_ UINT32 ElementCount | ||
) | ||
{ | ||
XSK_RING_INFO RingInfo = {0}; | ||
SIZE_T RingAllocSize; | ||
|
||
REQUIRE(SUCCEEDED(SizeTMult(ElementSize, ElementCount, &RingAllocSize))); | ||
REQUIRE(SUCCEEDED(SizeTAdd(RingAllocSize, sizeof(RINGPERF_SHARED_RING), &RingAllocSize))); | ||
|
||
RingInfo.Ring = _aligned_malloc(RingAllocSize, SYSTEM_CACHE_ALIGNMENT_SIZE); | ||
RingInfo.Size = ElementCount; | ||
RingInfo.DescriptorsOffset = sizeof(RINGPERF_SHARED_RING); | ||
RingInfo.ConsumerIndexOffset = FIELD_OFFSET(RINGPERF_SHARED_RING, ConsumerIndex); | ||
RingInfo.ProducerIndexOffset = FIELD_OFFSET(RINGPERF_SHARED_RING, ProducerIndex); | ||
RingInfo.FlagsOffset = FIELD_OFFSET(RINGPERF_SHARED_RING, Flags); | ||
RingInfo.ElementStride = ElementSize; | ||
|
||
XskRingInitialize(Ring, &RingInfo); | ||
} | ||
|
||
INT | ||
__cdecl | ||
main( | ||
INT ArgC, | ||
CHAR **ArgV | ||
) | ||
{ | ||
INT Err = 0; | ||
RING_SHARED RingShared = {0}; | ||
HANDLE ProdThread, ConsThread; | ||
UINT32 ElementCount = 0x1000; | ||
|
||
UNREFERENCED_PARAMETER(ArgC); | ||
UNREFERENCED_PARAMETER(ArgV); | ||
|
||
RingShared.MaxIterations = 0x100000000ui64; | ||
RingShared.ProdBatchSize = 32; | ||
RingShared.ConsBatchSize = 32; | ||
|
||
AllocateRing(&RingShared.Ring, sizeof(XSK_FRAME_DESCRIPTOR), ElementCount); | ||
AllocateRing(&RingShared.CompRing, sizeof(UINT64), ElementCount); | ||
|
||
ProdThread = CreateThread(NULL, 0, ProdRoutine, &RingShared, 0, NULL); | ||
REQUIRE(ProdThread != NULL); | ||
|
||
ConsThread = CreateThread(NULL, 0, ConsRoutine, &RingShared, 0, NULL); | ||
REQUIRE(ConsThread != NULL); | ||
|
||
WaitForSingleObject(ConsThread, INFINITE); | ||
WaitForSingleObject(ProdThread, INFINITE); | ||
|
||
return Err; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<ItemGroup> | ||
<ClCompile Include="ringperf.c" /> | ||
</ItemGroup> | ||
<PropertyGroup> | ||
<ProjectGuid>{838975ce-9bc8-4ba8-a129-2c33791ba339}</ProjectGuid> | ||
<TargetName>ringperf</TargetName> | ||
<UndockedType>exe</UndockedType> | ||
<ImportWnt>true</ImportWnt> | ||
</PropertyGroup> | ||
<Import Project="$(SolutionDir)src\xdp.cpp.props" /> | ||
<ItemDefinitionGroup> | ||
<Link> | ||
<AdditionalDependencies> | ||
onecore.lib; | ||
%(AdditionalDependencies) | ||
</AdditionalDependencies> | ||
</Link> | ||
</ItemDefinitionGroup> | ||
<Import Project="$(SolutionDir)src\xdp.targets" /> | ||
</Project> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
param ( | ||
[Parameter(Mandatory = $false)] | ||
[ValidateSet("Debug", "Release")] | ||
[string]$Config = "Debug", | ||
|
||
[Parameter(Mandatory = $false)] | ||
[ValidateSet("x64", "arm64")] | ||
[string]$Platform = "x64" | ||
) | ||
|
||
Set-StrictMode -Version 'Latest' | ||
$ErrorActionPreference = 'Stop' | ||
|
||
# Important paths. | ||
$RootDir = Split-Path $PSScriptRoot -Parent | ||
. $RootDir\tools\common.ps1 | ||
$ArtifactsDir = Get-ArtifactBinPath -Config $Config -Platform $Platform | ||
|
||
$Time = Measure-Command { | ||
& $ArtifactsDir\test\ringperf.exe | ||
} | ||
|
||
Write-Output "ringperf.exe took $($Time.TotalSeconds) seconds to run." |
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