Skip to content

Commit

Permalink
sched-ext: introduce the concept of performance profiles (#19)
Browse files Browse the repository at this point in the history
Add an extra combo box to select the "performance profile" for the
currently selected sched-ext scheduler. The selected profile will be
automatically converted into the appropriate flags for the chosen
scheduler.

Currently, only scx_bpfland and scx_lavd are supported, so the
additional combo box will be visible only when one of these schedulers
is selected.

Tested-by: Peter Jung <[email protected]>

Signed-off-by: Andrea Righi <[email protected]>
  • Loading branch information
arighi authored Aug 26, 2024
1 parent 666b97d commit 9da530f
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 26 deletions.
89 changes: 66 additions & 23 deletions src/schedext-window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ SchedExtWindow::SchedExtWindow(QWidget* parent)
<< "scx_userland";
m_ui->schedext_combo_box->addItems(sched_names);

// Selecting the performance profile
QStringList sched_profiles;
sched_profiles << "default"
<< "gaming"
<< "lowlatency"
<< "powersave";
m_ui->schedext_profile_combo_box->addItems(sched_profiles);

m_ui->current_sched_label->setText(QString::fromStdString(get_current_scheduler()));

// setup timer
Expand All @@ -124,6 +132,13 @@ SchedExtWindow::SchedExtWindow(QWidget* parent)
connect(m_sched_timer, &QTimer::timeout, this, &SchedExtWindow::update_current_sched);
m_sched_timer->start(1s);

connect(m_ui->schedext_combo_box,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&SchedExtWindow::on_sched_changed);
// Initialize the visibility of the profile selection box
on_sched_changed();

// Connect buttons signal
connect(m_ui->apply_button, &QPushButton::clicked, this, &SchedExtWindow::on_apply);
connect(m_ui->disable_button, &QPushButton::clicked, this, &SchedExtWindow::on_disable);
Expand Down Expand Up @@ -155,6 +170,22 @@ void SchedExtWindow::on_disable() noexcept {
m_ui->apply_button->setEnabled(true);
}

void SchedExtWindow::on_sched_changed() noexcept {
const auto& scheduler = m_ui->schedext_combo_box->currentText();

// Show or hide the profile selection UI based on the selected scheduler
//
// NOTE: only scx_bpfland and scx_lavd support different preset profiles at
// the moment.
if (scheduler == "scx_bpfland" || scheduler == "scx_lavd") {
m_ui->scheduler_profile_select_label->setVisible(true);
m_ui->schedext_profile_combo_box->setVisible(true);
} else {
m_ui->scheduler_profile_select_label->setVisible(false);
m_ui->schedext_profile_combo_box->setVisible(false);
}
}

void SchedExtWindow::on_apply() noexcept {
m_ui->disable_button->setEnabled(false);
m_ui->apply_button->setEnabled(false);
Expand All @@ -167,35 +198,47 @@ void SchedExtWindow::on_apply() noexcept {
return "restart"sv;
}();

static constexpr auto is_flags_commented = []() -> bool {
static constexpr auto get_scx_flags_sed = [](std::string_view scx_sched,
std::string_view scx_profile,
std::string_view scx_extra_flags) -> std::string {
using namespace std::string_view_literals;
static constexpr auto scx_conf_path = "/etc/default/scx"sv;
const auto& scx_conf_content = utils::read_whole_file(scx_conf_path);
return scx_conf_content.find("#SCX_FLAGS="sv) != std::string::npos;
};
static constexpr auto get_scx_flags_sed = [](std::string_view sched_flags_text, bool flags_commented) -> std::string {
using namespace std::string_literals;
if (sched_flags_text.empty() && !flags_commented) {
// comment out flags in scx
return "-e 's/SCX_FLAGS=/#SCX_FLAGS=/'"s;
} else if (!sched_flags_text.empty() && flags_commented) {
// set flags in scx
return fmt::format(R"(-e "s/.*SCX_FLAGS=.*/SCX_FLAGS='{}'/")", sched_flags_text);
} else if (!sched_flags_text.empty() && !flags_commented) {
// set flags in scx
return fmt::format(R"(-e "s/SCX_FLAGS=.*/SCX_FLAGS='{}'/")", sched_flags_text);

std::string_view scx_base_flags;

// Map the selected performance profile to the different scheduler
// options.
//
// NOTE: only scx_bpfland and scx_lavd are supported for now.
if (scx_profile == "default"sv) {
} else if (scx_profile == "gaming"sv) {
if (scx_sched == "scx_bpfland"sv)
scx_base_flags = "-c 0 -k -m performance"sv;
else if (scx_sched == "scx_lavd"sv)
scx_base_flags = "--performance"sv;
} else if (scx_profile == "lowlatency"sv) {
if (scx_sched == "scx_bpfland"sv)
scx_base_flags = "--lowlatency"sv;
else if (scx_sched == "scx_lavd"sv)
scx_base_flags = "--performance"sv;
} else if (scx_profile == "powersave"sv) {
if (scx_sched == "scx_bpfland"sv)
scx_base_flags = "-m powersave"sv;
else if (scx_sched == "scx_lavd"sv)
scx_base_flags = "--powersave"sv;
}
return ""s;
};

const bool flags_commented = is_flags_commented();
return fmt::format(R"(-e 's/^\s*#\?\s*SCX_FLAGS=.*$/SCX_FLAGS="{} {}"/')", scx_base_flags, scx_extra_flags);
};

// TODO(vnepogodin): refactor that
const auto& sched_flags_text = m_ui->schedext_flags_edit->text().trimmed().toStdString();
const auto& scx_flags_sed = get_scx_flags_sed(sched_flags_text, flags_commented);

const auto& current_selected = m_ui->schedext_combo_box->currentText().toStdString();
const auto& sed_cmd = fmt::format("sed -e 's/SCX_SCHEDULER=.*/SCX_SCHEDULER={}/' {} -i /etc/default/scx && systemctl {} scx", current_selected, scx_flags_sed, service_cmd);
const auto& current_profile = m_ui->schedext_profile_combo_box->currentText().toStdString();
const auto& extra_flags = m_ui->schedext_flags_edit->text().trimmed().toStdString();

const auto& scx_flags_sed = get_scx_flags_sed(current_selected, current_profile, extra_flags);

const auto& sed_cmd = fmt::format("sed -e 's/SCX_SCHEDULER=.*/SCX_SCHEDULER={}/' {} -i /etc/default/scx && systemctl {} scx", current_selected, scx_flags_sed, service_cmd);

QProcess::startDetached("/usr/bin/pkexec", {"/usr/bin/bash", "-c", QString::fromStdString(sed_cmd)});
fmt::print("Applying scx {}\n", current_selected);

Expand Down
1 change: 1 addition & 0 deletions src/schedext-window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class SchedExtWindow final : public QMainWindow {
private:
void on_apply() noexcept;
void on_disable() noexcept;
void on_sched_changed() noexcept;

std::vector<std::string> m_previously_set_options{};
std::unique_ptr<Ui::SchedExtWindow> m_ui = std::make_unique<Ui::SchedExtWindow>();
Expand Down
16 changes: 13 additions & 3 deletions src/schedext-window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@
<item row="1" column="3">
<widget class="QComboBox" name="schedext_combo_box"/>
</item>
<item row="2" column="1">
<widget class="QLabel" name="scheduler_profile_select_label">
<property name="text">
<string> Select scheduler profile:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QComboBox" name="schedext_profile_combo_box"/>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_6">
<property name="orientation">
Expand All @@ -106,14 +116,14 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<widget class="QLabel" name="scheduler_set_flags_label">
<property name="text">
<string>Set sched-ext scheduler flags:</string>
<string>Set sched-ext extra scheduler flags:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<item row="3" column="3">
<widget class="QLineEdit" name="schedext_flags_edit"/>
</item>
</layout>
Expand Down

0 comments on commit 9da530f

Please sign in to comment.