Skip to content

Commit 25eae75

Browse files
feat(core): allow measurement through codspeed core library
1 parent 915e6b0 commit 25eae75

File tree

6 files changed

+7406
-7
lines changed

6 files changed

+7406
-7
lines changed

core/CMakeLists.txt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
cmake_minimum_required(VERSION 3.10)
2-
project(
3-
codspeed
4-
VERSION 1.0
5-
LANGUAGES CXX)
2+
3+
set(CODSPEED_VERSION 1.0.0)
4+
5+
project(codspeed VERSION ${CODSPEED_VERSION} LANGUAGES CXX)
66

77
# Specify the C++ standard
88
set(CMAKE_CXX_STANDARD 17)
@@ -14,6 +14,15 @@ include_directories(include)
1414
# Add the library
1515
add_library(codspeed src/codspeed.cpp)
1616

17+
# Version
18+
add_compile_definitions(CODSPEED_VERSION="${CODSPEED_VERSION}")
19+
20+
# Disable valgrind compilation errors
21+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
22+
# Disable the old-style-cast warning for the specific target
23+
target_compile_options(codspeed PRIVATE -Wno-old-style-cast)
24+
endif()
25+
1726
# Specify the include directories for users of the library
1827
target_include_directories(
1928
codspeed

core/include/codspeed.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
#ifndef CODSPEED_H
22
#define CODSPEED_H
33

4-
void hello_codspeed();
4+
#include <string>
5+
#include <vector>
6+
7+
class CodSpeed {
8+
public:
9+
// Constructor
10+
CodSpeed();
11+
12+
// Member functions
13+
void push_group(const std::string &group);
14+
void pop_group();
15+
void start_benchmark(const std::string &name);
16+
void end_benchmark();
17+
18+
private:
19+
std::vector<std::string> benchmarked;
20+
std::string current_benchmark;
21+
std::vector<std::string> group_stack;
22+
bool is_instrumented;
23+
};
524

625
#endif // CODSPEED_H

core/src/callgrind.h

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
----------------------------------------------------------------
3+
4+
Notice that the following BSD-style license applies to this one
5+
file (callgrind.h) only. The rest of Valgrind is licensed under the
6+
terms of the GNU General Public License, version 2, unless
7+
otherwise indicated. See the COPYING file in the source
8+
distribution for details.
9+
10+
----------------------------------------------------------------
11+
12+
This file is part of callgrind, a valgrind tool for cache simulation
13+
and call tree tracing.
14+
15+
Copyright (C) 2003-2017 Josef Weidendorfer. All rights reserved.
16+
17+
Redistribution and use in source and binary forms, with or without
18+
modification, are permitted provided that the following conditions
19+
are met:
20+
21+
1. Redistributions of source code must retain the above copyright
22+
notice, this list of conditions and the following disclaimer.
23+
24+
2. The origin of this software must not be misrepresented; you must
25+
not claim that you wrote the original software. If you use this
26+
software in a product, an acknowledgment in the product
27+
documentation would be appreciated but is not required.
28+
29+
3. Altered source versions must be plainly marked as such, and must
30+
not be misrepresented as being the original software.
31+
32+
4. The name of the author may not be used to endorse or promote
33+
products derived from this software without specific prior written
34+
permission.
35+
36+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42+
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47+
48+
----------------------------------------------------------------
49+
50+
Notice that the above BSD-style license applies to this one file
51+
(callgrind.h) only. The entire rest of Valgrind is licensed under
52+
the terms of the GNU General Public License, version 2. See the
53+
COPYING file in the source distribution for details.
54+
55+
----------------------------------------------------------------
56+
*/
57+
58+
#ifndef __CALLGRIND_H
59+
#define __CALLGRIND_H
60+
61+
#include "valgrind.h"
62+
63+
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
64+
This enum comprises an ABI exported by Valgrind to programs
65+
which use client requests. DO NOT CHANGE THE ORDER OF THESE
66+
ENTRIES, NOR DELETE ANY -- add new ones at the end.
67+
68+
The identification ('C','T') for Callgrind has historical
69+
reasons: it was called "Calltree" before. Besides, ('C','G') would
70+
clash with cachegrind.
71+
*/
72+
73+
typedef enum {
74+
VG_USERREQ__DUMP_STATS = VG_USERREQ_TOOL_BASE('C', 'T'),
75+
VG_USERREQ__ZERO_STATS,
76+
VG_USERREQ__TOGGLE_COLLECT,
77+
VG_USERREQ__DUMP_STATS_AT,
78+
VG_USERREQ__START_INSTRUMENTATION,
79+
VG_USERREQ__STOP_INSTRUMENTATION
80+
} Vg_CallgrindClientRequest;
81+
82+
/* Dump current state of cost centers, and zero them afterwards */
83+
#define CALLGRIND_DUMP_STATS \
84+
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DUMP_STATS, 0, 0, 0, 0, 0)
85+
86+
/* Dump current state of cost centers, and zero them afterwards.
87+
The argument is appended to a string stating the reason which triggered
88+
the dump. This string is written as a description field into the
89+
profile data dump. */
90+
#define CALLGRIND_DUMP_STATS_AT(pos_str) \
91+
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DUMP_STATS_AT, pos_str, 0, 0, 0, \
92+
0)
93+
94+
/* Zero cost centers */
95+
#define CALLGRIND_ZERO_STATS \
96+
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ZERO_STATS, 0, 0, 0, 0, 0)
97+
98+
/* Toggles collection state.
99+
The collection state specifies whether the happening of events
100+
should be noted or if they are to be ignored. Events are noted
101+
by increment of counters in a cost center */
102+
#define CALLGRIND_TOGGLE_COLLECT \
103+
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TOGGLE_COLLECT, 0, 0, 0, 0, 0)
104+
105+
/* Start full callgrind instrumentation if not already switched on.
106+
When cache simulation is done, it will flush the simulated cache;
107+
this will lead to an artificial cache warmup phase afterwards with
108+
cache misses which would not have happened in reality. */
109+
#define CALLGRIND_START_INSTRUMENTATION \
110+
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__START_INSTRUMENTATION, 0, 0, 0, \
111+
0, 0)
112+
113+
/* Stop full callgrind instrumentation if not already switched off.
114+
This flushes Valgrinds translation cache, and does no additional
115+
instrumentation afterwards, which effectivly will run at the same
116+
speed as the "none" tool (ie. at minimal slowdown).
117+
Use this to bypass Callgrind aggregation for uninteresting code parts.
118+
To start Callgrind in this mode to ignore the setup phase, use
119+
the option "--instr-atstart=no". */
120+
#define CALLGRIND_STOP_INSTRUMENTATION \
121+
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STOP_INSTRUMENTATION, 0, 0, 0, \
122+
0, 0)
123+
124+
#endif /* __CALLGRIND_H */

core/src/codspeed.cpp

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,53 @@
1+
#include "measurement.hpp"
12
#include <codspeed.h>
23
#include <iostream>
4+
#include <string>
5+
#include <vector>
36

4-
void hello_codspeed() {
5-
std::cout << "Hello from CodSpeed core library!" << std::endl;
7+
std::string join(const std::vector<std::string> &elements,
8+
const std::string &delimiter) {
9+
std::string result;
10+
for (size_t i = 0; i < elements.size(); ++i) {
11+
result += elements[i];
12+
if (i != elements.size() - 1) {
13+
result += delimiter;
14+
}
15+
}
16+
return result;
17+
}
18+
19+
CodSpeed::CodSpeed() : is_instrumented(measurement_is_instrumented()) {
20+
if (!is_instrumented) {
21+
std::cerr
22+
<< "NOTICE: codspeed is enabled, but no performance measurement will "
23+
"be made since it's running in an unknown environment."
24+
<< std::endl;
25+
}
26+
measurement_set_metadata();
27+
}
28+
29+
// Member function definitions
30+
void CodSpeed::push_group(const std::string &group) {
31+
group_stack.push_back(group);
32+
}
33+
34+
void CodSpeed::pop_group() {
35+
if (!group_stack.empty()) {
36+
group_stack.pop_back();
37+
}
38+
}
39+
40+
void CodSpeed::start_benchmark(const std::string &name) {
41+
current_benchmark = name;
42+
measurement_start();
43+
}
44+
45+
void CodSpeed::end_benchmark() {
46+
measurement_stop(current_benchmark);
47+
benchmarked.push_back(current_benchmark);
48+
std::string action_str = is_instrumented ? "Measured" : "Checked";
49+
std::string group_str =
50+
group_stack.empty() ? "" : " (group: " + join(group_stack, "/") + ")";
51+
std::cerr << action_str << ": " << current_benchmark << group_str
52+
<< std::endl;
653
}

core/src/measurement.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef MEASUREMENT_H
2+
#define MEASUREMENT_H
3+
4+
#include "callgrind.h"
5+
#include <string>
6+
7+
inline std::string get_version() {
8+
#ifdef CODSPEED_VERSION
9+
return {CODSPEED_VERSION};
10+
#else
11+
return {""};
12+
#endif
13+
}
14+
15+
inline bool measurement_is_instrumented() { return RUNNING_ON_VALGRIND; }
16+
17+
inline void measurement_set_metadata() {
18+
std::string metadata = "Metadata: codspeed-cpp " + get_version();
19+
CALLGRIND_DUMP_STATS_AT(metadata.c_str());
20+
}
21+
22+
inline void measurement_start() {
23+
CALLGRIND_ZERO_STATS;
24+
CALLGRIND_START_INSTRUMENTATION;
25+
}
26+
27+
inline void measurement_stop(const std::string &name) {
28+
CALLGRIND_STOP_INSTRUMENTATION;
29+
CALLGRIND_DUMP_STATS_AT(name.c_str());
30+
};
31+
32+
#endif // MEASUREMENT_H

0 commit comments

Comments
 (0)