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

Introduce new, better performing IoRingLogDevice2. #155

Merged
merged 11 commits into from
Jul 25, 2024
2 changes: 1 addition & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def configure(self):


def requirements(self):
self.requires("batteries/0.52.4", **VISIBLE)
self.requires("batteries/0.53.0", **VISIBLE)
self.requires("boost/1.83.0", **VISIBLE)
self.requires("cli11/2.3.2", **VISIBLE)
self.requires("glog/0.6.0", **VISIBLE)
Expand Down
30 changes: 30 additions & 0 deletions src/llfs/ioring_log_config2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//#=##=##=#==#=#==#===#+==#+==========+==+=+=+=+=+=++=+++=+++++=-++++=-+++++++++++
//
// Part of the LLFS Project, under Apache License v2.0.
// See https://www.apache.org/licenses/LICENSE-2.0 for license information.
// SPDX short identifier: Apache-2.0
//
//+++++++++++-+-+--+----- --- -- - - - -

#include <llfs/ioring_log_config2.hpp>
//

#include <llfs/log_device_config2.hpp>

namespace llfs {

//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- - - - -
//
/*static*/ IoRingLogConfig2 IoRingLogConfig2::from_packed(
const FileOffsetPtr<const PackedLogDeviceConfig2&>& packed_config)
{
return IoRingLogConfig2{
.control_block_offset =
packed_config.absolute_from_relative_offset(packed_config->control_block_offset),
.log_capacity = packed_config->logical_size,
.device_page_size_log2 = packed_config->device_page_size_log2,
.data_alignment_log2 = packed_config->data_alignment_log2,
};
}

} //namespace llfs
45 changes: 45 additions & 0 deletions src/llfs/ioring_log_config2.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//#=##=##=#==#=#==#===#+==#+==========+==+=+=+=+=+=++=+++=+++++=-++++=-+++++++++++
//
// Part of the LLFS Project, under Apache License v2.0.
// See https://www.apache.org/licenses/LICENSE-2.0 for license information.
// SPDX short identifier: Apache-2.0
//
//+++++++++++-+-+--+----- --- -- - - - -

#pragma once
#ifndef LLFS_IORING_LOG_CONFIG2_HPP
#define LLFS_IORING_LOG_CONFIG2_HPP

#include <llfs/config.hpp>
//

#include <llfs/file_offset_ptr.hpp>
#include <llfs/int_types.hpp>
#include <llfs/ioring_log_config2.hpp>

namespace llfs {

struct PackedLogDeviceConfig2;

struct IoRingLogConfig2 {
static IoRingLogConfig2 from_packed(
const FileOffsetPtr<const PackedLogDeviceConfig2&>& packed_config);

//+++++++++++-+-+--+----- --- -- - - - -

i64 control_block_offset;
u64 log_capacity;
u16 device_page_size_log2;
u16 data_alignment_log2;

//+++++++++++-+-+--+----- --- -- - - - -

i64 control_block_size() const noexcept
{
return i64{1} << this->data_alignment_log2;
}
};

} //namespace llfs

#endif // LLFS_IORING_LOG_CONFIG2_HPP
106 changes: 14 additions & 92 deletions src/llfs/ioring_log_device.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <gtest/gtest.h>

#include <llfs/ioring.hpp>
#include <llfs/ioring_log_device.test.hpp>
#include <llfs/log_device_config.hpp>
#include <llfs/storage_context.hpp>
#include <llfs/uuid.hpp>
Expand Down Expand Up @@ -172,6 +173,8 @@ TEST(IoringLogDeviceTest, StorageFile)
*/
TEST(IoringLogDeviceTest, Benchmark)
{
using llfs::read_test_var;

const char* file_name = //
std::getenv("LLFS_LOG_DEVICE_FILE");

Expand All @@ -182,34 +185,18 @@ TEST(IoringLogDeviceTest, Benchmark)

std::cout << "LLFS_LOG_DEVICE_FILE=" << batt::c_str_literal(file_name) << std::endl;

//---- --- -- - - - -
const auto read_var = [](const char* name, auto default_value) {
using value_type = decltype(default_value);

const value_type value =
batt::getenv_as<value_type>("LLFS_STORAGE_CONTEXT_QUEUE_DEPTH").value_or(default_value);
//+++++++++++-+-+--+----- --- -- - - - -

std::cout << name << "=" << value << std::endl;
const usize queue_depth = read_test_var("LLFS_STORAGE_CONTEXT_QUEUE_DEPTH", usize{64});
const usize thread_pool_size = read_test_var("LLFS_STORAGE_CONTEXT_THREADS", usize{1});
const usize pages_per_block = read_test_var("LLFS_LOG_DEVICE_PAGES_PER_BLOCK", usize{32});
const usize log_queue_depth = read_test_var("LLFS_LOG_DEVICE_QUEUE_DEPTH", usize{1024});

return value;
};
//---- --- -- - - - -
//+++++++++++-+-+--+----- --- -- - - - -

const usize queue_depth = read_var("LLFS_STORAGE_CONTEXT_QUEUE_DEPTH", usize{64});
const usize thread_pool_size = read_var("LLFS_STORAGE_CONTEXT_THREADS", usize{1});
const usize pages_per_block = read_var("LLFS_LOG_DEVICE_PAGES_PER_BLOCK", usize{32});
const usize log_size = read_var("LLFS_LOG_DEVICE_SIZE_KB", usize{1024 * 64}) * 1024;
const usize log_queue_depth = read_var("LLFS_LOG_DEVICE_QUEUE_DEPTH", usize{1024});
const usize total_to_write = read_var("LLFS_LOG_DEVICE_WRITE_KB", usize{1024 * 1024}) * 1024;
const usize append_size = read_var("LLFS_LOG_DEVICE_APPEND_SIZE", usize{256});
const usize trim_size = read_var("LLFS_LOG_DEVICE_TRIM_SIZE", usize{4 * 1024 * 1024});
const usize trim_trigger = read_var("LLFS_LOG_DEVICE_TRIM_TRIGGER", //
usize{log_size - trim_size * 2});
const usize repeat_count = read_var("LLFS_LOG_DEVICE_REPEAT", usize{3});
llfs::run_log_device_benchmark([&](usize log_size, bool create, auto&& consume_log_fn) {
BATT_CHECK(create);

//+++++++++++-+-+--+----- --- -- - - - -
//
for (usize retry = 0; retry < repeat_count; ++retry) {
auto scoped_ioring = llfs::ScopedIoRing::make_new(llfs::MaxQueueDepth{queue_depth},
llfs::ThreadPoolSize{thread_pool_size});

Expand Down Expand Up @@ -259,75 +246,10 @@ TEST(IoringLogDeviceTest, Benchmark)

llfs::IoRingLogDevice& log_device = **status_or_log_device;

// Generate some random data.
// Run the workload.
//
std::vector<u64> data(32 * 1024 * 1024);
std::default_random_engine rng{1};
for (u64& word : data) {
word = rng();
}

auto start = std::chrono::steady_clock::now();

std::thread writer_thread{[&] {
llfs::LogDevice::Writer& log_writer = log_device.writer();

std::uniform_int_distribution<usize> pick_offset{
0, data.size() - (append_size + sizeof(u64) - 1) / sizeof(u64)};

usize n_written = 0;
while (n_written < total_to_write) {
BATT_CHECK_OK(log_writer.await(llfs::BytesAvailable{.size = append_size}));

llfs::StatusOr<llfs::MutableBuffer> buffer = log_writer.prepare(append_size);
BATT_CHECK_OK(buffer);

std::memcpy(buffer->data(), &data[pick_offset(rng)], buffer->size());

BATT_CHECK_OK(log_writer.commit(buffer->size()));

n_written += buffer->size();
}

BATT_CHECK_OK(log_device.flush());

log_device.halt();
}};

std::thread trimmer_thread{[&] {
for (;;) {
llfs::SlotRange durable = log_device.slot_range(llfs::LogReadMode::kDurable);

llfs::Status sync_status =
log_device.sync(llfs::LogReadMode::kDurable,
llfs::SlotUpperBoundAt{durable.lower_bound + trim_trigger});

if (!sync_status.ok()) {
break;
}

llfs::Status trim_status = log_device.trim(durable.lower_bound + trim_size);

if (!trim_status.ok()) {
break;
}
}
}};

writer_thread.join();
trimmer_thread.join();
log_device.join();

auto finish = std::chrono::steady_clock::now();

double duration_sec =
double(std::chrono::duration_cast<std::chrono::microseconds>(finish - start).count()) /
(1000.0 * 1000.0);

LLFS_LOG_INFO() << total_to_write << " bytes written in " << duration_sec
<< " seconds; rate=" << (double(total_to_write) / duration_sec) / 1000000.0
<< "MB/s";
}
consume_log_fn(log_device);
});
}

} // namespace
Expand Down
Loading