blob: 787e8a43795cecf82a4169f26af1a700f370271d [file] [log] [blame] [edit]
// Copyright 2013 The Emscripten Authors. All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License. Both these licenses can be
// found in the LICENSE file.
//
// Based on joelgwebber's Box2D benchmarks,
// https://github.com/joelgwebber/bench2d/blob/master/c/Bench2d.cpp
//
// Settings =====================
// Turn this on to include the y-position of the top box in the output.
#define DEBUG 0
int WARMUP;
int FRAMES;
typedef struct {
float mean;
float stddev;
} result_t;
// ==============================
#include <cstdio>
#include <time.h>
#include <math.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#if NO_PRINTING
#define printf(fmt, ...) (0)
#endif
#include "Box2D/Box2D.h"
using namespace std;
const int e_count = 40;
result_t measure(clock_t *times) {
float values[FRAMES];
result_t r;
float total = 0;
for (int i = 0; i < FRAMES; ++i) {
values[i] = (float)times[i] / CLOCKS_PER_SEC * 1000;
total += values[i];
}
r.mean = total / FRAMES;
float variance = 0;
for (int i = 0; i < FRAMES; ++i) {
float diff = values[i] - r.mean;
variance += diff * diff;
}
r.stddev = sqrt(variance / FRAMES);
return r;
}
b2World *world;
clock_t *times, minn = CLOCKS_PER_SEC * 1000 * 100, maxx = -1;
b2Body* topBody;
int32 frameCounter = 0;
void iter();
int main(int argc, char **argv) {
int arg = argc > 1 ? argv[1][0] - '0' : 3;
switch(arg) {
case 0: return 0; break;
case 1: WARMUP = 5; FRAMES = 35; break;
case 2: WARMUP = 32; FRAMES = 161; break;
case 3: WARMUP = 64; FRAMES = 333; break;
case 4: WARMUP = 5*64; FRAMES = 7*333; break;
case 5: WARMUP = 10*64; FRAMES = 17*333; break;
default: printf("error: %d\\n", arg); return -1;
}
// do not split out warmup, do not ignore initial stalls
FRAMES += WARMUP;
WARMUP = 0;
times = new clock_t[FRAMES];
// Define the gravity vector.
b2Vec2 gravity(0.0f, -10.0f);
// Construct a world object, which will hold and simulate the rigid bodies.
world = new b2World(gravity);
world->SetAllowSleeping(false);
{
b2BodyDef bd;
b2Body* ground = world->CreateBody(&bd);
b2EdgeShape shape;
shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
ground->CreateFixture(&shape, 0.0f);
}
{
float32 a = 0.5f;
b2PolygonShape shape;
shape.SetAsBox(a, a);
b2Vec2 x(-7.0f, 0.75f);
b2Vec2 y;
b2Vec2 deltaX(0.5625f, 1);
b2Vec2 deltaY(1.125f, 0.0f);
for (int32 i = 0; i < e_count; ++i) {
y = x;
for (int32 j = i; j < e_count; ++j) {
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position = y;
b2Body* body = world->CreateBody(&bd);
body->CreateFixture(&shape, 5.0f);
topBody = body;
y += deltaY;
}
x += deltaX;
}
}
for (int32 i = 0; i < WARMUP; ++i) {
world->Step(1.0f/60.0f, 3, 3);
}
do {
iter();
} while (frameCounter <= FRAMES);
return 0;
}
void iter() {
if (frameCounter < FRAMES) {
clock_t start = clock();
world->Step(1.0f/60.0f, 3, 3);
clock_t end = clock();
clock_t curr = end - start;
times[frameCounter] = curr;
if (curr < minn) minn = curr;
if (curr > maxx) maxx = curr;
#if DEBUG
printf("%f :: ", topBody->GetPosition().y);
printf("%f\n", (float32)(end - start) / CLOCKS_PER_SEC * 1000);
#endif
frameCounter++;
return;
}
// that's it!
frameCounter++;
result_t result = measure(times);
printf("frame averages: %.3f +- %.3f, range: %.3f to %.3f \n", result.mean, result.stddev, float(minn)/CLOCKS_PER_SEC * 1000, float(maxx)/CLOCKS_PER_SEC * 1000);
}