Skip to content

Commit 272f7b9

Browse files
feat(core): allow measurement through codspeed core library
1 parent d223d43 commit 272f7b9

File tree

7 files changed

+7414
-5
lines changed

7 files changed

+7414
-5
lines changed

core/CMakeLists.txt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
cmake_minimum_required(VERSION 3.10)
2+
3+
set(CODSPEED_VERSION 1.0)
4+
25
project(
36
codspeed
4-
VERSION 1.0
7+
VERSION ${CODSPEED_VERSION}
58
LANGUAGES CXX)
69

710
# Specify the C++ standard
@@ -12,7 +15,16 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
1215
include_directories(include)
1316

1417
# Add the library
15-
add_library(codspeed src/codspeed.cpp)
18+
add_library(codspeed src/codspeed.cpp src/measurement.cpp)
19+
20+
# Version
21+
add_compile_definitions(CODSPEED_VERSION="${CODSPEED_VERSION}")
22+
23+
# Disable valgrind compilation errors
24+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
25+
# Disable the old-style-cast warning for the specific target
26+
target_compile_options(codspeed PRIVATE -Wno-old-style-cast)
27+
endif()
1628

1729
# Specify the include directories for users of the library
1830
target_include_directories(

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.h"
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::cout
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::cout << action_str << ": " << current_benchmark << group_str
52+
<< std::endl;
653
}

core/src/measurement.cpp

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

core/src/measurement.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef MEASUREMENT_H
2+
#define MEASUREMENT_H
3+
4+
#include <string>
5+
6+
bool measurement_is_instrumented();
7+
void measurement_set_metadata();
8+
void measurement_start();
9+
void measurement_stop(const std::string &name);
10+
11+
#endif // MEASUREMENT_H

0 commit comments

Comments
 (0)