Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev: Add RecentMessages benchmark #5071

Merged
merged 13 commits into from
Jan 7, 2024
6 changes: 6 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,11 @@ CheckOptions:
- key: readability-identifier-naming.LocalPointerIgnoredRegexp
value: ^L$

# Benchmarks
- key: readability-identifier-naming.FunctionIgnoredRegexp
value: ^BM_[^_]+$
- key: readability-identifier-naming.ClassIgnoredRegexp
value: ^BM_[^_]+$

- key: misc-const-correctness.AnalyzeValues
value: false
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# JSON resources should not be prettified...
resources/*.json
benchmarks/resources/*.json
tests/resources/*.json
# ...themes should be prettified for readability.
!resources/themes/*.json

# Ignore submodule files
lib/*/
conan-pkgs/*/
cmake/sanitizers-cmake/
tools/crash-handler

# Build folders
*build-*/
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
- Dev: Autogenerate docs/plugin-meta.lua. (#5055)
- Dev: Removed duplicate scale in settings dialog. (#5069)
- Dev: Fix `NotebookTab` emitting updates for every message. (#5068)
- Dev: Added benchmark for parsing and building recent messages. (#5071)

## 2.4.6

Expand Down
18 changes: 11 additions & 7 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
project(chatterino-benchmark)

set(benchmark_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/main.cpp
${CMAKE_CURRENT_LIST_DIR}/src/Emojis.cpp
${CMAKE_CURRENT_LIST_DIR}/src/Highlights.cpp
${CMAKE_CURRENT_LIST_DIR}/src/FormatTime.cpp
${CMAKE_CURRENT_LIST_DIR}/src/Helpers.cpp
${CMAKE_CURRENT_LIST_DIR}/src/LimitedQueue.cpp
${CMAKE_CURRENT_LIST_DIR}/src/LinkParser.cpp
src/main.cpp
resources/bench.qrc

src/Emojis.cpp
src/Highlights.cpp
src/FormatTime.cpp
src/Helpers.cpp
src/LimitedQueue.cpp
src/LinkParser.cpp
src/RecentMessages.cpp
# Add your new file above this line!
)

Expand All @@ -27,4 +30,5 @@ set_target_properties(${PROJECT_NAME}
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin"
AUTORCC ON
)
6 changes: 6 additions & 0 deletions benchmarks/resources/bench.qrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/bench">
<file>recentmessages-nymn.json</file>
<file>seventvemotes-nymn.json</file>
</qresource>
</RCC>
1 change: 1 addition & 0 deletions benchmarks/resources/recentmessages-nymn.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions benchmarks/resources/seventvemotes-nymn.json

Large diffs are not rendered by default.

7 changes: 2 additions & 5 deletions benchmarks/src/Emojis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,13 @@ static void BM_EmojiParsing(benchmark::State &state)

BENCHMARK(BM_EmojiParsing);

template <class... Args>
static void BM_EmojiParsing2(benchmark::State &state, Args &&...args)
static void BM_EmojiParsing2(benchmark::State &state, const QString &input,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'BM_EmojiParsing2' declared 'static', move to anonymous namespace instead [misc-use-anonymous-namespace]

                                             ^

int expectedNumEmojis)
{
Emojis emojis;

emojis.load();

auto argsTuple = std::make_tuple(std::move(args)...);
auto input = std::get<0>(argsTuple);
auto expectedNumEmojis = std::get<1>(argsTuple);
for (auto _ : state)
{
auto output = emojis.parse(input);
Expand Down
58 changes: 32 additions & 26 deletions benchmarks/src/FormatTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,41 @@

using namespace chatterino;

template <class... Args>
void BM_TimeFormatting(benchmark::State &state, Args &&...args)
void BM_TimeFormattingQString(benchmark::State &state, const QString &v)
{
auto args_tuple = std::make_tuple(std::move(args)...);
for (auto _ : state)
{
formatTime(std::get<0>(args_tuple));
formatTime(v);
}
}

BENCHMARK_CAPTURE(BM_TimeFormatting, 0, 0);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs0, "0");
BENCHMARK_CAPTURE(BM_TimeFormatting, 1337, 1337);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs1337, "1337");
BENCHMARK_CAPTURE(BM_TimeFormatting, 623452, 623452);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs623452, "623452");
BENCHMARK_CAPTURE(BM_TimeFormatting, 8345, 8345);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs8345, "8345");
BENCHMARK_CAPTURE(BM_TimeFormatting, 314034, 314034);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs314034, "314034");
BENCHMARK_CAPTURE(BM_TimeFormatting, 27, 27);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs27, "27");
BENCHMARK_CAPTURE(BM_TimeFormatting, 34589, 34589);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs34589, "34589");
BENCHMARK_CAPTURE(BM_TimeFormatting, 3659, 3659);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs3659, "3659");
BENCHMARK_CAPTURE(BM_TimeFormatting, 1045345, 1045345);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs1045345, "1045345");
BENCHMARK_CAPTURE(BM_TimeFormatting, 86432, 86432);
BENCHMARK_CAPTURE(BM_TimeFormatting, qs86432, "86432");
BENCHMARK_CAPTURE(BM_TimeFormatting, qsempty, "");
BENCHMARK_CAPTURE(BM_TimeFormatting, qsinvalid, "asd");
void BM_TimeFormattingInt(benchmark::State &state, int v)
{
for (auto _ : state)
{
formatTime(v);
}
}

BENCHMARK_CAPTURE(BM_TimeFormattingInt, 0, 0);
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 1045345, 1045345);
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 1337, 1337);
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 27, 27);
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 314034, 314034);
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 34589, 34589);
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 3659, 3659);
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 623452, 623452);
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 8345, 8345);
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 86432, 86432);
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs0, "0");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs1045345, "1045345");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs1337, "1337");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs27, "27");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs314034, "314034");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs34589, "34589");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs3659, "3659");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs623452, "623452");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs8345, "8345");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs86432, "86432");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qsempty, "");
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qsinvalid, "asd");
223 changes: 223 additions & 0 deletions benchmarks/src/RecentMessages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
#include "common/Literals.hpp"
#include "controllers/accounts/AccountController.hpp"
#include "controllers/highlights/HighlightController.hpp"
#include "messages/Emote.hpp"
#include "mocks/EmptyApplication.hpp"
#include "mocks/TwitchIrcServer.hpp"
#include "mocks/UserData.hpp"
#include "providers/bttv/BttvEmotes.hpp"
#include "providers/chatterino/ChatterinoBadges.hpp"
#include "providers/ffz/FfzBadges.hpp"
#include "providers/ffz/FfzEmotes.hpp"
#include "providers/recentmessages/Impl.hpp"
#include "providers/seventv/SeventvBadges.hpp"
#include "providers/seventv/SeventvEmotes.hpp"
#include "providers/twitch/TwitchChannel.hpp"
#include "singletons/Emotes.hpp"
#include "singletons/Resources.hpp"

#include <benchmark/benchmark.h>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QString>

#include <optional>

using namespace chatterino;
using namespace literals;

namespace {

class MockApplication : mock::EmptyApplication
{
public:
IEmotes *getEmotes() override
{
return &this->emotes;
}

IUserDataController *getUserData() override
{
return &this->userData;
}

AccountController *getAccounts() override
{
return &this->accounts;
}

ITwitchIrcServer *getTwitch() override
{
return &this->twitch;
}

ChatterinoBadges *getChatterinoBadges() override
{
return &this->chatterinoBadges;
}

FfzBadges *getFfzBadges() override
{
return &this->ffzBadges;
}

SeventvBadges *getSeventvBadges() override
{
return &this->seventvBadges;
}

HighlightController *getHighlights() override
{
return &this->highlights;
}

AccountController accounts;
Emotes emotes;
mock::UserDataController userData;
mock::MockTwitchIrcServer twitch;
ChatterinoBadges chatterinoBadges;
FfzBadges ffzBadges;
SeventvBadges seventvBadges;
HighlightController highlights;
};

std::optional<QJsonDocument> tryReadJsonFile(const QString &path)
{
QFile file(path);
if (!file.open(QFile::ReadOnly))
{
return std::nullopt;
}

QJsonParseError e;
Nerixyz marked this conversation as resolved.
Show resolved Hide resolved
auto doc = QJsonDocument::fromJson(file.readAll(), &e);
if (e.error != QJsonParseError::NoError)
{
return std::nullopt;
}

return doc;
}

QJsonDocument readJsonFile(const QString &path)
{
auto opt = tryReadJsonFile(path);
if (!opt)
{
_exit(1);
}
return *opt;
}

class RecentMessages
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: class 'RecentMessages' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]

class RecentMessages
      ^

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: destructor of 'RecentMessages' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]

class RecentMessages
      ^
Additional context

benchmarks/src/RecentMessages.cpp:112: make it public and virtual

class RecentMessages
      ^

{
public:
explicit RecentMessages(const QString &name_)
: name(name_)
Comment on lines +116 to +117
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: pass by value and use std::move [modernize-pass-by-value]

benchmarks/src/RecentMessages.cpp:25:

+ #include <utility>
Suggested change
explicit RecentMessages(const QString &name_)
: name(name_)
explicit RecentMessages(QString name_)
: name(std::move(name_))

, chan(this->name)
{
const auto seventvEmotes =
tryReadJsonFile(u":/bench/seventvemotes-%1.json"_s.arg(this->name));
const auto bttvEmotes =
tryReadJsonFile(u":/bench/bttvemotes-%1.json"_s.arg(this->name));
const auto ffzEmotes =
tryReadJsonFile(u":/bench/ffzemotes-%1.json"_s.arg(this->name));

if (seventvEmotes)
{
this->chan.setSeventvEmotes(
std::make_shared<const EmoteMap>(seventv::detail::parseEmotes(
seventvEmotes->object()["emote_set"_L1]
.toObject()["emotes"_L1]
.toArray(),
false)));
}

if (bttvEmotes)
{
this->chan.setBttvEmotes(std::make_shared<const EmoteMap>(
bttv::detail::parseChannelEmotes(bttvEmotes->object(),
this->name)));
}

if (ffzEmotes)
{
this->chan.setFfzEmotes(std::make_shared<const EmoteMap>(
ffz::detail::parseChannelEmotes(ffzEmotes->object())));
}

this->messages =
readJsonFile(u":/bench/recentmessages-%1.json"_s.arg(this->name));
}

~RecentMessages()
{
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
}

virtual void run(benchmark::State &state) = 0;

protected:
QString name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: invalid case style for protected member 'name' [readability-identifier-naming]

benchmarks/src/RecentMessages.cpp:116:

-         : name(name_)
-         , chan(this->name)
+         : name_(name_)
+         , chan(this->name_)

benchmarks/src/RecentMessages.cpp:120:

-             tryReadJsonFile(u":/bench/seventvemotes-%1.json"_s.arg(this->name));
+             tryReadJsonFile(u":/bench/seventvemotes-%1.json"_s.arg(this->name_));

benchmarks/src/RecentMessages.cpp:122:

-             tryReadJsonFile(u":/bench/bttvemotes-%1.json"_s.arg(this->name));
+             tryReadJsonFile(u":/bench/bttvemotes-%1.json"_s.arg(this->name_));

benchmarks/src/RecentMessages.cpp:124:

-             tryReadJsonFile(u":/bench/ffzemotes-%1.json"_s.arg(this->name));
+             tryReadJsonFile(u":/bench/ffzemotes-%1.json"_s.arg(this->name_));

benchmarks/src/RecentMessages.cpp:140:

-                                                  this->name)));
+                                                  this->name_)));

benchmarks/src/RecentMessages.cpp:150:

-             readJsonFile(u":/bench/recentmessages-%1.json"_s.arg(this->name));
+             readJsonFile(u":/bench/recentmessages-%1.json"_s.arg(this->name_));
Suggested change
QString name;
QString name_;

MockApplication app;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: invalid case style for protected member 'app' [readability-identifier-naming]

Suggested change
MockApplication app;
MockApplication app_;

TwitchChannel chan;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: invalid case style for protected member 'chan' [readability-identifier-naming]

benchmarks/src/RecentMessages.cpp:117:

-         , chan(this->name)
+         , chan_(this->name)

benchmarks/src/RecentMessages.cpp:128:

-             this->chan.setSeventvEmotes(
+             this->chan_.setSeventvEmotes(

benchmarks/src/RecentMessages.cpp:138:

-             this->chan.setBttvEmotes(std::make_shared<const EmoteMap>(
+             this->chan_.setBttvEmotes(std::make_shared<const EmoteMap>(

benchmarks/src/RecentMessages.cpp:145:

-             this->chan.setFfzEmotes(std::make_shared<const EmoteMap>(
+             this->chan_.setFfzEmotes(std::make_shared<const EmoteMap>(
Suggested change
TwitchChannel chan;
TwitchChannel chan_;

benchmarks/src/RecentMessages.cpp:201:

-                 parsed, &this->chan);
+                 parsed, &this->chan_);

QJsonDocument messages;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: invalid case style for protected member 'messages' [readability-identifier-naming]

benchmarks/src/RecentMessages.cpp:149:

-         this->messages =
+         this->messages_ =
Suggested change
QJsonDocument messages;
QJsonDocument messages_;

benchmarks/src/RecentMessages.cpp:180:

-                 this->messages.object());
+                 this->messages_.object());

benchmarks/src/RecentMessages.cpp:197:

-             this->messages.object());
+             this->messages_.object());

};

class ParseRecentMessages : public RecentMessages
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: destructor of 'ParseRecentMessages' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]

class ParseRecentMessages : public RecentMessages
      ^
Additional context

benchmarks/src/RecentMessages.cpp:167: make it public and virtual

class ParseRecentMessages : public RecentMessages
      ^

{
public:
explicit ParseRecentMessages(const QString &name_)
: RecentMessages(name_)
{
}

void run(benchmark::State &state)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: annotate this function with 'override' or (rarely) 'final' [cppcoreguidelines-explicit-virtual-functions]

Suggested change
void run(benchmark::State &state)
void run(benchmark::State &state) override

{
for (auto _ : state)
{
auto parsed = recentmessages::detail::parseRecentMessages(
this->messages.object());
benchmark::DoNotOptimize(parsed);
}
}
};

class BuildRecentMessages : public RecentMessages
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: destructor of 'BuildRecentMessages' is public and non-virtual [cppcoreguidelines-virtual-class-destructor]

class BuildRecentMessages : public RecentMessages
      ^
Additional context

benchmarks/src/RecentMessages.cpp:186: make it public and virtual

class BuildRecentMessages : public RecentMessages
      ^

{
public:
explicit BuildRecentMessages(const QString &name_)
: RecentMessages(name_)
{
}

void run(benchmark::State &state)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: annotate this function with 'override' or (rarely) 'final' [cppcoreguidelines-explicit-virtual-functions]

Suggested change
void run(benchmark::State &state)
void run(benchmark::State &state) override

{
auto parsed = recentmessages::detail::parseRecentMessages(
this->messages.object());
for (auto _ : state)
{
auto built = recentmessages::detail::buildRecentMessages(
parsed, &this->chan);
benchmark::DoNotOptimize(built);
}
}
};

void BM_ParseRecentMessages(benchmark::State &state, const QString &name)
{
ParseRecentMessages bench(name);
bench.run(state);
}

void BM_BuildRecentMessages(benchmark::State &state, const QString &name)
{
BuildRecentMessages bench(name);
bench.run(state);
}

} // namespace

BENCHMARK_CAPTURE(BM_ParseRecentMessages, nymn, u"nymn"_s);
BENCHMARK_CAPTURE(BM_BuildRecentMessages, nymn, u"nymn"_s);
3 changes: 3 additions & 0 deletions benchmarks/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "singletons/Resources.hpp"
#include "singletons/Settings.hpp"

#include <benchmark/benchmark.h>
Expand All @@ -11,6 +12,8 @@ int main(int argc, char **argv)
{
QApplication app(argc, argv);

initResources();

::benchmark::Initialize(&argc, argv);

// Ensure settings are initialized before any benchmarks are run
Expand Down
Loading
Loading