Commit 43c59cc3 authored by Kenton Varda's avatar Kenton Varda

Benchmark case: car sales

parent f8b5d71d
......@@ -10,10 +10,10 @@ continuous:
CXX=g++-4.7 CXXFLAGS='-std=gnu++0x -g -Wall' LIBS='-lz -pthread' ekam -j6 -c -n :51315
continuous-opt:
CXX=g++-4.7 CXXFLAGS='-std=gnu++0x -O2 -DNDEBUG -Wall' LIBS='-lz -lprofiler -pthread' ekam -j6 -c -n :51315
CXX=g++-4.7 CXXFLAGS='-std=gnu++0x -O2 -DNDEBUG -Wall' LIBS='-lz -pthread' ekam -j6 -c -n :51315
continuous-prof:
CXX=g++-4.7 CXXFLAGS='-std=gnu++0x -O2 -DNDEBUG -Wall -pg' LIBS='-pg -lz -pthread' ekam -j6 -c -n :51315
continuous-opt3:
CXX=g++-4.7 CXXFLAGS='-std=gnu++0x -O3 -DNDEBUG -Wall' LIBS='-lz -pthread' ekam -j6 -c -n :51315
clean:
rm -rf bin lib tmp
......
......@@ -22,6 +22,7 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "benchmark.capnp.h"
#include <limits>
#include <capnproto/serialize.h>
#include <capnproto/serialize-snappy.h>
#include <unistd.h>
......@@ -37,6 +38,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <semaphore.h>
#include "fast-random.h"
namespace capnproto {
namespace benchmark {
......@@ -118,23 +120,23 @@ inline int32_t mod(int32_t a, int32_t b) {
return a % b;
}
int32_t makeExpression(Expression::Builder exp, int depth) {
// TODO: Operation_MAX or something.
exp.setOp((Operation)(rand() % (int)Operation::MODULUS + 1));
int32_t makeExpression(Expression::Builder exp, uint depth) {
// TODO: Operation_RANGE or something.
exp.setOp((Operation)(fastRand((int)Operation::MODULUS + 1)));
uint32_t left, right;
if (rand() % 8 < depth) {
if (fastRand(8) < depth) {
exp.setLeftIsValue(true);
left = rand() % 128 + 1;
left = fastRand(128) + 1;
exp.setLeftValue(left);
} else {
left = makeExpression(exp.initLeftExpression(), depth + 1);
}
if (rand() % 8 < depth) {
if (fastRand(8) < depth) {
exp.setRightIsValue(true);
right = rand() % 128 + 1;
right = fastRand(128) + 1;
exp.setRightValue(right);
} else {
right = makeExpression(exp.initRightExpression(), depth + 1);
......@@ -214,7 +216,7 @@ public:
// The promotion multiplier is large enough that all the results mentioning "cat" but not "dog"
// should end up at the front ofthe list, which is how we verify the result.
static const char* WORDS[] = {
static const char* const WORDS[] = {
"foo ", "bar ", "baz ", "qux ", "quux ", "corge ", "grault ", "garply ", "waldo ", "fred ",
"plugh ", "xyzzy ", "thud "
};
......@@ -237,7 +239,7 @@ public:
typedef int Expectation;
static int setupRequest(SearchResultList::Builder request) {
int count = rand() % 1000;
int count = fastRand(1000);
int goodCount = 0;
auto list = request.initResults(count);
......@@ -245,7 +247,7 @@ public:
for (int i = 0; i < count; i++) {
SearchResult::Builder result = list[i];
result.setScore(1000 - i);
int urlSize = rand() % 100;
int urlSize = fastRand(100);
static const char URL_PREFIX[] = "http://example.com/";
auto url = result.initUrl(urlSize + sizeof(URL_PREFIX));
......@@ -253,28 +255,28 @@ public:
strcpy(url.data(), URL_PREFIX);
char* pos = url.data() + strlen(URL_PREFIX);
for (int j = 0; j < urlSize; j++) {
*pos++ = 'a' + rand() % 26;
*pos++ = 'a' + fastRand(26);
}
bool isCat = rand() % 8 == 0;
bool isDog = rand() % 8 == 0;
bool isCat = fastRand(8) == 0;
bool isDog = fastRand(8) == 0;
goodCount += isCat && !isDog;
static std::string snippet;
snippet.clear();
snippet.push_back(' ');
int prefix = rand() % 20;
int prefix = fastRand(20);
for (int j = 0; j < prefix; j++) {
snippet.append(WORDS[rand() % WORDS_COUNT]);
snippet.append(WORDS[fastRand(WORDS_COUNT)]);
}
if (isCat) snippet.append("cat ");
if (isDog) snippet.append("dog ");
int suffix = rand() % 20;
int suffix = fastRand(20);
for (int j = 0; j < suffix; j++) {
snippet.append(WORDS[rand() % WORDS_COUNT]);
snippet.append(WORDS[fastRand(WORDS_COUNT)]);
}
result.setSnippet(snippet);
......@@ -324,6 +326,112 @@ public:
}
};
// =======================================================================================
// Test case: Car Sales
//
// We have a parking lot full of cars and we want to know how much they are worth.
template <typename ReaderOrBuilder>
uint64_t carValue(ReaderOrBuilder car) {
// Do not think too hard about realism.
uint64_t result = 0;
result += car.getSeats() * 200;
result += car.getDoors() * 350;
for (auto wheel: car.getWheels()) {
result += wheel.getDiameter() * wheel.getDiameter();
result += wheel.getSnowTires() ? 100 : 0;
}
result += car.getLength() * car.getWidth() * car.getHeight() / 50;
auto engine = car.getEngine();
result += engine.getHorsepower() * 40;
if (engine.getUsesElectric()) {
if (engine.getUsesGas()) {
// hybrid
result += 5000;
} else {
result += 3000;
}
}
result += car.getHasPowerWindows() ? 100 : 0;
result += car.getHasPowerSteering() ? 200 : 0;
result += car.getHasCruiseControl() ? 400 : 0;
result += car.getHasNavSystem() ? 2000 : 0;
result += car.getCupHolders() * 25;
return result;
}
void randomCar(Car::Builder car) {
// Do not think too hard about realism.
static const char* const MAKES[] = { "Toyota", "GM", "Ford", "Honda", "Tesla" };
static const char* const MODELS[] = { "Camry", "Prius", "Volt", "Accord", "Leaf", "Model S" };
car.setMake(MAKES[fastRand(sizeof(MAKES) / sizeof(MAKES[0]))]);
car.setModel(MODELS[fastRand(sizeof(MODELS) / sizeof(MODELS[0]))]);
// TODO: Color_RANGE or something.
car.setColor((Color)fastRand((uint)Color::SILVER + 1));
car.setSeats(2 + fastRand(6));
car.setDoors(2 + fastRand(3));
for (auto wheel: car.initWheels(4)) {
wheel.setDiameter(25 + fastRand(15));
wheel.setAirPressure(30 + fastRandDouble(20));
wheel.setSnowTires(fastRand(16) == 0);
}
car.setLength(170 + fastRand(150));
car.setWidth(48 + fastRand(36));
car.setHeight(54 + fastRand(48));
car.setWeight(car.getLength() * car.getWidth() * car.getHeight() / 200);
auto engine = car.initEngine();
engine.setHorsepower(100 * fastRand(400));
engine.setCylinders(4 + 2 * fastRand(3));
engine.setCc(800 + fastRand(10000));
car.setFuelCapacity(10.0 + fastRandDouble(30.0));
car.setFuelLevel(fastRandDouble(car.getFuelCapacity()));
car.setHasPowerWindows(fastRand(2));
car.setHasPowerSteering(fastRand(2));
car.setHasCruiseControl(fastRand(2));
car.setCupHolders(fastRand(12));
car.setHasNavSystem(fastRand(2));
}
class CarSalesTestCase {
public:
typedef ParkingLot Request;
typedef TotalValue Response;
typedef uint64_t Expectation;
static uint64_t setupRequest(ParkingLot::Builder request) {
uint64_t result = 0;
for (auto car: request.initCars(fastRand(200))) {
randomCar(car);
result += carValue(car);
}
return result;
}
static void handleRequest(ParkingLot::Reader request, TotalValue::Builder response) {
uint64_t result = 0;
for (auto car: request.getCars()) {
result += carValue(car);
}
response.setAmount(result);
}
static inline bool checkResponse(TotalValue::Reader response, uint64_t expected) {
return response.getAmount() == expected;
}
};
// =======================================================================================
class CountingOutputStream: public FdOutputStream {
......@@ -703,7 +811,6 @@ int main(int argc, char* argv[]) {
}
uint64_t iters = strtoull(argv[5], nullptr, 0);
srand(123);
uint64_t throughput;
......@@ -712,6 +819,8 @@ int main(int argc, char* argv[]) {
throughput = doBenchmark3<ExpressionTestCase>(argv[2], argv[3], argv[4], iters);
} else if (testcase == "catrank") {
throughput = doBenchmark3<CatRankTestCase>(argv[2], argv[3], argv[4], iters);
} else if (testcase == "carsales") {
throughput = doBenchmark3<CarSalesTestCase>(argv[2], argv[3], argv[4], iters);
} else {
std::cerr << "Unknown test case: " << testcase << std::endl;
return 1;
......
......@@ -30,6 +30,8 @@
#include <stdexcept>
#include <algorithm>
#include <string.h>
#include <limits>
#include "fast-random.h"
namespace capnproto {
namespace benchmark {
......@@ -64,7 +66,7 @@ enum class Operation {
DIVIDE,
MODULUS
};
uint Operation_MAX = static_cast<uint>(Operation::MODULUS) + 1;
uint OPERATION_RANGE = static_cast<uint>(Operation::MODULUS) + 1;
struct Expression {
Operation op;
......@@ -97,14 +99,14 @@ inline int32_t mod(int32_t a, int32_t b) {
return a % b;
}
int32_t makeExpression(Expression* exp, int depth) {
exp->op = (Operation)(rand() % Operation_MAX);
int32_t makeExpression(Expression* exp, uint depth) {
exp->op = (Operation)(fastRand(OPERATION_RANGE));
int32_t left, right;
if (rand() % 8 < depth) {
if (fastRand(8) < depth) {
exp->leftIsValue = true;
left = rand() % 128 + 1;
left = fastRand(128) + 1;
exp->leftValue = left;
} else {
exp->leftIsValue = false;
......@@ -112,9 +114,9 @@ int32_t makeExpression(Expression* exp, int depth) {
left = makeExpression(exp->leftExpression, depth + 1);
}
if (rand() % 8 < depth) {
if (fastRand(8) < depth) {
exp->rightIsValue = true;
right = rand() % 128 + 1;
right = fastRand(128) + 1;
exp->rightValue = right;
} else {
exp->rightIsValue = false;
......@@ -200,7 +202,7 @@ public:
// The promotion multiplier is large enough that all the results mentioning "cat" but not "dog"
// should end up at the front ofthe list, which is how we verify the result.
static const char* WORDS[] = {
static const char* const WORDS[] = {
"foo ", "bar ", "baz ", "qux ", "quux ", "corge ", "grault ", "garply ", "waldo ", "fred ",
"plugh ", "xyzzy ", "thud "
};
......@@ -213,6 +215,12 @@ struct List {
inline T* begin() const { return items; }
inline T* end() const { return items + size; }
inline List<T>& init(size_t size) {
this->size = size;
items = allocate<T>(size);
return *this;
}
};
struct SearchResult {
......@@ -238,11 +246,10 @@ public:
typedef int Expectation;
static int setupRequest(List<SearchResult>* request) {
int count = rand() % 1000;
int count = fastRand(1000);
int goodCount = 0;
request->size = count;
request->items = allocate<SearchResult>(count);
request->init(count);
for (int i = 0; i < count; i++) {
SearchResult& result = request->items[i];
result.score = 1000 - i;
......@@ -251,9 +258,9 @@ public:
strcpy(pos, "http://example.com/");
pos += strlen("http://example.com/");
int urlSize = rand() % 100;
int urlSize = fastRand(100);
for (int j = 0; j < urlSize; j++) {
*pos++ = 'a' + rand() % 26;
*pos++ = 'a' + fastRand(26);
}
*pos++ = '\0';
......@@ -262,8 +269,8 @@ public:
throw std::bad_alloc();
}
bool isCat = rand() % 8 == 0;
bool isDog = rand() % 8 == 0;
bool isCat = fastRand(8) == 0;
bool isDog = fastRand(8) == 0;
goodCount += isCat && !isDog;
pos = reinterpret_cast<char*>(arenaPos);
......@@ -271,9 +278,9 @@ public:
*pos++ = ' ';
int prefix = rand() % 20;
int prefix = fastRand(20);
for (int j = 0; j < prefix; j++) {
const char* word = WORDS[rand() % WORDS_COUNT];
const char* word = WORDS[fastRand(WORDS_COUNT)];
size_t len = strlen(word);
memcpy(pos, word, len);
pos += len;
......@@ -288,9 +295,9 @@ public:
pos += 4;
}
int suffix = rand() % 20;
int suffix = fastRand(20);
for (int j = 0; j < suffix; j++) {
const char* word = WORDS[rand() % WORDS_COUNT];
const char* word = WORDS[fastRand(WORDS_COUNT)];
size_t len = strlen(word);
memcpy(pos, word, len);
pos += len;
......@@ -324,8 +331,7 @@ public:
std::sort(scoredResults.begin(), scoredResults.end());
response->size = scoredResults.size();
response->items = allocate<SearchResult>(scoredResults.size());
response->init(scoredResults.size());
SearchResult* dst = response->items;
for (auto& result: scoredResults) {
dst->url = copyString(result.result->url);
......@@ -350,6 +356,157 @@ public:
}
};
// =======================================================================================
// Test case: Car Sales
//
// We have a parking lot full of cars and we want to know how much they are worth.
enum class Color {
BLACK,
WHITE,
RED,
GREEN,
BLUE,
CYAN,
MAGENTA,
YELLOW,
SILVER
};
constexpr uint COLOR_RANGE = static_cast<uint>(Color::SILVER) + 1;
struct Wheel {
uint16_t diameter;
float airPressure;
bool snowTires;
};
struct Engine {
uint16_t horsepower;
uint8_t cylinders;
uint32_t cc;
bool usesGas;
bool usesElectric;
};
struct Car {
const char* make;
const char* model;
Color color;
uint8_t seats;
uint8_t doors;
List<Wheel> wheels;
uint16_t length;
uint16_t width;
uint16_t height;
uint32_t weight;
Engine engine;
float fuelCapacity;
float fuelLevel;
bool hasPowerWindows;
bool hasPowerSteering;
bool hasCruiseControl;
uint8_t cupHolders;
bool hasNavSystem;
};
uint64_t carValue(const Car& car) {
// Do not think too hard about realism.
uint64_t result = 0;
result += car.seats * 200;
result += car.doors * 350;
for (auto wheel: car.wheels) {
result += wheel.diameter * wheel.diameter;
result += wheel.snowTires ? 100 : 0;
}
result += car.length * car.width * car.height / 50;
auto engine = car.engine;
result += engine.horsepower * 40;
if (engine.usesElectric) {
if (engine.usesGas) {
// hybrid
result += 5000;
} else {
result += 3000;
}
}
result += car.hasPowerWindows ? 100 : 0;
result += car.hasPowerSteering ? 200 : 0;
result += car.hasCruiseControl ? 400 : 0;
result += car.hasNavSystem ? 2000 : 0;
result += car.cupHolders * 25;
return result;
}
void randomCar(Car* car) {
// Do not think too hard about realism.
static const char* const MAKES[] = { "Toyota", "GM", "Ford", "Honda", "Tesla" };
static const char* const MODELS[] = { "Camry", "Prius", "Volt", "Accord", "Leaf", "Model S" };
car->make = copyString(MAKES[fastRand(sizeof(MAKES) / sizeof(MAKES[0]))]);
car->model = copyString(MODELS[fastRand(sizeof(MODELS) / sizeof(MODELS[0]))]);
car->color = (Color)fastRand(COLOR_RANGE);
car->seats = 2 + fastRand(6);
car->doors = 2 + fastRand(3);
for (auto& wheel: car->wheels.init(4)) {
wheel.diameter = 25 + fastRand(15);
wheel.airPressure = 30 + fastRandDouble(20);
wheel.snowTires = fastRand(16) == 0;
}
car->length = 170 + fastRand(150);
car->width = 48 + fastRand(36);
car->height = 54 + fastRand(48);
car->weight = car->length * car->width * car->height / 200;
car->engine.horsepower = 100 * fastRand(400);
car->engine.cylinders = 4 + 2 * fastRand(3);
car->engine.cc = 800 + fastRand(10000);
car->fuelCapacity = 10.0 + fastRandDouble(30.0);
car->fuelLevel = fastRandDouble(car->fuelCapacity);
car->hasPowerWindows = fastRand(2);
car->hasPowerSteering = fastRand(2);
car->hasCruiseControl = fastRand(2);
car->cupHolders = fastRand(12);
car->hasNavSystem = fastRand(2);
}
class CarSalesTestCase {
public:
typedef List<Car> Request;
typedef uint64_t Response;
typedef uint64_t Expectation;
static uint64_t setupRequest(List<Car>* request) {
uint64_t result = 0;
for (auto& car: request->init(fastRand(200))) {
randomCar(&car);
result += carValue(car);
}
return result;
}
static void handleRequest(const List<Car>& request, uint64_t* response) {
*response = 0;
for (auto& car: request) {
*response += carValue(car);
}
}
static inline bool checkResponse(uint64_t response, uint64_t expected) {
return response == expected;
}
};
// =======================================================================================
struct SingleUseObjects {
......@@ -416,7 +573,6 @@ int main(int argc, char* argv[]) {
}
uint64_t iters = strtoull(argv[5], nullptr, 0);
srand(123);
uint64_t throughput;
......@@ -425,6 +581,8 @@ int main(int argc, char* argv[]) {
throughput = doBenchmark<ExpressionTestCase>(argv[2], iters);
} else if (testcase == "catrank") {
throughput = doBenchmark<CatRankTestCase>(argv[2], iters);
} else if (testcase == "carsales") {
throughput = doBenchmark<CarSalesTestCase>(argv[2], iters);
} else {
std::cerr << "Unknown test case: " << testcase << std::endl;
return 1;
......
......@@ -23,6 +23,7 @@
#include "benchmark.pb.h"
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <limits>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
......@@ -37,6 +38,7 @@
#include <semaphore.h>
#include <snappy/snappy.h>
#include <snappy/snappy-sinksource.h>
#include "fast-random.h"
namespace capnproto {
namespace benchmark {
......@@ -118,20 +120,20 @@ inline int32_t mod(int32_t a, int32_t b) {
return a % b;
}
int32_t makeExpression(Expression* exp, int depth) {
exp->set_op((Operation)(rand() % Operation_MAX + 1));
int32_t makeExpression(Expression* exp, uint depth) {
exp->set_op((Operation)(fastRand(Operation_MAX + 1)));
int32_t left, right;
if (rand() % 8 < depth) {
left = rand() % 128 + 1;
if (fastRand(8) < depth) {
left = fastRand(128) + 1;
exp->set_left_value(left);
} else {
left = makeExpression(exp->mutable_left_expression(), depth + 1);
}
if (rand() % 8 < depth) {
right = rand() % 128 + 1;
if (fastRand(8) < depth) {
right = fastRand(128) + 1;
exp->set_right_value(right);
} else {
right = makeExpression(exp->mutable_right_expression(), depth + 1);
......@@ -209,7 +211,7 @@ public:
// The promotion multiplier is large enough that all the results mentioning "cat" but not "dog"
// should end up at the front ofthe list, which is how we verify the result.
static const char* WORDS[] = {
static const char* const WORDS[] = {
"foo ", "bar ", "baz ", "qux ", "quux ", "corge ", "grault ", "garply ", "waldo ", "fred ",
"plugh ", "xyzzy ", "thud "
};
......@@ -232,7 +234,7 @@ public:
typedef int Expectation;
static int setupRequest(SearchResultList* request) {
int count = rand() % 1000;
int count = fastRand(1000);
int goodCount = 0;
for (int i = 0; i < count; i++) {
......@@ -240,29 +242,29 @@ public:
result->set_score(1000 - i);
result->set_url("http://example.com/");
std::string* url = result->mutable_url();
int urlSize = rand() % 100;
int urlSize = fastRand(100);
for (int j = 0; j < urlSize; j++) {
url->push_back('a' + rand() % 26);
url->push_back('a' + fastRand(26));
}
bool isCat = rand() % 8 == 0;
bool isDog = rand() % 8 == 0;
bool isCat = fastRand(8) == 0;
bool isDog = fastRand(8) == 0;
goodCount += isCat && !isDog;
std::string* snippet = result->mutable_snippet();
snippet->push_back(' ');
int prefix = rand() % 20;
int prefix = fastRand(20);
for (int j = 0; j < prefix; j++) {
snippet->append(WORDS[rand() % WORDS_COUNT]);
snippet->append(WORDS[fastRand(WORDS_COUNT)]);
}
if (isCat) snippet->append("cat ");
if (isDog) snippet->append("dog ");
int suffix = rand() % 20;
int suffix = fastRand(20);
for (int j = 0; j < suffix; j++) {
snippet->append(WORDS[rand() % WORDS_COUNT]);
snippet->append(WORDS[fastRand(WORDS_COUNT)]);
}
}
......@@ -307,6 +309,113 @@ public:
}
};
// =======================================================================================
// Test case: Car Sales
//
// We have a parking lot full of cars and we want to know how much they are worth.
uint64_t carValue(const Car& car) {
// Do not think too hard about realism.
uint64_t result = 0;
result += car.seats() * 200;
result += car.doors() * 350;
for (auto& wheel: car.wheel()) {
result += wheel.diameter() * wheel.diameter();
result += wheel.snow_tires() ? 100 : 0;
}
result += car.length() * car.width() * car.height() / 50;
const Engine& engine = car.engine();
result += engine.horsepower() * 40;
if (engine.uses_electric()) {
if (engine.uses_gas()) {
// hybrid
result += 5000;
} else {
result += 3000;
}
}
result += car.has_power_windows() ? 100 : 0;
result += car.has_power_steering() ? 200 : 0;
result += car.has_cruise_control() ? 400 : 0;
result += car.has_nav_system() ? 2000 : 0;
result += car.cup_holders() * 25;
return result;
}
void randomCar(Car* car) {
// Do not think too hard about realism.
static const char* const MAKES[] = { "Toyota", "GM", "Ford", "Honda", "Tesla" };
static const char* const MODELS[] = { "Camry", "Prius", "Volt", "Accord", "Leaf", "Model S" };
car->set_make(MAKES[fastRand(sizeof(MAKES) / sizeof(MAKES[0]))]);
car->set_model(MODELS[fastRand(sizeof(MODELS) / sizeof(MODELS[0]))]);
car->set_color((Color)fastRand(Color_MAX));
car->set_seats(2 + fastRand(6));
car->set_doors(2 + fastRand(3));
for (uint i = 0; i < 4; i++) {
Wheel* wheel = car->add_wheel();
wheel->set_diameter(25 + fastRand(15));
wheel->set_air_pressure(30 + fastRandDouble(20));
wheel->set_snow_tires(fastRand(16) == 0);
}
car->set_length(170 + fastRand(150));
car->set_width(48 + fastRand(36));
car->set_height(54 + fastRand(48));
car->set_weight(car->length() * car->width() * car->height() / 200);
Engine* engine = car->mutable_engine();
engine->set_horsepower(100 * fastRand(400));
engine->set_cylinders(4 + 2 * fastRand(3));
engine->set_cc(800 + fastRand(10000));
car->set_fuel_capacity(10.0 + fastRandDouble(30.0));
car->set_fuel_level(fastRandDouble(car->fuel_capacity()));
car->set_has_power_windows(fastRand(2));
car->set_has_power_steering(fastRand(2));
car->set_has_cruise_control(fastRand(2));
car->set_cup_holders(fastRand(12));
car->set_has_nav_system(fastRand(2));
}
class CarSalesTestCase {
public:
typedef ParkingLot Request;
typedef TotalValue Response;
typedef uint64_t Expectation;
static uint64_t setupRequest(ParkingLot* request) {
uint count = fastRand(200);
uint64_t result = 0;
for (uint i = 0; i < count; i++) {
Car* car = request->add_car();
randomCar(car);
result += carValue(*car);
}
return result;
}
static void handleRequest(const ParkingLot& request, TotalValue* response) {
uint64_t result = 0;
for (auto& car: request.car()) {
result += carValue(car);
}
response->set_amount(result);
}
static inline bool checkResponse(const TotalValue& response, uint64_t expected) {
return response.amount() == expected;
}
};
// =======================================================================================
struct SingleUseMessages {
......@@ -736,7 +845,6 @@ int main(int argc, char* argv[]) {
}
uint64_t iters = strtoull(argv[5], nullptr, 0);
srand(123);
uint64_t throughput;
......@@ -745,6 +853,8 @@ int main(int argc, char* argv[]) {
throughput = doBenchmark3<ExpressionTestCase>(argv[2], argv[3], argv[4], iters);
} else if (testcase == "catrank") {
throughput = doBenchmark3<CatRankTestCase>(argv[2], argv[3], argv[4], iters);
} else if (testcase == "carsales") {
throughput = doBenchmark3<CarSalesTestCase>(argv[2], argv[3], argv[4], iters);
} else {
std::cerr << "Unknown test case: " << testcase << std::endl;
return 1;
......
......@@ -90,7 +90,8 @@ enum class Product {
enum class TestCase {
EVAL,
CATRANK
CATRANK,
CARSALES
};
enum class Mode {
......@@ -134,6 +135,9 @@ TestResult runTest(Product product, TestCase testCase, Mode mode, Reuse reuse,
case TestCase::CATRANK:
argv[1] = strdup("catrank");
break;
case TestCase::CARSALES:
argv[1] = strdup("carsales");
break;
}
switch (mode) {
......@@ -342,6 +346,8 @@ int main(int argc, char* argv[]) {
mode = Mode::BYTES;
} else if (arg == "eval") {
testCase = TestCase::EVAL;
} else if (arg == "carsales") {
testCase = TestCase::CARSALES;
} else if (arg == "no-reuse") {
reuse = Reuse::NO;
} else if (arg == "snappy") {
......@@ -356,6 +362,9 @@ int main(int argc, char* argv[]) {
case TestCase::CATRANK:
iters *= 1000;
break;
case TestCase::CARSALES:
iters *= 20000;
break;
}
cout << "Running " << iters << " iterations of ";
......@@ -366,6 +375,9 @@ int main(int argc, char* argv[]) {
case TestCase::CATRANK:
cout << "CatRank";
break;
case TestCase::CARSALES:
cout << "car sales";
break;
}
cout << " example case with:" << endl;
......@@ -404,7 +416,6 @@ int main(int argc, char* argv[]) {
break;
}
cout << endl;
reportTableHeader();
TestResult nullCase = runTest(
......@@ -417,19 +428,19 @@ int main(int argc, char* argv[]) {
Product::PROTOBUF, testCase, Mode::OBJECT_SIZE, reuse, compression, iters).throughput;
reportResults("Protobuf pass-by-object", iters, protobufBase);
TestResult protobuf = runTest(
Product::PROTOBUF, testCase, mode, reuse, compression, iters);
reportResults("Protobuf end-to-end", iters, protobuf);
TestResult capnpBase = runTest(
Product::CAPNPROTO, testCase, Mode::OBJECTS, reuse, compression, iters);
capnpBase.throughput = runTest(
Product::CAPNPROTO, testCase, Mode::OBJECT_SIZE, reuse, compression, iters).throughput;
reportResults("Cap'n Proto pass-by-object", iters, capnpBase);
TestResult protobuf = runTest(
Product::PROTOBUF, testCase, mode, reuse, compression, iters);
reportResults("Protobuf pass-by-I/O", iters, protobuf);
TestResult capnp = runTest(
Product::CAPNPROTO, testCase, mode, reuse, compression, iters);
reportResults("Cap'n Proto end-to-end", iters, capnp);
reportResults("Cap'n Proto pass-by-I/O", iters, capnp);
cout << endl;
......@@ -438,7 +449,7 @@ int main(int argc, char* argv[]) {
nullCase.throughput, protobufBase.throughput, capnpBase.throughput, iters);
reportComparison("object manipulation",
nullCase.time.cpu(), protobufBase.time.cpu(), capnpBase.time.cpu(), iters);
reportComparison("I/O overhead", "us",
reportComparison("I/O", "us",
(protobuf.time.cpu() - protobufBase.time.cpu()) / 1000.0,
(capnp.time.cpu() - capnpBase.time.cpu()) / 1000.0, iters);
......
......@@ -58,3 +58,60 @@ struct SearchResult {
score@1: Float64;
snippet@2: Text;
}
# ========================================================================================
struct ParkingLot {
cars@0: List(Car);
}
struct TotalValue {
amount@0: UInt64;
}
struct Car {
make@0: Text;
model@1: Text;
color@2: Color;
seats@3: UInt8;
doors@4: UInt8;
wheels@5: List(Wheel);
length@6: UInt16;
width@7: UInt16;
height@8: UInt16;
weight@9: UInt32;
engine@10: Engine;
fuelCapacity@11: Float32;
fuelLevel@12: Float32;
hasPowerWindows@13: Bool;
hasPowerSteering@14: Bool;
hasCruiseControl@15: Bool;
cupHolders@16: UInt8;
hasNavSystem@17: Bool;
}
enum Color {
black = 0;
white = 1;
red = 2;
green = 3;
blue = 4;
cyan = 5;
magenta = 6;
yellow = 7;
silver = 8;
}
struct Wheel {
diameter@0: UInt16;
airPressure@1: Float32;
snowTires@2: Bool;
}
struct Engine {
horsepower@0: UInt16;
cylinders@1: UInt8;
cc@2: UInt32;
usesGas@3: Bool;
usesElectric@4: Bool;
}
......@@ -56,3 +56,60 @@ message SearchResult {
optional double score = 2;
optional string snippet = 3;
}
// =======================================================================================
message ParkingLot {
repeated Car car = 1;
}
message TotalValue {
required uint64 amount = 1;
}
message Car {
optional string make = 1;
optional string model = 2;
optional Color color = 3;
optional uint32 seats = 4;
optional uint32 doors = 5;
repeated Wheel wheel = 6;
optional uint32 length = 7;
optional uint32 width = 8;
optional uint32 height = 9;
optional uint32 weight = 10;
optional Engine engine = 11;
optional float fuel_capacity = 12;
optional float fuel_level = 13;
optional bool has_power_windows = 14;
optional bool has_power_steering = 15;
optional bool has_cruise_control = 16;
optional uint32 cup_holders = 17;
optional bool has_nav_system = 18;
}
enum Color {
BLACK = 0;
WHITE = 1;
RED = 2;
GREEN = 3;
BLUE = 4;
CYAN = 5;
MAGENTA = 6;
YELLOW = 7;
SILVER = 8;
}
message Wheel {
optional uint32 diameter = 1;
optional float air_pressure = 2;
optional bool snow_tires = 3;
}
message Engine {
optional uint32 horsepower = 1;
optional uint32 cylinders = 2;
optional uint32 cc = 3;
optional bool uses_gas = 4;
optional bool uses_electric = 5;
}
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CAPNPROTO_BENCHMARK_FAST_RANDOM_H_
#define CAPNPROTO_BENCHMARK_FAST_RANDOM_H_
namespace capnproto {
namespace benchmark {
static inline uint32_t nextFastRand() {
static constexpr uint32_t A = 1664525;
static constexpr uint32_t C = 1013904223;
static uint32_t state = C;
state = A * state + C;
return state;
}
static inline uint32_t fastRand(uint32_t range) {
return nextFastRand() % range;
}
static inline double fastRandDouble(double range) {
return nextFastRand() * range / std::numeric_limits<uint32_t>::max();
}
} // namespace capnproto
} // namespace benchmark
#endif // CAPNPROTO_BENCHMARK_FAST_RANDOM_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment