forked from electronicarts/EASTL
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEASTLBenchmark.h
226 lines (158 loc) · 5.78 KB
/
EASTLBenchmark.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/////////////////////////////////////////////////////////////////////////////
// Copyright (c) Electronic Arts Inc. All rights reserved.
/////////////////////////////////////////////////////////////////////////////
#ifndef EASTLBENCHMARK_H
#define EASTLBENCHMARK_H
// Intrinsic control
//
// Our benchmark results are being skewed by inconsistent decisions by the
// VC++ compiler to use intrinsic functions. Additionally, many of our
// benchmarks work on large blocks of elements, whereas intrinsics often
// are an improvement only over small blocks of elements. As a result,
// enabling of intrinsics is often resulting in poor benchmark results for
// code that gets an intrinsic enabled for it, even though it will often
// happen in real code to be the opposite case. The disabling of intrinsics
// here often results in EASTL performance being lower than it would be in
// real-world situations.
//
#include <string.h>
#ifdef _MSC_VER
#pragma function(strlen, strcmp, strcpy, strcat, memcpy, memcmp, memset)
#endif
#include <EASTL/set.h>
#include <EASTL/string.h>
#include <EAStdC/EAStopwatch.h>
#include <stdlib.h>
#include <string.h>
void BenchmarkSort();
void BenchmarkList();
void BenchmarkString();
void BenchmarkVector();
void BenchmarkDeque();
void BenchmarkSet();
void BenchmarkMap();
void BenchmarkHash();
void BenchmarkAlgorithm();
void BenchmarkHeap();
void BenchmarkBitset();
namespace Benchmark
{
// Environment
//
// The environment for this benchmark test.
//
struct Environment
{
eastl::string8 msPlatform; // Name of test platform (e.g. "Windows")
eastl::string8 msSTLName1; // Name of competitor #1 (e.g. "EASTL").
eastl::string8 msSTLName2; // Name of competitor #2 (e.g. "MS STL").
void clear() { msPlatform.set_capacity(0); msSTLName1.set_capacity(0); msSTLName2.set_capacity(0); }
};
Environment& GetEnvironment();
// Result
//
// An individual benchmark result.
//
struct Result
{
eastl::string8 msName; // Test name (e.g. "vector/insert").
int mUnits; // Timing units (e.g. EA::StdC::Stopwatch::kUnitsSeconds).
int64_t mTime1; // Time of competitor #1.
uint64_t mTime1NS; // Nanoseconds.
int64_t mTime2; // Time of competitor #2.
int64_t mTime2NS; // Nanoseconds.
eastl::string8 msNotes; // Any comments to attach to this result.
Result() : msName(), mUnits(EA::StdC::Stopwatch::kUnitsCPUCycles),
mTime1(0), mTime1NS(0), mTime2(0), mTime2NS(0), msNotes() { }
};
inline bool operator<(const Result& r1, const Result& r2)
{ return r1.msName < r2.msName; }
typedef eastl::set<Result> ResultSet;
ResultSet& GetResultSet();
// Scratch sprintf buffer
extern char gScratchBuffer[1024];
// Utility functions
//
void DoNothing(...);
void AddResult(const char* pName, int units, int64_t nTime1, int64_t nTime2, const char* pNotes = NULL);
void PrintResults();
} // namespace Benchmark
///////////////////////////////////////////////////////////////////////////////
/// LargePOD
///
/// Implements a structure which is essentially a largish POD. Useful for testing
/// containers and algorithms for their ability to efficiently work with PODs.
/// This class isn't strictly a POD by the definition of the C++ standard,
/// but it suffices for our interests.
///
struct LargeObject
{
int32_t mData[2048];
};
struct LargePOD
{
LargeObject mLargeObject1;
LargeObject mLargeObject2;
const char* mpName1;
const char* mpName2;
explicit LargePOD(int32_t x = 0) // A true POD doesn't have a non-trivial constructor.
{
memset(mLargeObject1.mData, 0, sizeof(mLargeObject1.mData));
memset(mLargeObject2.mData, 0, sizeof(mLargeObject2.mData));
mLargeObject1.mData[0] = x;
mpName1 = "LargePOD1";
mpName2 = "LargePOD2";
}
LargePOD(const LargePOD& largePOD) // A true POD doesn't have a non-trivial copy-constructor.
: mLargeObject1(largePOD.mLargeObject1),
mLargeObject2(largePOD.mLargeObject2),
mpName1(largePOD.mpName1),
mpName2(largePOD.mpName2)
{
}
virtual ~LargePOD() { }
LargePOD& operator=(const LargePOD& largePOD) // A true POD doesn't have a non-trivial assignment operator.
{
if(&largePOD != this)
{
mLargeObject1 = largePOD.mLargeObject1;
mLargeObject2 = largePOD.mLargeObject2;
mpName1 = largePOD.mpName1;
mpName2 = largePOD.mpName2;
}
return *this;
}
virtual void DoSomething() // Note that by declaring this virtual, this class is not truly a POD.
{ // But it acts like a POD for the purposes of EASTL algorithms.
mLargeObject1.mData[1]++;
}
operator int()
{
return (int)mLargeObject1.mData[0];
}
};
//EASTL_DECLARE_POD(LargePOD);
//EASTL_DECLARE_TRIVIAL_CONSTRUCTOR(LargePOD);
//EASTL_DECLARE_TRIVIAL_COPY(LargePOD);
//EASTL_DECLARE_TRIVIAL_ASSIGN(LargePOD);
//EASTL_DECLARE_TRIVIAL_DESTRUCTOR(LargePOD);
//EASTL_DECLARE_TRIVIAL_RELOCATE(LargePOD);
// Operators
// We specifically define only == and <, in order to verify that
// our containers and algorithms are not mistakenly expecting other
// operators for the contained and manipulated classes.
inline bool operator==(const LargePOD& t1, const LargePOD& t2)
{
return (memcmp(&t1.mLargeObject1, &t2.mLargeObject1, sizeof(t1.mLargeObject1)) == 0) &&
(memcmp(&t1.mLargeObject2, &t2.mLargeObject2, sizeof(t1.mLargeObject2)) == 0) &&
(strcmp(t1.mpName1, t2.mpName1) == 0) &&
(strcmp(t1.mpName2, t2.mpName2) == 0);
}
inline bool operator<(const LargePOD& t1, const LargePOD& t2)
{
return (memcmp(&t1.mLargeObject1, &t2.mLargeObject1, sizeof(t1.mLargeObject1)) < 0) &&
(memcmp(&t1.mLargeObject2, &t2.mLargeObject2, sizeof(t1.mLargeObject2)) < 0) &&
(strcmp(t1.mpName1, t2.mpName1) < 0) &&
(strcmp(t1.mpName2, t2.mpName2) < 0);
}
#endif // Header sentry