Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
43c59cc3
Commit
43c59cc3
authored
Mar 26, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Benchmark case: car sales
parent
f8b5d71d
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
619 additions
and
68 deletions
+619
-68
Makefile.ekam
c++/Makefile.ekam
+3
-3
benchmark-capnproto.c++
c++/src/capnproto/benchmark/benchmark-capnproto.c++
+127
-18
benchmark-null.c++
c++/src/capnproto/benchmark/benchmark-null.c++
+180
-22
benchmark-protobuf.c++
c++/src/capnproto/benchmark/benchmark-protobuf.c++
+127
-17
benchmark-runner.c++
c++/src/capnproto/benchmark/benchmark-runner.c++
+19
-8
benchmark.capnp
c++/src/capnproto/benchmark/benchmark.capnp
+57
-0
benchmark.proto
c++/src/capnproto/benchmark/benchmark.proto
+57
-0
fast-random.h
c++/src/capnproto/benchmark/fast-random.h
+49
-0
No files found.
c++/Makefile.ekam
View file @
43c59cc3
...
...
@@ -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 -O
2 -DNDEBUG -Wall -pg'
LIBS
=
'-pg
-lz -pthread'
ekam
-j6
-c
-n
:51315
continuous-
opt3
:
CXX
=
g++-4.7
CXXFLAGS
=
'-std=gnu++0x -O
3 -DNDEBUG -Wall'
LIBS
=
'
-lz -pthread'
ekam
-j6
-c
-n
:51315
clean
:
rm
-rf
bin lib tmp
...
...
c++/src/capnproto/benchmark/benchmark-capnproto.c++
View file @
43c59cc3
...
...
@@ -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
,
u
int
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
;
...
...
c++/src/capnproto/benchmark/benchmark-null.c++
View file @
43c59cc3
...
...
@@ -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
O
peration_MAX
=
static_cast
<
uint
>
(
Operation
::
MODULUS
)
+
1
;
uint
O
PERATION_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
,
u
int
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
;
...
...
c++/src/capnproto/benchmark/benchmark-protobuf.c++
View file @
43c59cc3
...
...
@@ -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
,
u
int
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
;
...
...
c++/src/capnproto/benchmark/benchmark-runner.c++
View file @
43c59cc3
...
...
@@ -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
);
...
...
c++/src/capnproto/benchmark/benchmark.capnp
View file @
43c59cc3
...
...
@@ -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;
}
c++/src/capnproto/benchmark/benchmark.proto
View file @
43c59cc3
...
...
@@ -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
;
}
c++/src/capnproto/benchmark/fast-random.h
0 → 100644
View file @
43c59cc3
// 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_
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment