Set the I/O scheduler of loop devices to 'none'
The user interface of Android devices becomes very slow under memory pressure. This is because Android uses the zram driver on top of the loop driver for swapping, because under memory pressure the swap code alternates reads and writes quickly, because mq-deadline is the default scheduler for loop devices and because mq-deadline delays writes by five seconds for such a workload with default settings. Fix this by selecting I/O scheduler 'none' for loop devices. Bug: 194450129 Test: Built Android images, installed these and verified that the I/O scheduler of all loop devices is 'none' instead of 'mq-deadline'. Change-Id: Ia5f606504b663948ab56955cad5a71885a356430 Signed-off-by: Bart Van Assche <bvanassche@acm.org>
This commit is contained in:
parent
06b95de973
commit
ec5f635270
1 changed files with 34 additions and 0 deletions
|
@ -34,11 +34,13 @@
|
|||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
@ -101,6 +103,7 @@ using android::base::GetUintProperty;
|
|||
using android::base::Realpath;
|
||||
using android::base::SetProperty;
|
||||
using android::base::StartsWith;
|
||||
using android::base::StringPrintf;
|
||||
using android::base::Timer;
|
||||
using android::base::unique_fd;
|
||||
using android::dm::DeviceMapper;
|
||||
|
@ -2044,6 +2047,35 @@ int fs_mgr_do_tmpfs_mount(const char *n_name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool ConfigureIoScheduler(const std::string& device_path) {
|
||||
if (!StartsWith(device_path, "/dev/")) {
|
||||
LERROR << __func__ << ": invalid argument " << device_path;
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string iosched_path =
|
||||
StringPrintf("/sys/block/%s/queue/scheduler", Basename(device_path).c_str());
|
||||
unique_fd iosched_fd(open(iosched_path.c_str(), O_RDWR | O_CLOEXEC));
|
||||
if (iosched_fd.get() == -1) {
|
||||
PERROR << __func__ << ": failed to open " << iosched_path;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Kernels before v4.1 only support 'noop'. Kernels [v4.1, v5.0) support
|
||||
// 'noop' and 'none'. Kernels v5.0 and later only support 'none'.
|
||||
static constexpr const std::array<std::string_view, 2> kNoScheduler = {"none", "noop"};
|
||||
|
||||
for (const std::string_view& scheduler : kNoScheduler) {
|
||||
int ret = write(iosched_fd.get(), scheduler.data(), scheduler.size());
|
||||
if (ret > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
PERROR << __func__ << ": failed to write to " << iosched_path;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool InstallZramDevice(const std::string& device) {
|
||||
if (!android::base::WriteStringToFile(device, ZRAM_BACK_DEV)) {
|
||||
PERROR << "Cannot write " << device << " in: " << ZRAM_BACK_DEV;
|
||||
|
@ -2076,6 +2108,8 @@ static bool PrepareZramBackingDevice(off64_t size) {
|
|||
return false;
|
||||
}
|
||||
|
||||
ConfigureIoScheduler(loop_device);
|
||||
|
||||
// set block size & direct IO
|
||||
unique_fd loop_fd(TEMP_FAILURE_RETRY(open(loop_device.c_str(), O_RDWR | O_CLOEXEC)));
|
||||
if (loop_fd.get() == -1) {
|
||||
|
|
Loading…
Reference in a new issue