mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-22 12:26:37 +00:00
config: add mmap read env alias (#4021)
This commit is contained in:
@@ -76,6 +76,11 @@ Current guidance:
|
|||||||
- `RUSTFS_SCANNER_CYCLE_MAX_OBJECTS` (canonical)
|
- `RUSTFS_SCANNER_CYCLE_MAX_OBJECTS` (canonical)
|
||||||
- `RUSTFS_SCANNER_CYCLE_MAX_DIRECTORIES` (canonical)
|
- `RUSTFS_SCANNER_CYCLE_MAX_DIRECTORIES` (canonical)
|
||||||
|
|
||||||
|
## Mmap read environment aliases
|
||||||
|
|
||||||
|
- `RUSTFS_OBJECT_MMAP_READ_ENABLE` (canonical)
|
||||||
|
- `RUSTFS_OBJECT_ZERO_COPY_ENABLE` (deprecated alias for compatibility)
|
||||||
|
|
||||||
## Health compatibility switches
|
## Health compatibility switches
|
||||||
|
|
||||||
- `RUSTFS_HEALTH_ENDPOINT_ENABLE`
|
- `RUSTFS_HEALTH_ENDPOINT_ENABLE`
|
||||||
|
|||||||
@@ -15,8 +15,9 @@
|
|||||||
//! Mmap-based read I/O configuration constants.
|
//! Mmap-based read I/O configuration constants.
|
||||||
//!
|
//!
|
||||||
//! This module defines environment variables and default values for mmap-based
|
//! This module defines environment variables and default values for mmap-based
|
||||||
//! read operations. Note: despite the "zero_copy" naming in env vars (kept for
|
//! read operations. Note: the legacy "zero_copy" env var is kept as a
|
||||||
//! backward compatibility), the actual implementation performs mmap-then-copy,
|
//! deprecated compatibility alias; the actual implementation performs
|
||||||
|
//! mmap-then-copy, not true zero-copy.
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Mmap Read Configuration
|
// Mmap Read Configuration
|
||||||
@@ -32,9 +33,13 @@
|
|||||||
/// - Acceptable values: `"true"` / `"false"` (case-insensitive) or a boolean typed config
|
/// - Acceptable values: `"true"` / `"false"` (case-insensitive) or a boolean typed config
|
||||||
/// - Semantics: When enabled, uses mmap on Unix systems for memory-mapped file reads;
|
/// - Semantics: When enabled, uses mmap on Unix systems for memory-mapped file reads;
|
||||||
/// falls back to regular I/O on non-Unix platforms or when mmap fails
|
/// falls back to regular I/O on non-Unix platforms or when mmap fails
|
||||||
/// - Example: `export RUSTFS_OBJECT_ZERO_COPY_ENABLE=true`
|
/// - Example: `export RUSTFS_OBJECT_MMAP_READ_ENABLE=true`
|
||||||
/// - Note: The env var name is kept as ZERO_COPY for backward compatibility.
|
pub const ENV_OBJECT_MMAP_READ_ENABLE: &str = "RUSTFS_OBJECT_MMAP_READ_ENABLE";
|
||||||
/// The actual behavior is mmap-then-copy, not true zero-copy.
|
|
||||||
|
/// Deprecated compatibility alias for mmap-based read enable.
|
||||||
|
///
|
||||||
|
/// Prefer [`ENV_OBJECT_MMAP_READ_ENABLE`]. When both variables are set, the
|
||||||
|
/// canonical mmap-read variable takes precedence.
|
||||||
pub const ENV_OBJECT_ZERO_COPY_ENABLE: &str = "RUSTFS_OBJECT_ZERO_COPY_ENABLE";
|
pub const ENV_OBJECT_ZERO_COPY_ENABLE: &str = "RUSTFS_OBJECT_ZERO_COPY_ENABLE";
|
||||||
|
|
||||||
/// Default: mmap-based reads are enabled.
|
/// Default: mmap-based reads are enabled.
|
||||||
@@ -45,7 +50,12 @@ pub const ENV_OBJECT_ZERO_COPY_ENABLE: &str = "RUSTFS_OBJECT_ZERO_COPY_ENABLE";
|
|||||||
///
|
///
|
||||||
/// On non-Unix platforms or when mmap fails, the system automatically falls back
|
/// On non-Unix platforms or when mmap fails, the system automatically falls back
|
||||||
/// to regular I/O without errors.
|
/// to regular I/O without errors.
|
||||||
pub const DEFAULT_OBJECT_ZERO_COPY_ENABLE: bool = true;
|
pub const DEFAULT_OBJECT_MMAP_READ_ENABLE: bool = true;
|
||||||
|
|
||||||
|
/// Deprecated compatibility alias for mmap-based read default.
|
||||||
|
///
|
||||||
|
/// Prefer [`DEFAULT_OBJECT_MMAP_READ_ENABLE`].
|
||||||
|
pub const DEFAULT_OBJECT_ZERO_COPY_ENABLE: bool = DEFAULT_OBJECT_MMAP_READ_ENABLE;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Direct I/O Configuration
|
// Direct I/O Configuration
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
use crate::disk::{self, DiskAPI as _, DiskStore, FileReader, error::DiskError};
|
use crate::disk::{self, DiskAPI as _, DiskStore, FileReader, error::DiskError};
|
||||||
use crate::erasure::coding::{BitrotReader, BitrotWriterWrapper, CustomWriter};
|
use crate::erasure::coding::{BitrotReader, BitrotWriterWrapper, CustomWriter};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
use rustfs_config::{DEFAULT_OBJECT_MMAP_READ_ENABLE, ENV_OBJECT_MMAP_READ_ENABLE, ENV_OBJECT_ZERO_COPY_ENABLE};
|
||||||
use rustfs_utils::HashAlgorithm;
|
use rustfs_utils::HashAlgorithm;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::io::{self, Cursor};
|
use std::io::{self, Cursor};
|
||||||
@@ -28,6 +29,14 @@ use tracing::debug;
|
|||||||
type BoxedObjectReader = Box<dyn AsyncRead + Send + Sync + Unpin>;
|
type BoxedObjectReader = Box<dyn AsyncRead + Send + Sync + Unpin>;
|
||||||
type OpenObjectReaderFuture = Pin<Box<dyn Future<Output = disk::error::Result<Option<BoxedObjectReader>>> + Send>>;
|
type OpenObjectReaderFuture = Pin<Box<dyn Future<Output = disk::error::Result<Option<BoxedObjectReader>>> + Send>>;
|
||||||
|
|
||||||
|
pub(crate) fn object_mmap_read_enabled() -> bool {
|
||||||
|
rustfs_utils::get_env_bool_with_aliases(
|
||||||
|
ENV_OBJECT_MMAP_READ_ENABLE,
|
||||||
|
&[ENV_OBJECT_ZERO_COPY_ENABLE],
|
||||||
|
DEFAULT_OBJECT_MMAP_READ_ENABLE,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct BitrotReaderSource {
|
struct BitrotReaderSource {
|
||||||
inline_data: Option<Bytes>,
|
inline_data: Option<Bytes>,
|
||||||
@@ -295,6 +304,32 @@ pub async fn create_bitrot_writer(
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn object_mmap_read_enabled_accepts_legacy_zero_copy_alias() {
|
||||||
|
temp_env::with_vars(
|
||||||
|
[
|
||||||
|
(ENV_OBJECT_MMAP_READ_ENABLE, None::<&str>),
|
||||||
|
(ENV_OBJECT_ZERO_COPY_ENABLE, Some("false")),
|
||||||
|
],
|
||||||
|
|| {
|
||||||
|
assert!(!object_mmap_read_enabled());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn object_mmap_read_enabled_prefers_canonical_env() {
|
||||||
|
temp_env::with_vars(
|
||||||
|
[
|
||||||
|
(ENV_OBJECT_MMAP_READ_ENABLE, Some("true")),
|
||||||
|
(ENV_OBJECT_ZERO_COPY_ENABLE, Some("false")),
|
||||||
|
],
|
||||||
|
|| {
|
||||||
|
assert!(object_mmap_read_enabled());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_create_bitrot_reader_with_inline_data() {
|
async fn test_create_bitrot_reader_with_inline_data() {
|
||||||
let test_data = b"hello world test data";
|
let test_data = b"hello world test data";
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::io_support::bitrot::object_mmap_read_enabled;
|
||||||
use crate::storage_api_contracts::namespace::NamespaceLocking as _;
|
use crate::storage_api_contracts::namespace::NamespaceLocking as _;
|
||||||
use rustfs_config::{DEFAULT_OBJECT_ZERO_COPY_ENABLE, ENV_OBJECT_ZERO_COPY_ENABLE};
|
|
||||||
|
|
||||||
const LOG_COMPONENT_ECSTORE: &str = "ecstore";
|
const LOG_COMPONENT_ECSTORE: &str = "ecstore";
|
||||||
const LOG_SUBSYSTEM_HEAL: &str = "heal";
|
const LOG_SUBSYSTEM_HEAL: &str = "heal";
|
||||||
@@ -360,10 +360,7 @@ impl SetDisks {
|
|||||||
|
|
||||||
for (part_index, part) in latest_meta.parts.iter().enumerate() {
|
for (part_index, part) in latest_meta.parts.iter().enumerate() {
|
||||||
let till_offset = erasure.shard_file_offset(0, part.size, part.size);
|
let till_offset = erasure.shard_file_offset(0, part.size, part.size);
|
||||||
// Read zero-copy configuration from environment variable
|
let use_mmap_read = object_mmap_read_enabled();
|
||||||
// Default: enabled (true) for performance
|
|
||||||
let use_mmap_read =
|
|
||||||
rustfs_utils::get_env_bool(ENV_OBJECT_ZERO_COPY_ENABLE, DEFAULT_OBJECT_ZERO_COPY_ENABLE);
|
|
||||||
|
|
||||||
let mut readers = Vec::with_capacity(latest_disks.len());
|
let mut readers = Vec::with_capacity(latest_disks.len());
|
||||||
let mut writers = Vec::with_capacity(out_dated_disks.len());
|
let mut writers = Vec::with_capacity(out_dated_disks.len());
|
||||||
|
|||||||
@@ -26,11 +26,10 @@ use crate::diagnostics::get::{
|
|||||||
record_get_object_pipeline_failure_for_path, record_get_stage_duration_if_enabled,
|
record_get_object_pipeline_failure_for_path, record_get_stage_duration_if_enabled,
|
||||||
};
|
};
|
||||||
use crate::erasure::coding::BitrotReader;
|
use crate::erasure::coding::BitrotReader;
|
||||||
use crate::io_support::bitrot::create_deferred_bitrot_reader;
|
use crate::io_support::bitrot::{create_deferred_bitrot_reader, object_mmap_read_enabled};
|
||||||
use crate::set_disk::shard_source::ShardReadCost;
|
use crate::set_disk::shard_source::ShardReadCost;
|
||||||
use futures::stream::{FuturesUnordered, StreamExt};
|
use futures::stream::{FuturesUnordered, StreamExt};
|
||||||
use metrics::counter;
|
use metrics::counter;
|
||||||
use rustfs_config::{DEFAULT_OBJECT_ZERO_COPY_ENABLE, ENV_OBJECT_ZERO_COPY_ENABLE};
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
future::Future,
|
future::Future,
|
||||||
@@ -2004,9 +2003,7 @@ impl SetDisks {
|
|||||||
};
|
};
|
||||||
let read_length = till_offset.saturating_sub(read_offset);
|
let read_length = till_offset.saturating_sub(read_offset);
|
||||||
|
|
||||||
// Read zero-copy configuration from environment variable
|
let use_mmap_read = object_mmap_read_enabled();
|
||||||
// Default: enabled (true) for performance
|
|
||||||
let use_mmap_read = rustfs_utils::get_env_bool(ENV_OBJECT_ZERO_COPY_ENABLE, DEFAULT_OBJECT_ZERO_COPY_ENABLE);
|
|
||||||
|
|
||||||
let reader_setup_stage_start = Instant::now();
|
let reader_setup_stage_start = Instant::now();
|
||||||
let read_costs = disks
|
let read_costs = disks
|
||||||
@@ -2387,7 +2384,7 @@ impl SetDisks {
|
|||||||
} else {
|
} else {
|
||||||
checksum_info.algorithm
|
checksum_info.algorithm
|
||||||
};
|
};
|
||||||
let use_mmap_read = rustfs_utils::get_env_bool(ENV_OBJECT_ZERO_COPY_ENABLE, DEFAULT_OBJECT_ZERO_COPY_ENABLE);
|
let use_mmap_read = object_mmap_read_enabled();
|
||||||
let till_offset = erasure.shard_file_offset(part_offset, part_length, part_size);
|
let till_offset = erasure.shard_file_offset(part_offset, part_length, part_size);
|
||||||
let read_offset = (part_offset / erasure.block_size) * erasure.shard_size();
|
let read_offset = (part_offset / erasure.block_size) * erasure.shard_size();
|
||||||
let read_length = till_offset.saturating_sub(read_offset);
|
let read_length = till_offset.saturating_sub(read_offset);
|
||||||
|
|||||||
Reference in New Issue
Block a user