mirror of
https://github.com/transmission/transmission
synced 2024-12-21 23:32:35 +00:00
perf: prefer small containers (#6542)
* perf: make pref_is_savable() constexpr * refactor: use std::vector in tr_torrents::removedSince() * chore: remove unused typedef in OptionsDialog * perf: use std::vector in tr_num_parse_range() * perf: use small::max_size_set in FileTreeItem::update() * perf: use small:set in Wishlist::next() * perf: use small:map in FilterBar * perf: use small::map for counts in tr_logAddMessage() * perf: use small::max_size_map in FileTreeModel::twiddleWanted() perf: use small::max_size_map in FileTreeModel::twiddlePriority() * perf: use a std::array instead of std::map in TorrentFilter::update() * perf: use a std::array instead of std::map in TorrentSorter::set_mode() * perf: use a std::array instead of std::map in TorrentSorter::update() * perf: use small::set in Application::Impl::on_rpc_changed_idle() * perf: use std::array for MessageLogColumnsModel::level_names_ * fixup! perf: use std::array for MessageLogColumnsModel::level_names_ * fixup! perf: use small::map for counts in tr_logAddMessage()
This commit is contained in:
parent
9f77ef9c7a
commit
a51f08e532
16 changed files with 97 additions and 66 deletions
|
@ -11,7 +11,7 @@ IncludeCategories:
|
|||
SortPriority: 4
|
||||
- Regex: '^<(cairo|gdk|gio|glib|gtk|pango)mm([-./]|config)'
|
||||
Priority: 5
|
||||
- Regex: '^<(fmt)/'
|
||||
- Regex: '^<(fmt|small)/'
|
||||
Priority: 6
|
||||
- Regex: '^<(cairo|gdk|gio|glib|gtk|pango)[-./]'
|
||||
Priority: 8
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
#include <gtkmm/stylecontext.h>
|
||||
#include <gtkmm/window.h>
|
||||
|
||||
#include <small/set.hpp>
|
||||
|
||||
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
||||
#include <gtkmm/droptarget.h>
|
||||
#include <gtkmm/eventcontrollerfocus.h>
|
||||
|
@ -70,7 +72,6 @@
|
|||
#include <iterator> // std::back_inserter
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
@ -478,11 +479,13 @@ bool Application::Impl::on_rpc_changed_idle(tr_rpc_callback_type type, tr_torren
|
|||
auto const newvals = tr_sessionGetSettings(session);
|
||||
|
||||
// determine which settings changed
|
||||
auto changed_keys = std::set<tr_quark>{};
|
||||
auto changed_keys = small::set<tr_quark>{};
|
||||
auto& oldvals = gtr_pref_get_all();
|
||||
auto const serde = tr_variant_serde::benc();
|
||||
if (auto const* const newvals_map = newvals.get_if<tr_variant::Map>(); newvals_map != nullptr)
|
||||
{
|
||||
changed_keys.reserve(std::size(*newvals_map));
|
||||
|
||||
for (auto const& [key, newval] : *newvals_map)
|
||||
{
|
||||
bool changed = true;
|
||||
|
|
|
@ -36,9 +36,10 @@
|
|||
#include <fmt/core.h>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
class MessageLogColumnsModel : public Gtk::TreeModelColumnRecord
|
||||
{
|
||||
|
@ -95,7 +96,14 @@ private:
|
|||
tr_log_level maxLevel_ = TR_LOG_INFO;
|
||||
bool isPaused_ = false;
|
||||
sigc::connection refresh_tag_;
|
||||
std::map<tr_log_level, char const*> const level_names_;
|
||||
|
||||
static auto const inline level_names_ = std::array<std::pair<tr_log_level, char const*>, 5U>{ {
|
||||
{ TR_LOG_CRITICAL, C_("Logging level", "Critical") },
|
||||
{ TR_LOG_ERROR, C_("Logging level", "Error") },
|
||||
{ TR_LOG_WARN, C_("Logging level", "Warning") },
|
||||
{ TR_LOG_INFO, C_("Logging level", "Information") },
|
||||
{ TR_LOG_DEBUG, C_("Logging level", "Debug") },
|
||||
} };
|
||||
};
|
||||
|
||||
namespace
|
||||
|
@ -163,6 +171,7 @@ void MessageLogWindow::Impl::level_combo_init(Gtk::ComboBox* level_combo) const
|
|||
|
||||
auto has_pref_level = false;
|
||||
auto items = std::vector<std::pair<Glib::ustring, int>>{};
|
||||
items.reserve(std::size(level_names_));
|
||||
for (auto const& [level, name] : level_names_)
|
||||
{
|
||||
items.emplace_back(name, level);
|
||||
|
@ -213,8 +222,11 @@ void MessageLogWindow::Impl::doSave(std::string const& filename)
|
|||
auto const* const node = row.get_value(message_log_cols.tr_msg);
|
||||
auto const date = gtr_asctime(node->when);
|
||||
|
||||
auto const it = level_names_.find(node->level);
|
||||
auto const* const level_str = it != std::end(level_names_) ? it->second : "???";
|
||||
auto const iter = std::find_if(
|
||||
std::begin(level_names_),
|
||||
std::end(level_names_),
|
||||
[key = node->level](auto const& item) { return item.first == key; });
|
||||
auto const* const level_str = iter != std::end(level_names_) ? iter->second : "???";
|
||||
|
||||
fmt::print(stream, "{}\t{}\t{}\t{}\n", date, level_str, node->name, node->message);
|
||||
}
|
||||
|
@ -477,13 +489,6 @@ MessageLogWindow::Impl::Impl(
|
|||
, refresh_tag_(Glib::signal_timeout().connect_seconds(
|
||||
sigc::mem_fun(*this, &Impl::onRefresh),
|
||||
SECONDARY_WINDOW_REFRESH_INTERVAL_SECONDS))
|
||||
, level_names_{ {
|
||||
{ TR_LOG_CRITICAL, C_("Logging level", "Critical") },
|
||||
{ TR_LOG_ERROR, C_("Logging level", "Error") },
|
||||
{ TR_LOG_WARN, C_("Logging level", "Warning") },
|
||||
{ TR_LOG_INFO, C_("Logging level", "Information") },
|
||||
{ TR_LOG_DEBUG, C_("Logging level", "Debug") },
|
||||
} }
|
||||
{
|
||||
/**
|
||||
*** toolbar
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
TorrentFilter::TorrentFilter()
|
||||
: Glib::ObjectBase(typeid(TorrentFilter))
|
||||
{
|
||||
|
@ -127,7 +130,7 @@ void TorrentFilter::update(Torrent::ChangeFlags changes)
|
|||
|
||||
if (activity_type_ != Activity::ALL)
|
||||
{
|
||||
static auto const activity_flags = std::map<Activity, Torrent::ChangeFlags>({
|
||||
static constexpr auto ActivityFlags = std::array<std::pair<Activity, Torrent::ChangeFlags>, 7U>{ {
|
||||
{ Activity::DOWNLOADING, Flag::ACTIVITY },
|
||||
{ Activity::SEEDING, Flag::ACTIVITY },
|
||||
{ Activity::ACTIVE, Flag::ACTIVE_PEER_COUNT | Flag::ACTIVITY },
|
||||
|
@ -135,10 +138,13 @@ void TorrentFilter::update(Torrent::ChangeFlags changes)
|
|||
{ Activity::FINISHED, Flag::FINISHED },
|
||||
{ Activity::VERIFYING, Flag::ACTIVITY },
|
||||
{ Activity::ERROR, Flag::ERROR_CODE },
|
||||
});
|
||||
} };
|
||||
|
||||
auto const activity_flags_it = activity_flags.find(activity_type_);
|
||||
refilter_needed = activity_flags_it != activity_flags.end() && changes.test(activity_flags_it->second);
|
||||
auto const iter = std::find_if(
|
||||
std::begin(ActivityFlags),
|
||||
std::end(ActivityFlags),
|
||||
[key = activity_type_](auto const& row) { return row.first == key; });
|
||||
refilter_needed = iter != std::end(ActivityFlags) && changes.test(iter->second);
|
||||
}
|
||||
|
||||
if (!refilter_needed)
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <libtransmission/utils.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
|
@ -178,7 +180,8 @@ TorrentSorter::TorrentSorter()
|
|||
|
||||
void TorrentSorter::set_mode(std::string_view mode)
|
||||
{
|
||||
static auto const compare_funcs = std::map<std::string_view, CompareFunc>({
|
||||
static auto constexpr DefaultCompareFunc = &compare_by_name;
|
||||
static auto constexpr CompareFuncs = std::array<std::pair<std::string_view, CompareFunc>, 9U>{ {
|
||||
{ "sort-by-activity"sv, &compare_by_activity },
|
||||
{ "sort-by-age"sv, &compare_by_age },
|
||||
{ "sort-by-name"sv, &compare_by_name },
|
||||
|
@ -188,14 +191,13 @@ void TorrentSorter::set_mode(std::string_view mode)
|
|||
{ "sort-by-size"sv, &compare_by_size },
|
||||
{ "sort-by-state"sv, &compare_by_state },
|
||||
{ "sort-by-time-left"sv, &compare_by_eta },
|
||||
});
|
||||
|
||||
auto compare_func = &compare_by_name;
|
||||
if (auto const compare_func_it = compare_funcs.find(mode); compare_func_it != compare_funcs.end())
|
||||
{
|
||||
compare_func = compare_func_it->second;
|
||||
}
|
||||
} };
|
||||
|
||||
auto const iter = std::find_if(
|
||||
std::begin(CompareFuncs),
|
||||
std::end(CompareFuncs),
|
||||
[key = mode](auto const& row) { return row.first == key; });
|
||||
auto const compare_func = iter != std::end(CompareFuncs) ? iter->second : DefaultCompareFunc;
|
||||
if (compare_func_ == compare_func)
|
||||
{
|
||||
return;
|
||||
|
@ -224,8 +226,7 @@ int TorrentSorter::compare(Torrent const& lhs, Torrent const& rhs) const
|
|||
void TorrentSorter::update(Torrent::ChangeFlags changes)
|
||||
{
|
||||
using Flag = Torrent::ChangeFlag;
|
||||
|
||||
static auto const compare_flags = std::map<CompareFunc, Torrent::ChangeFlags>({
|
||||
static auto constexpr CompareFlags = std::array<std::pair<CompareFunc, Torrent::ChangeFlags>, 9U>{ {
|
||||
{ &compare_by_activity, Flag::ACTIVE_PEER_COUNT | Flag::QUEUE_POSITION | Flag::SPEED_DOWN | Flag::SPEED_UP },
|
||||
{ &compare_by_age, Flag::ADDED_DATE | Flag::NAME },
|
||||
{ &compare_by_eta, Flag::ETA | Flag::NAME },
|
||||
|
@ -235,10 +236,13 @@ void TorrentSorter::update(Torrent::ChangeFlags changes)
|
|||
{ &compare_by_ratio, Flag::QUEUE_POSITION | Flag::RATIO },
|
||||
{ &compare_by_size, Flag::NAME | Flag::TOTAL_SIZE },
|
||||
{ &compare_by_state, Flag::ACTIVITY | Flag::QUEUE_POSITION },
|
||||
});
|
||||
} };
|
||||
|
||||
if (auto const compare_flags_it = compare_flags.find(compare_func_);
|
||||
compare_flags_it != compare_flags.end() && changes.test(compare_flags_it->second))
|
||||
if (auto const iter = std::find_if(
|
||||
std::begin(CompareFlags),
|
||||
std::end(CompareFlags),
|
||||
[key = compare_func_](auto const& row) { return row.first == key; });
|
||||
iter != std::end(CompareFlags) && changes.test(iter->second))
|
||||
{
|
||||
changed(Change::DIFFERENT);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <chrono>
|
||||
#include <cstddef> // size_t
|
||||
#include <iterator> // back_insert_iterator, empty
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
@ -22,6 +22,8 @@
|
|||
#include <fmt/chrono.h>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <small/map.hpp>
|
||||
|
||||
#include "libtransmission/file.h"
|
||||
#include "libtransmission/log.h"
|
||||
#include "libtransmission/tr-assert.h"
|
||||
|
@ -246,12 +248,12 @@ void tr_logAddMessage(char const* file, long line, tr_log_level level, std::stri
|
|||
auto const lock = log_state.unique_lock();
|
||||
|
||||
// don't log the same warning ad infinitum.
|
||||
// it's not useful after some point.
|
||||
// at some point, it stops being useful.
|
||||
bool last_one = false;
|
||||
if (level == TR_LOG_CRITICAL || level == TR_LOG_ERROR || level == TR_LOG_WARN)
|
||||
{
|
||||
static auto constexpr MaxRepeat = size_t{ 30 };
|
||||
static auto counts = new std::map<std::pair<std::string_view, int>, size_t>{};
|
||||
static auto* const counts = new small::map<std::pair<std::string_view, long>, size_t>{};
|
||||
|
||||
auto& count = (*counts)[std::make_pair(filename, line)];
|
||||
++count;
|
||||
|
@ -267,12 +269,8 @@ void tr_logAddMessage(char const* file, long line, tr_log_level level, std::stri
|
|||
logAddImpl(filename, line, level, std::move(msg), name);
|
||||
if (last_one)
|
||||
{
|
||||
logAddImpl(
|
||||
filename,
|
||||
line,
|
||||
level,
|
||||
_("Too many messages like this! I won't log this message anymore this session."),
|
||||
name);
|
||||
char const* final_msg = _("Too many messages like this! I won't log this message anymore this session.");
|
||||
logAddImpl(filename, line, level, final_msg, name);
|
||||
}
|
||||
|
||||
errno = err;
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
|
||||
#include <algorithm> // std::min, std::partial_sort
|
||||
#include <cstddef>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <small/set.hpp>
|
||||
|
||||
#define LIBTRANSMISSION_PEER_MODULE
|
||||
|
||||
#include "libtransmission/transmission.h"
|
||||
|
@ -136,11 +137,12 @@ std::vector<tr_block_span_t> Wishlist::next(size_t n_wanted_blocks)
|
|||
|
||||
// We usually won't need all the candidates to be sorted until endgame, so don't
|
||||
// waste cycles sorting all of them here. partial sort is enough.
|
||||
static auto constexpr MaxSortedPieces = size_t{ 30 };
|
||||
static auto constexpr MaxSortedPieces = size_t{ 30U };
|
||||
auto const middle = std::min(std::size(candidates), MaxSortedPieces);
|
||||
std::partial_sort(std::begin(candidates), std::begin(candidates) + middle, std::end(candidates));
|
||||
|
||||
auto blocks = std::set<tr_block_index_t>{};
|
||||
auto blocks = small::set<tr_block_index_t, 4096U>{};
|
||||
blocks.reserve(n_wanted_blocks);
|
||||
for (auto const& candidate : candidates)
|
||||
{
|
||||
// do we have enough?
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <set>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
|
@ -91,15 +90,18 @@ void tr_torrents::remove(tr_torrent const* tor, time_t current_time)
|
|||
|
||||
std::vector<tr_torrent_id_t> tr_torrents::removedSince(time_t timestamp) const
|
||||
{
|
||||
auto ids = std::set<tr_torrent_id_t>{};
|
||||
auto ids = std::vector<tr_torrent_id_t>{};
|
||||
ids.reserve(std::size(removed_));
|
||||
|
||||
for (auto const& [id, removed_at] : removed_)
|
||||
{
|
||||
if (removed_at >= timestamp)
|
||||
{
|
||||
ids.insert(id);
|
||||
ids.emplace_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
return { std::begin(ids), std::end(ids) };
|
||||
std::sort(std::begin(ids), std::end(ids));
|
||||
ids.erase(std::unique(std::begin(ids), std::end(ids)), std::end(ids));
|
||||
return ids;
|
||||
}
|
||||
|
|
|
@ -493,18 +493,20 @@ std::vector<int> tr_num_parse_range(std::string_view str)
|
|||
{
|
||||
using namespace tr_num_parse_range_impl;
|
||||
|
||||
auto values = std::set<int>{};
|
||||
auto values = std::vector<int>{};
|
||||
auto token = std::string_view{};
|
||||
auto range = number_range{};
|
||||
while (tr_strv_sep(&str, &token, ',') && parseNumberSection(token, range))
|
||||
{
|
||||
for (auto i = range.low; i <= range.high; ++i)
|
||||
{
|
||||
values.insert(i);
|
||||
values.emplace_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
return { std::begin(values), std::end(values) };
|
||||
std::sort(std::begin(values), std::end(values));
|
||||
values.erase(std::unique(std::begin(values), std::end(values)), std::end(values));
|
||||
return values;
|
||||
}
|
||||
|
||||
// ---
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include <small/set.hpp>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QStyle>
|
||||
|
||||
|
@ -223,7 +224,7 @@ uint64_t FileTreeItem::size() const
|
|||
|
||||
std::pair<int, int> FileTreeItem::update(QString const& name, bool wanted, int priority, uint64_t have_size, bool update_fields)
|
||||
{
|
||||
auto changed_columns = std::set<int>{};
|
||||
auto changed_columns = small::max_size_set<int, FileTreeModel::NUM_COLUMNS>{};
|
||||
|
||||
if (name_ != name)
|
||||
{
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
#include <small/map.hpp>
|
||||
|
||||
#include <libtransmission/transmission.h> // priorities
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
@ -470,7 +471,7 @@ void FileTreeModel::emitSubtreeChanged(QModelIndex const& idx, int first_column,
|
|||
|
||||
void FileTreeModel::twiddleWanted(QModelIndexList const& indices)
|
||||
{
|
||||
std::map<bool, QModelIndexList> wanted_indices;
|
||||
auto wanted_indices = small::max_size_map<bool, QModelIndexList, 2U>{};
|
||||
|
||||
for (QModelIndex const& i : getOrphanIndices(indices))
|
||||
{
|
||||
|
@ -489,7 +490,7 @@ void FileTreeModel::twiddleWanted(QModelIndexList const& indices)
|
|||
|
||||
void FileTreeModel::twiddlePriority(QModelIndexList const& indices)
|
||||
{
|
||||
std::map<int, QModelIndexList> priority_indices;
|
||||
auto priority_indices = small::max_size_map<int, QModelIndexList, 8U>{};
|
||||
|
||||
for (QModelIndex const& i : getOrphanIndices(indices))
|
||||
{
|
||||
|
|
|
@ -155,7 +155,7 @@ void FilterBar::refreshTrackers()
|
|||
return i;
|
||||
};
|
||||
|
||||
auto new_trackers = std::map<QString, int>(torrents_per_sitename.begin(), torrents_per_sitename.end());
|
||||
auto new_trackers = small::map<QString, int>{ torrents_per_sitename.begin(), torrents_per_sitename.end() };
|
||||
auto old_it = sitename_counts_.cbegin();
|
||||
auto new_it = new_trackers.cbegin();
|
||||
auto const old_end = sitename_counts_.cend();
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
|
||||
#include <small/map.hpp>
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QStandardItemModel>
|
||||
|
@ -63,7 +64,7 @@ private:
|
|||
FilterBarComboBox* const tracker_combo_ = createTrackerCombo(tracker_model_);
|
||||
QLineEdit* const line_edit_ = new QLineEdit{ this };
|
||||
|
||||
std::map<QString, int> sitename_counts_;
|
||||
small::map<QString, int> sitename_counts_;
|
||||
QTimer recount_timer_;
|
||||
Pending pending_ = {};
|
||||
bool is_bootstrapping_ = {};
|
||||
|
|
|
@ -54,8 +54,6 @@ private slots:
|
|||
void onSessionUpdated();
|
||||
|
||||
private:
|
||||
using mybins_t = std::map<uint32_t, int32_t>;
|
||||
|
||||
void reload();
|
||||
void updateWidgetsLocality();
|
||||
void clearInfo();
|
||||
|
|
19
qt/Prefs.cc
19
qt/Prefs.cc
|
@ -201,6 +201,19 @@ bool isValidUtf8(QByteArray const& byteArray)
|
|||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto pref_is_savable(int pref)
|
||||
{
|
||||
switch (pref)
|
||||
{
|
||||
// these are the prefs that don't get saved to settings.json
|
||||
// when the application exits.
|
||||
case Prefs::FILTER_TEXT:
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/***
|
||||
|
@ -220,10 +233,6 @@ Prefs::Prefs(QString config_dir)
|
|||
|
||||
#endif
|
||||
|
||||
// these are the prefs that don't get saved to settings.json
|
||||
// when the application exits.
|
||||
temporary_prefs_.insert(FILTER_TEXT);
|
||||
|
||||
auto const app_defaults = get_default_app_settings();
|
||||
auto settings = tr_sessionLoadSettings(&app_defaults, config_dir_.toUtf8().constData(), nullptr);
|
||||
ensureSoundCommandIsAList(&settings);
|
||||
|
@ -323,7 +332,7 @@ Prefs::~Prefs()
|
|||
|
||||
for (int i = 0; i < PREFS_COUNT; ++i)
|
||||
{
|
||||
if (temporary_prefs_.count(i) != 0U)
|
||||
if (!pref_is_savable(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -204,7 +204,6 @@ private:
|
|||
|
||||
QString const config_dir_;
|
||||
|
||||
std::set<int> temporary_prefs_;
|
||||
std::array<QVariant, PREFS_COUNT> mutable values_;
|
||||
|
||||
static std::array<PrefItem, PREFS_COUNT> const Items;
|
||||
|
|
Loading…
Reference in a new issue