Skip to content

Commit

Permalink
benchmark step time
Browse files Browse the repository at this point in the history
  • Loading branch information
erincatto committed Dec 27, 2024
1 parent 90d491c commit b2a55b4
Show file tree
Hide file tree
Showing 17 changed files with 198 additions and 113 deletions.
46 changes: 45 additions & 1 deletion benchmark/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ static void FinishTask( void* userTask, void* userContext )
// Examples:
// start /affinity 0x5555 .\build\bin\Release\benchmark.exe -t=4 -w=4
// start /affinity 0x5555 .\build\bin\Release\benchmark.exe -t=8
// start /affinity 0x5555 .\build\bin\Release\benchmark.exe -t=4 -w=4 -b=3 -r=1 -nc -s

int main( int argc, char** argv )
{
Benchmark benchmarks[] = {
Expand All @@ -134,12 +136,21 @@ int main( int argc, char** argv )

int benchmarkCount = ARRAY_COUNT( benchmarks );

int maxSteps = benchmarks[0].totalStepCount;
for (int i = 1; i < benchmarkCount; ++i)
{
maxSteps = b2MaxInt( maxSteps, benchmarks[i].totalStepCount );
}

float* stepTimes = malloc( maxSteps * sizeof( float ) );

int maxThreadCount = GetNumberOfCores();
int runCount = 4;
int singleBenchmark = -1;
int singleWorkerCount = -1;
b2Counters counters = { 0 };
bool enableContinuous = true;
bool recordStepTimes = false;

assert( maxThreadCount <= THREAD_LIMIT );

Expand Down Expand Up @@ -168,13 +179,18 @@ int main( int argc, char** argv )
{
enableContinuous = false;
}
else if ( strncmp( arg, "-s", 3 ) == 0 )
{
recordStepTimes = true;
}
else if ( strcmp( arg, "-h" ) == 0 )
{
printf( "Usage\n"
"-t=<integer>: the maximum number of threads to use\n"
"-b=<integer>: run a single benchmark\n"
"-w=<integer>: run a single worker count\n"
"-r=<integer>: number of repeats (default is 4)\n" );
"-r=<integer>: number of repeats (default is 4)\n"
"-s: record step times\n" );
exit( 0 );
}
}
Expand Down Expand Up @@ -246,7 +262,13 @@ int main( int argc, char** argv )
{
benchmark->stepFcn( worldId, 0 );
}

assert( stepCount <= maxSteps );

b2Timer stepTimer = b2CreateTimer();
b2World_Step( worldId, timeStep, subStepCount );
stepTimes[0] = b2GetMillisecondsAndReset( &stepTimer );

taskCount = 0;

b2Timer timer = b2CreateTimer();
Expand All @@ -259,6 +281,8 @@ int main( int argc, char** argv )
}
b2World_Step( worldId, timeStep, subStepCount );
taskCount = 0;

stepTimes[step] = b2GetMillisecondsAndReset( &stepTimer );
}

float ms = b2GetMilliseconds( &timer );
Expand All @@ -284,6 +308,24 @@ int main( int argc, char** argv )

enkiDeleteTaskScheduler( scheduler );
scheduler = NULL;

if (recordStepTimes && runIndex == 0)
{
char fileName[64] = { 0 };
snprintf( fileName, 64, "%s_t%d.dat", benchmarks[benchmarkIndex].name, threadCount );
FILE* file = fopen( fileName, "w" );
if ( file == NULL )
{
continue;
}

for ( int stepIndex = 0; stepIndex < stepCount; ++stepIndex)
{
fprintf( file, "%g\n", stepTimes[stepIndex] );
}

fclose( file );
}
}
}

Expand All @@ -310,5 +352,7 @@ int main( int argc, char** argv )
printf( "======================================\n" );
printf( "All Box2D benchmarks complete!\n" );

free( stepTimes );

return 0;
}
2 changes: 1 addition & 1 deletion include/box2d/math_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ B2_INLINE b2Rot b2NormalizeRot( b2Rot q )
return qn;
}

/// Integration rotation from angular velocity
/// Integrate rotation from angular velocity
/// @param q1 initial rotation
/// @param deltaAngle the angular displacement in radians
B2_INLINE b2Rot b2IntegrateRotation( b2Rot q1, float deltaAngle )
Expand Down
2 changes: 1 addition & 1 deletion samples/sample_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,7 @@ class BenchmarkRain : public Sample

Sample::Step( settings );

if (m_stepCount == 1000)
if (m_stepCount % 1000 == 0)
{
m_stepCount += 0;
}
Expand Down
82 changes: 21 additions & 61 deletions samples/sample_collision.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1475,15 +1475,15 @@ class RayCastWorld : public Sample
bodyDef.rotation = b2MakeRot( RandomFloatRange( -B2_PI, B2_PI ) );

int mod = m_bodyIndex % 3;
if (mod == 0)
if ( mod == 0 )
{
bodyDef.type = b2_staticBody;
}
else if (mod == 1)
else if ( mod == 1 )
{
bodyDef.type = b2_kinematicBody;
}
else if (mod == 2)
else if ( mod == 2 )
{
bodyDef.type = b2_dynamicBody;
bodyDef.gravityScale = 0.0f;
Expand Down Expand Up @@ -3417,7 +3417,7 @@ class TimeOfImpact : public Sample
if ( settings.restart == false )
{
g_camera.m_center = { 0.6f, 2.0f };
g_camera.m_center = { -123.750000f, 134.750000f };
g_camera.m_center = { -16, 45 };
g_camera.m_zoom = 5.0f;
}
}
Expand All @@ -3427,59 +3427,20 @@ class TimeOfImpact : public Sample
return new TimeOfImpact( settings );
}

#if 0
- input 0x00000044f14fd550 {proxyA={points=0x00000044f14fd550 {{...}, {...}, {...}, {...}, {...}, {...}, {...}, ...} ...} ...} const b2TOIInput *
- proxyA {points=0x00000044f14fd550 {{x=-123.750000 y=134.750000 }, {x=-123.250000 y=134.750000 }, {x=-123.250000 ...}, ...} ...} b2ShapeProxy
- points 0x00000044f14fd550 {{x=-123.750000 y=134.750000 }, {x=-123.250000 y=134.750000 }, {x=-123.250000 y=135.250000 }, ...} b2Vec2[8]
+ [0] {x=-123.750000 y=134.750000 } b2Vec2
+ [1] {x=-123.250000 y=134.750000 } b2Vec2
+ [2] {x=-123.250000 y=135.250000 } b2Vec2
+ [3] {x=-123.750000 y=135.250000 } b2Vec2
+ [4] {x=-123.905960 y=135.246246 } b2Vec2
+ [5] {x=-123.583496 y=135.491089 } b2Vec2
+ [6] {x=-1.02951760e+30 y=9.529e-44#DEN } b2Vec2
+ [7] {x=8.40272566e-18 y=7.539e-43#DEN } b2Vec2
count 4 int
radius 0.00000000 float
- proxyB {points=0x00000044f14fd598 {{x=0.00000000 y=-0.125000000 }, {x=0.00000000 y=0.125000000 }, {x=-123.250000 ...}, ...} ...} b2ShapeProxy
- points 0x00000044f14fd598 {{x=0.00000000 y=-0.125000000 }, {x=0.00000000 y=0.125000000 }, {x=-123.250000 y=...}, ...} b2Vec2[8]
+ [0] {x=0.00000000 y=-0.125000000 } b2Vec2
+ [1] {x=0.00000000 y=0.125000000 } b2Vec2
+ [2] {x=-123.250000 y=135.250000 } b2Vec2
+ [3] {x=-123.750000 y=135.250000 } b2Vec2
+ [4] {x=-123.905960 y=135.246246 } b2Vec2
+ [5] {x=-123.583496 y=135.491089 } b2Vec2
+ [6] {x=-1.02951760e+30 y=9.529e-44#DEN } b2Vec2
+ [7] {x=8.40272566e-18 y=7.539e-43#DEN } b2Vec2
count 2 int
radius 0.0350000001 float
- sweepA {localCenter={x=0.00000000 y=0.00000000 } c1={x=0.00000000 y=0.00000000 } c2={x=0.00000000 y=0.00000000 } ...} b2Sweep
+ localCenter {x=0.00000000 y=0.00000000 } b2Vec2
+ c1 {x=0.00000000 y=0.00000000 } b2Vec2
+ c2 {x=0.00000000 y=0.00000000 } b2Vec2
+ q1 {c=1.00000000 s=0.00000000 } b2Rot
+ q2 {c=1.00000000 s=0.00000000 } b2Rot
- sweepB {localCenter={x=0.00000000 y=0.00000000 } c1={x=-123.721443 y=135.385178 } c2={x=-123.757744 y=135.334244 } ...} b2Sweep
+ localCenter {x=0.00000000 y=0.00000000 } b2Vec2
+ c1 {x=-123.721443 y=135.385178 } b2Vec2
+ c2 {x=-123.757744 y=135.334244 } b2Vec2
+ q1 {c=0.567239463 s=0.823552966 } b2Rot
+ q2 {c=0.423919678 s=0.905699849 } b2Rot
tMax 1.00000000 float

#endif
void Step( Settings& settings ) override
{
Sample::Step( settings );

b2Sweep sweepA = {
b2Vec2_zero, { 0.0f, 0.0f }, { 0.0f, 0.0f }, b2Rot_identity, b2Rot_identity,
};
b2Sweep sweepB = { b2Vec2_zero,
{ -123.721443f, 135.385178f },
{ -123.757744f, 135.334244f },
{ 0.567239463f, 0.823552966f },
{ 0.423919678f, 0.905699849f } };
b2Sweep sweepB = {
b2Vec2_zero,
{ -15.8332710, 45.3520279 },
{ -15.8324337, 45.3413048 },
{ -0.540891349, 0.841092527 },
{ -0.457797021, 0.889056742 },
};

b2TOIInput input;
input.proxyA = b2MakeProxy( m_verticesA, m_countA, m_radiusA );
Expand Down Expand Up @@ -3535,15 +3496,15 @@ class TimeOfImpact : public Sample

if ( output.state == b2_toiStateHit )
{
b2DistanceInput dinput;
dinput.proxyA = input.proxyA;
dinput.proxyB = input.proxyB;
dinput.transformA = b2GetSweepTransform( &sweepA, output.fraction );
dinput.transformB = b2GetSweepTransform( &sweepB, output.fraction );
dinput.useRadii = false;
b2DistanceInput distanceInput;
distanceInput.proxyA = input.proxyA;
distanceInput.proxyB = input.proxyB;
distanceInput.transformA = b2GetSweepTransform( &sweepA, output.fraction );
distanceInput.transformB = b2GetSweepTransform( &sweepB, output.fraction );
distanceInput.useRadii = false;
b2SimplexCache cache = { 0 };
b2DistanceOutput doutput = b2ShapeDistance( &cache, &dinput, nullptr, 0 );
g_draw.DrawString( 5, m_textLine, "distance = %g", doutput.distance );
b2DistanceOutput distanceOutput = b2ShapeDistance( &cache, &distanceInput, nullptr, 0 );
g_draw.DrawString( 5, m_textLine, "distance = %g", distanceOutput.distance );
m_textLine += m_textIncrement;
}

Expand All @@ -3560,15 +3521,14 @@ class TimeOfImpact : public Sample
#endif
}

b2Vec2 m_verticesA[4] = {
{ -123.750000, 134.750000 }, { -123.250000, 134.750000 }, { -123.250000, 135.250000 }, { -123.750000, 135.250000 } };
b2Vec2 m_verticesA[4] = { { -16.25, 44.75 }, { -15.75, 44.75 }, { -15.75, 45.25 }, { -16.25, 45.25 } };
b2Vec2 m_verticesB[2] = { { 0.0f, -0.125000000f }, { 0.0f, 0.125000000f } };

int m_countA = ARRAY_COUNT( m_verticesA );
int m_countB = ARRAY_COUNT( m_verticesB );

float m_radiusA = 0.0f;
float m_radiusB = 0.0350000001f;
float m_radiusB = 0.0299999993f;
};

static int sampleTimeOfImpact = RegisterSample( "Collision", "Time of Impact", TimeOfImpact::Create );
13 changes: 8 additions & 5 deletions shared/benchmarks.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: MIT

#include "benchmarks.h"

#include "human.h"

#include "box2d/box2d.h"
Expand All @@ -18,8 +19,6 @@

void CreateJointGrid( b2WorldId worldId )
{
// Turning gravity off to isolate joint performance.
//b2World_SetGravity( worldId, b2Vec2_zero );
b2World_EnableSleeping( worldId, false );

int N = BENCHMARK_DEBUG ? 10 : 100;
Expand Down Expand Up @@ -238,16 +237,20 @@ void CreateRain( b2WorldId worldId )

b2ShapeDef shapeDef = b2DefaultShapeDef();
float y = 0.0f;
float w = 0.5f * g_rainData.gridSize;
float h = 0.5f * g_rainData.gridSize;
float width = g_rainData.gridSize;
float height = g_rainData.gridSize;

for ( int i = 0; i < RAIN_ROW_COUNT; ++i )
{
float x = -0.5f * g_rainData.gridCount * g_rainData.gridSize;
for ( int j = 0; j <= g_rainData.gridCount; ++j )
{
b2Polygon box = b2MakeOffsetBox( w, h, ( b2Vec2 ){ x, y }, b2Rot_identity );
b2Polygon box = b2MakeOffsetBox( 0.5f * width, 0.5f * height, ( b2Vec2 ){ x, y }, b2Rot_identity );
b2CreatePolygonShape( groundId, &shapeDef, &box );

//b2Segment segment = { { x - 0.5f * width, y }, { x + 0.5f * width, y } };
//b2CreateSegmentShape( groundId, &shapeDef, &segment );

x += g_rainData.gridSize;
}

Expand Down
2 changes: 1 addition & 1 deletion src/body.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ static void b2DestroyBodyContacts( b2World* world, b2Body* body, bool wakeBodies

b2BodyId b2CreateBody( b2WorldId worldId, const b2BodyDef* def )
{
b2CheckDef( def );
B2_CHECK_DEF( def );
B2_ASSERT( b2IsValidVec2( def->position ) );
B2_ASSERT( b2IsValidRotation( def->rotation ) );
B2_ASSERT( b2IsValidVec2( def->linearVelocity ) );
Expand Down
26 changes: 20 additions & 6 deletions src/broad_phase.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,13 @@ static bool b2PairQueryCallback( int proxyId, int shapeId, void* context )
return true;
}

// Warning: writing to these globals significantly slows multithreading performance
#if B2_SNOOP_PAIR_COUNTERS
b2TreeStats b2_dynamicStats;
b2TreeStats b2_kinematicStats;
b2TreeStats b2_staticStats;
#endif

static void b2FindPairsTask( int startIndex, int endIndex, uint32_t threadIndex, void* context )
{
b2TracyCZoneNC( pair_task, "Pair Task", b2_colorAquamarine, true );
Expand Down Expand Up @@ -341,20 +348,27 @@ static void b2FindPairsTask( int startIndex, int endIndex, uint32_t threadIndex,

// Query trees. Only dynamic proxies collide with kinematic and static proxies.
// Using B2_DEFAULT_MASK_BITS so that b2Filter::groupIndex works.
b2TreeStats stats = { 0 };
if ( proxyType == b2_dynamicBody )
{
// consider using bits = groupIndex > 0 ? B2_DEFAULT_MASK_BITS : maskBits
queryContext.queryTreeType = b2_kinematicBody;
b2DynamicTree_Query( bp->trees + b2_kinematicBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext );
b2TreeStats statsKinematic = b2DynamicTree_Query( bp->trees + b2_kinematicBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext );
stats.nodeVisits += statsKinematic.nodeVisits;
stats.leafVisits += statsKinematic.leafVisits;

queryContext.queryTreeType = b2_staticBody;
b2DynamicTree_Query( bp->trees + b2_staticBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext );
b2TreeStats statsStatic = b2DynamicTree_Query( bp->trees + b2_staticBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext );
stats.nodeVisits += statsStatic.nodeVisits;
stats.leafVisits += statsStatic.leafVisits;
}

// All proxies collide with dynamic proxies
// Using B2_DEFAULT_MASK_BITS so that b2Filter::groupIndex works.
queryContext.queryTreeType = b2_dynamicBody;
b2DynamicTree_Query( bp->trees + b2_dynamicBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext );
b2TreeStats statsDynamic = b2DynamicTree_Query( bp->trees + b2_dynamicBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext );
stats.nodeVisits += statsDynamic.nodeVisits;
stats.leafVisits += statsDynamic.leafVisits;
}

b2TracyCZoneEnd( pair_task );
Expand Down Expand Up @@ -382,9 +396,9 @@ void b2UpdateBroadPhasePairs( b2World* world )
bp->movePairs = b2AllocateArenaItem( alloc, bp->movePairCapacity * sizeof( b2MovePair ), "move pairs" );
bp->movePairIndex = 0;

#ifndef NDEBUG
extern _Atomic int g_probeCount;
g_probeCount = 0;
#if B2_SNOOP_TABLE_COUNTERS
extern _Atomic int b2_probeCount;
b2_probeCount = 0;
#endif

int minRange = 64;
Expand Down
4 changes: 4 additions & 0 deletions src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extern float b2_lengthUnitsPerMeter;

// A small length used as a collision and constraint tolerance. Usually it is
// chosen to be numerically significant, but visually insignificant. In meters.
// Normally this is 0.5cm.
// @warning modifying this can have a significant impact on stability
#define B2_LINEAR_SLOP ( 0.005f * b2_lengthUnitsPerMeter )

Expand All @@ -29,11 +30,14 @@ extern float b2_lengthUnitsPerMeter;
// @warning increasing this to 0.5f * b2_pi or greater will break continuous collision.
#define B2_MAX_ROTATION ( 0.25f * B2_PI )

// Box2D uses limited speculative collision. This reduces jitter.
// Normally this is 2cm.
// @warning modifying this can have a significant impact on performance and stability
#define B2_SPECULATIVE_DISTANCE ( 4.0f * B2_LINEAR_SLOP )

// This is used to fatten AABBs in the dynamic tree. This allows proxies
// to move by a small amount without triggering a tree adjustment. This is in meters.
// Normally this is 5cm.
// @warning modifying this can have a significant impact on performance
#define B2_AABB_MARGIN ( 0.05f * b2_lengthUnitsPerMeter )

Expand Down
Loading

0 comments on commit b2a55b4

Please sign in to comment.