Add configurable NuDB block size feature

- Implement parseBlockSize() function with validation
- Add nudb_block_size configuration parameter
- Support block sizes from 4K to 64K (power of 2)
- Add comprehensive logging and error handling
- Maintain backward compatibility with 4K default
This commit is contained in:
Valon Mamudi
2025-06-03 17:45:35 +02:00
parent 2a61aee562
commit 6e11a3f1a3
2 changed files with 80 additions and 1 deletions

View File

@@ -975,6 +975,40 @@
# number of ledger records online. Must be greater
# than or equal to ledger_history.
#
# Optional keys for NuDB only:
#
# nudb_block_size Block size in bytes for NuDB storage.
# Must be a power of 2 between 4096 and 65536.
# Default is 4096.
#
# This parameter controls the fundamental storage unit
# size for NuDB's internal data structures. The choice
# of block size can significantly impact performance
# depending on your storage hardware and filesystem:
#
# - 4096 bytes: Optimal for most standard SSDs and
# traditional filesystems (ext4, NTFS, HFS+).
# Provides good balance of performance and storage
# efficiency. Recommended for most deployments.
#
# - 8192-16384 bytes: May improve performance on
# high-end NVMe SSDs and copy-on-write filesystems
# like ZFS or Btrfs that benefit from larger block
# alignment. Can reduce metadata overhead for large
# databases.
#
# - 32768-65536 bytes: Suitable for specialized
# high-throughput scenarios with very fast storage.
# May increase memory usage and reduce efficiency
# for smaller databases.
#
# Note: This setting cannot be changed after database
# creation without rebuilding the entire database.
# Choose carefully based on your hardware and expected
# database size.
#
# Example: nudb_block_size=4096
#
# These keys modify the behavior of online_delete, and thus are only
# relevant if online_delete is defined and non-zero:
#
@@ -1471,6 +1505,7 @@ secure_gateway = 127.0.0.1
[node_db]
type=NuDB
path=/var/lib/rippled/db/nudb
nudb_block_size=4096
online_delete=512
advisory_delete=0

View File

@@ -24,6 +24,7 @@
#include <xrpld/nodestore/detail/codec.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/core/LexicalCast.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <boost/filesystem.hpp>
@@ -52,6 +53,7 @@ public:
size_t const keyBytes_;
std::size_t const burstSize_;
std::string const name_;
std::size_t const blockSize_;
nudb::store db_;
std::atomic<bool> deletePath_;
Scheduler& scheduler_;
@@ -66,6 +68,7 @@ public:
, keyBytes_(keyBytes)
, burstSize_(burstSize)
, name_(get(keyValues, "path"))
, blockSize_(parseBlockSize(keyValues, journal))
, deletePath_(false)
, scheduler_(scheduler)
{
@@ -85,6 +88,7 @@ public:
, keyBytes_(keyBytes)
, burstSize_(burstSize)
, name_(get(keyValues, "path"))
, blockSize_(parseBlockSize(keyValues, journal))
, db_(context)
, deletePath_(false)
, scheduler_(scheduler)
@@ -143,7 +147,7 @@ public:
uid,
salt,
keyBytes_,
nudb::block_size(kp),
blockSize_,
0.50,
ec);
if (ec == nudb::errc::file_exists)
@@ -359,6 +363,46 @@ public:
{
return 3;
}
private:
static std::size_t
parseBlockSize(Section const& keyValues, beast::Journal journal)
{
std::size_t blockSize = 4096; // Default 4K
std::string blockSizeStr;
if (get_if_exists(keyValues, "nudb_block_size", blockSizeStr))
{
try
{
blockSize = beast::lexicalCastThrow<std::size_t>(blockSizeStr);
// Validate: must be power of 2 between 4K and 64K
if (blockSize < 4096 || blockSize > 65536 ||
(blockSize & (blockSize - 1)) != 0)
{
JLOG(journal.warn())
<< "Invalid nudb_block_size: " << blockSize
<< ". Must be power of 2 between 4096 and 65536. Using default 4096.";
blockSize = 4096;
}
else
{
JLOG(journal.info())
<< "Using custom NuDB block size: " << blockSize << " bytes";
}
}
catch (std::exception const& e)
{
JLOG(journal.warn())
<< "Invalid nudb_block_size value: " << blockSizeStr
<< ". Using default 4096. Error: " << e.what();
blockSize = 4096;
}
}
return blockSize;
}
};
//------------------------------------------------------------------------------