Add basic benchmark (#3038)

* Add basic benchmark

* Add basic documentation for how to run and add tests/benchmarks

* Update benchmark example output

* Add changelog entry

Co-authored-by: zneix <zneix@zneix.eu>
This commit is contained in:
pajlada 2021-08-08 14:16:30 +02:00 committed by GitHub
parent 7309fd8668
commit d0f817a60b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 239 additions and 1 deletions

View file

@ -8,6 +8,7 @@
- Bugfix: Moderation mode and active filters are now preserved when opening a split as a popup. (#3113, #3130)
- Bugfix: Fixed a bug that caused all badge highlights to use the same color. (#3132, #3134)
- Dev: Renamed CMake's build option `USE_SYSTEM_QT5KEYCHAIN` to `USE_SYSTEM_QTKEYCHAIN`. (#3103)
- Dev: Add benchmarks that can be compiled with the `BUILD_BENCHMARKS` CMake flag. Off by default. (#3038)
## 2.3.4

View file

@ -11,6 +11,7 @@ project(chatterino VERSION 2.3.4)
option(BUILD_APP "Build Chatterino" ON)
option(BUILD_TESTS "Build the tests for Chatterino" OFF)
option(BUILD_BENCHMARKS "Build the benchmarks for Chatterino" OFF)
option(USE_SYSTEM_PAJLADA_SETTINGS "Use system pajlada settings library" OFF)
option(USE_SYSTEM_LIBCOMMUNI "Use system communi library" OFF)
option(USE_SYSTEM_QTKEYCHAIN "Use system QtKeychain library" OFF)
@ -101,6 +102,11 @@ if (BUILD_TESTS)
find_package(GTest REQUIRED)
endif ()
if (BUILD_BENCHMARKS)
# Include system benchmark (Google Benchmark)
find_package(benchmark REQUIRED)
endif ()
find_package(PajladaSerialize REQUIRED)
find_package(PajladaSignals REQUIRED)
find_package(LRUCache REQUIRED)
@ -118,7 +124,7 @@ endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (BUILD_TESTS)
if (BUILD_TESTS OR BUILD_BENCHMARKS)
add_definitions(-DCHATTERINO_TEST)
endif ()
@ -129,4 +135,8 @@ if (BUILD_TESTS)
add_subdirectory(tests)
endif ()
if (BUILD_BENCHMARKS)
add_subdirectory(benchmarks)
endif ()
feature_summary(WHAT ALL)

35
benchmarks/.clang-format Normal file
View file

@ -0,0 +1,35 @@
Language: Cpp
AccessModifierOffset: -4
AlignEscapedNewlinesLeft: true
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: Empty
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakBeforeMultilineStrings: false
BasedOnStyle: Google
BraceWrapping: {
AfterClass: 'true'
AfterControlStatement: 'true'
AfterFunction: 'true'
AfterNamespace: 'false'
BeforeCatch: 'true'
BeforeElse: 'true'
}
BreakBeforeBraces: Custom
BreakConstructorInitializersBeforeComma: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: false
DerivePointerBinding: false
FixNamespaceComments: true
IndentCaseLabels: true
IndentWidth: 4
IndentWrappedFunctionNames: true
IndentPPDirectives: AfterHash
IncludeBlocks: Preserve
NamespaceIndentation: Inner
PointerBindsToType: false
SpacesBeforeTrailingComments: 2
Standard: Auto
ReflowComments: false

28
benchmarks/CMakeLists.txt Normal file
View file

@ -0,0 +1,28 @@
project(chatterino-benchmark)
set(benchmark_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/main.cpp
${CMAKE_CURRENT_LIST_DIR}/src/Emojis.cpp
# Add your new file above this line!
)
add_executable(${PROJECT_NAME} ${benchmark_SOURCES})
add_sanitizers(${PROJECT_NAME})
target_link_libraries(${PROJECT_NAME} PRIVATE chatterino-lib)
target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark)
target_compile_definitions(${PROJECT_NAME} PRIVATE
CHATTERINO_TEST
)
set_target_properties(${PROJECT_NAME}
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin"
)

57
benchmarks/src/Emojis.cpp Normal file
View file

@ -0,0 +1,57 @@
#include "providers/emoji/Emojis.hpp"
#include <benchmark/benchmark.h>
#include <QDebug>
#include <QString>
using namespace chatterino;
static void BM_ShortcodeParsing(benchmark::State &state)
{
Emojis emojis;
emojis.load();
struct TestCase {
QString input;
QString expectedOutput;
};
std::vector<TestCase> tests{
{
// input
"foo :penguin: bar",
// expected output
"foo 🐧 bar",
},
{
// input
"foo :nonexistantcode: bar",
// expected output
"foo :nonexistantcode: bar",
},
{
// input
":male-doctor:",
// expected output
"👨‍⚕️",
},
};
for (auto _ : state)
{
for (const auto &test : tests)
{
auto output = emojis.replaceShortCodes(test.input);
auto matches = output == test.expectedOutput;
if (!matches && !output.endsWith(QChar(0xFE0F)))
{
// Try to append 0xFE0F if needed
output = output.append(QChar(0xFE0F));
}
}
}
}
BENCHMARK(BM_ShortcodeParsing);

18
benchmarks/src/main.cpp Normal file
View file

@ -0,0 +1,18 @@
#include <benchmark/benchmark.h>
#include <QApplication>
#include <QtConcurrent>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
::benchmark::Initialize(&argc, argv);
QtConcurrent::run([&app] {
::benchmark::RunSpecifiedBenchmarks();
app.exit(0);
});
return app.exec();
}

View file

@ -0,0 +1,88 @@
# Test and Benchmark
Chatterino includes a set of unit tests and benchmarks. These can be built using cmake by adding the `-DBUILD_TESTS=On` and `-DBUILD_BENCHMARKS=On` flags respectively.
## Adding your own test
1. Create a new file for the file you're adding tests for. If you're creating tests for `src/providers/emoji/Emojis.cpp`, create `tests/src/Emojis.cpp`.
2. Add the newly created file to `tests/CMakeLists.txt` in the `test_SOURCES` variable (see the comment near it)
See `tests/src/Emojis.cpp` for simple tests you can base your tests off of.
Read up on http://google.github.io/googletest/primer.html to figure out how GoogleTest works.
## Building and running tests
```sh
mkdir build-tests
cd build-tests
cmake -DBUILD_TESTS=On ..
make
./bin/chatterino-test
```
### Example output
```
[==========] Running 26 tests from 8 test suites.
[----------] Global test environment set-up.
[----------] 2 tests from AccessGuardLocker
[ RUN ] AccessGuardLocker.NonConcurrentUsage
[ OK ] AccessGuardLocker.NonConcurrentUsage (0 ms)
[ RUN ] AccessGuardLocker.ConcurrentUsage
[ OK ] AccessGuardLocker.ConcurrentUsage (686 ms)
[----------] 2 tests from AccessGuardLocker (686 ms total)
[----------] 4 tests from NetworkCommon
[ RUN ] NetworkCommon.parseHeaderList1
[ OK ] NetworkCommon.parseHeaderList1 (0 ms)
[ RUN ] NetworkCommon.parseHeaderListTrimmed
[ OK ] NetworkCommon.parseHeaderListTrimmed (0 ms)
[ RUN ] NetworkCommon.parseHeaderListColonInValue
...
[ RUN ] TwitchAccount.NotEnoughForMoreThanOneBatch
[ OK ] TwitchAccount.NotEnoughForMoreThanOneBatch (0 ms)
[ RUN ] TwitchAccount.BatchThreeParts
[ OK ] TwitchAccount.BatchThreeParts (0 ms)
[----------] 3 tests from TwitchAccount (2 ms total)
[----------] Global test environment tear-down
[==========] 26 tests from 8 test suites ran. (10297 ms total)
[ PASSED ] 26 tests.
```
## Adding your own benchmark
1. Create a new file for the file you're adding benchmark for. If you're creating benchmarks for `src/providers/emoji/Emojis.cpp`, create `benchmarks/src/Emojis.cpp`.
2. Add the newly created file to `benchmarks/CMakeLists.txt` in the `benchmark_SOURCES` variable (see the comment near it)
See `benchmarks/src/Emojis.cpp` for simple benchmark you can base your benchmarks off of.
## Building and running benchmarks
```sh
mkdir build-benchmarks
cd build-benchmarks
cmake -DBUILD_BENCHMARKS=On ..
make
./bin/chatterino-benchmark
```
### Example output
```
2021-07-18T13:12:11+02:00
Running ./bin/chatterino-benchmark
Run on (12 X 4000 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x6)
L1 Instruction 32 KiB (x6)
L2 Unified 256 KiB (x6)
L3 Unified 15360 KiB (x1)
Load Average: 2.86, 3.08, 3.51
***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.
--------------------------------------------------------------
Benchmark Time CPU Iterations
--------------------------------------------------------------
BM_ShortcodeParsing 2394 ns 2389 ns 278933
```

View file

@ -12,6 +12,7 @@ set(test_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/TwitchAccount.cpp
${CMAKE_CURRENT_LIST_DIR}/src/Helpers.cpp
${CMAKE_CURRENT_LIST_DIR}/src/RatelimitBucket.cpp
# Add your new file above this line!
)
add_executable(${PROJECT_NAME} ${test_SOURCES})