mz_rocksdb_types/
config.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10// This module is mostly boilerplate, with all relevant
11// documentation on `RocksDBTuningParameters`.
12#![allow(missing_docs)]
13
14//! This module offers a protobuf implementation (to be used
15//! with LaunchDarkly) `RocksDBTuningParameters` that can be used
16//! to tune a RocksDB instance. The supported options are carefully
17//! considered to be a minimal set required to tune RocksDB to perform
18//! well for the `UPSERT` usecase. This usecase is slightly odd:
19//! - Very high write rate (1:1 with reads)
20//! - No durability requirements
21//! - Minimal space amplification
22//! - Relatively relaxed read and write latency requirements
23//!     - (note that `UPSERT` RocksDB instances are NOT in the
24//!     critical path for any sort of query.
25//!
26//! The defaults (so, the values resulting from derserializing `{}`
27//! into a `RocksDBTuningParameters`) should be reasonable defaults.
28//!
29//! The documentation on each field in `RocksDBTuningParameters` has more
30//! information
31//!
32//! Note that the following documents are required reading to deeply understand
33//! this module:
34//! - <https://github.com/EighteenZi/rocksdb_wiki/blob/master/RocksDB-Tuning-Guide.md>
35//! - <https://github.com/EighteenZi/rocksdb_wiki/blob/master/Compression.md>
36//! - <https://github.com/facebook/rocksdb/wiki/Setup-Options-and-Basic-Tuning>
37//! - <https://www.eecg.toronto.edu/~stumm/Papers/Dong-CIDR-16.pdf>
38//! - <http://smalldatum.blogspot.com/2015/11/read-write-space-amplification-pick-2_23.html>
39
40use std::fmt::Debug;
41use std::str::FromStr;
42use std::time::Duration;
43
44use mz_ore::cast::CastFrom;
45use mz_proto::{IntoRustIfSome, RustType, TryFromProtoError};
46
47use proptest_derive::Arbitrary;
48use serde::{Deserialize, Serialize};
49use uncased::UncasedStr;
50
51include!(concat!(env!("OUT_DIR"), "/mz_rocksdb_types.config.rs"));
52
53/// A set of parameters to tune RocksDB. This struct is plain-old-data, and is
54/// used to update `RocksDBConfig`, which contains some dynamic value for some
55/// parameters.
56#[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Arbitrary)]
57pub struct RocksDBTuningParameters {
58    /// RocksDB has 2 primary styles of compaction:
59    /// - The default, usually referred to as "level" compaction
60    /// - "universal"
61    ///
62    /// Universal is simpler and for some workloads could be
63    /// better. Also, you can directly configure its space-amplification ratio
64    /// (using `universal_compaction_target_ratio`). However, its unclear
65    /// if the `UPSERT` workload is a good workload for universal compaction,
66    /// and its also might be the case that universal compaction uses significantly
67    /// more space temporarily while performing compaction.
68    ///
69    /// For these reasons, the default is `CompactionStyle::Level`.
70    pub compaction_style: CompactionStyle,
71    /// The `RocksDB` api offers a single configuration method that sets some
72    /// reasonable defaults for heavy-write workloads, either
73    /// <https://docs.rs/rocksdb/latest/rocksdb/struct.Options.html#method.optimize_level_style_compaction>
74    /// or
75    /// <https://docs.rs/rocksdb/latest/rocksdb/struct.Options.html#method.optimize_universal_style_compaction>
76    /// depending on `compaction_style`. We ALSO enable this configuration, which is tuned
77    /// by the size of the memtable (basically the in-memory buffer used to avoid IO). The default
78    /// here is ~512MB, which is the default from here: <https://github.com/facebook/rocksdb/blob/main/include/rocksdb/options.h#L102>,
79    /// and about twice the global RocksDB default.
80    pub optimize_compaction_memtable_budget: usize,
81
82    /// This option, when enabled, dynamically tunes
83    /// the size of the various LSM levels to put a bound on space-amplification.
84    /// With the default level-ratio of `10`, this means space-amplification is
85    /// O(1.11 * the size of data). Note this is big-O notation, and the actual
86    /// amplification factor depends on the workload.
87    ///
88    /// See <https://www.eecg.toronto.edu/~stumm/Papers/Dong-CIDR-16.pdf> for more details.
89    ///
90    /// This option defaults to true, as its basically free saved-space, and only applies to
91    /// `CompactionStyle::Level`.
92    pub level_compaction_dynamic_level_bytes: bool,
93
94    /// The additional space-amplification used with universal compaction.
95    /// Only applies to `CompactionStyle::Universal`.
96    ///
97    /// See `compaction_style` for more information.
98    pub universal_compaction_target_ratio: i32,
99
100    /// By default, RocksDB uses only 1 thread to perform compaction and other background tasks.
101    ///
102    /// The default here is the number of cores, as mentioned by
103    /// <https://docs.rs/rocksdb/latest/rocksdb/struct.Options.html#method.increase_parallelism>.
104    ///
105    /// Note that this option is shared across all RocksDB instances that share a `rocksdb::Env`.
106    pub parallelism: Option<i32>,
107
108    /// The most important way to reduce space amplification in RocksDB is compression.
109    ///
110    /// In RocksDB, data on disk is stored in an LSM tree. Because the higher layers (which are
111    /// smaller) will need to be read during reads that aren't cached, we want a relatively
112    /// lightweight compression scheme, choosing `Lz4` as the default, which is considered almost
113    /// always better than `Snappy`.
114    ///
115    /// The meat of the data is stored in the largest, bottom layer, which can be configured
116    /// (using `bottommost_compression_type`) to use a more expensive compression scheme to save
117    /// more space. The default is `Zstd`, which many think has the best compression ratio. Note
118    /// that tuning the bottommost layer separately only makes sense when you have free cpu,
119    /// which we have in the case of the `UPSERT` usecase.
120    pub compression_type: CompressionType,
121
122    /// See `compression_type` for more information.
123    pub bottommost_compression_type: CompressionType,
124
125    /// The size of the `multi_get` and `multi_put` batches sent to RocksDB. The default is 1024.
126    pub batch_size: usize,
127
128    /// The maximum duration for the retries when performing rocksdb actions in case of retry-able errors.
129    pub retry_max_duration: Duration,
130
131    /// The interval to dump stats in `LOG`.
132    pub stats_log_interval_seconds: u32,
133
134    /// The interval to persist stats into rocksdb.
135    pub stats_persist_interval_seconds: u32,
136
137    /// The optional block cache size in MiB for optimizing rocksdb for point lookups.
138    /// If not provided there will be no optimization.
139    /// <https://github.com/facebook/rocksdb/blob/main/include/rocksdb/options.h#L82-L85>
140    pub point_lookup_block_cache_size_mb: Option<u32>,
141
142    /// The number of times by which unused buffers will be reduced.
143    /// For example, if the number is 2, the buffers will be reduced to being twice as small,
144    /// i.e. halved.
145    /// Shrinking will be disabled if value is 0;
146    pub shrink_buffers_by_ratio: usize,
147
148    /// Optional write buffer manager bytes. This needs to be set to enable write buffer manager
149    /// across all rocksdb instances
150    pub write_buffer_manager_memory_bytes: Option<usize>,
151    /// Optional write buffer manager memory limit as a percentage of cluster limit
152    pub write_buffer_manager_memory_fraction: Option<f64>,
153    /// Config to enable stalls with write buffer manager
154    pub write_buffer_manager_allow_stall: bool,
155}
156
157impl Default for RocksDBTuningParameters {
158    fn default() -> Self {
159        Self {
160            compaction_style: defaults::DEFAULT_COMPACTION_STYLE,
161            optimize_compaction_memtable_budget:
162                defaults::DEFAULT_OPTIMIZE_COMPACTION_MEMTABLE_BUDGET,
163            level_compaction_dynamic_level_bytes:
164                defaults::DEFAULT_LEVEL_COMPACTION_DYNAMIC_LEVEL_BYTES,
165            universal_compaction_target_ratio: defaults::DEFAULT_UNIVERSAL_COMPACTION_RATIO,
166            parallelism: defaults::DEFAULT_PARALLELISM,
167            compression_type: defaults::DEFAULT_COMPRESSION_TYPE,
168            bottommost_compression_type: defaults::DEFAULT_BOTTOMMOST_COMPRESSION_TYPE,
169            batch_size: defaults::DEFAULT_BATCH_SIZE,
170            retry_max_duration: defaults::DEFAULT_RETRY_DURATION,
171            stats_log_interval_seconds: defaults::DEFAULT_STATS_LOG_INTERVAL_S,
172            stats_persist_interval_seconds: defaults::DEFAULT_STATS_PERSIST_INTERVAL_S,
173            point_lookup_block_cache_size_mb: None,
174            shrink_buffers_by_ratio: defaults::DEFAULT_SHRINK_BUFFERS_BY_RATIO,
175            write_buffer_manager_memory_bytes: None,
176            write_buffer_manager_memory_fraction: None,
177            write_buffer_manager_allow_stall: false,
178        }
179    }
180}
181
182impl RocksDBTuningParameters {
183    /// Build a `RocksDBTuningParameters` from strings and values from LD parameters.
184    pub fn from_parameters(
185        compaction_style: CompactionStyle,
186        optimize_compaction_memtable_budget: usize,
187        level_compaction_dynamic_level_bytes: bool,
188        universal_compaction_target_ratio: i32,
189        parallelism: Option<i32>,
190        compression_type: CompressionType,
191        bottommost_compression_type: CompressionType,
192        batch_size: usize,
193        retry_max_duration: Duration,
194        stats_log_interval_seconds: u32,
195        stats_persist_interval_seconds: u32,
196        point_lookup_block_cache_size_mb: Option<u32>,
197        shrink_buffers_by_ratio: usize,
198        write_buffer_manager_memory_bytes: Option<usize>,
199        write_buffer_manager_memory_fraction: Option<f64>,
200        write_buffer_manager_allow_stall: bool,
201    ) -> Result<Self, anyhow::Error> {
202        Ok(Self {
203            compaction_style,
204            optimize_compaction_memtable_budget,
205            level_compaction_dynamic_level_bytes,
206            universal_compaction_target_ratio: if universal_compaction_target_ratio > 100 {
207                universal_compaction_target_ratio
208            } else {
209                return Err(anyhow::anyhow!(
210                    "universal_compaction_target_ratio ({}) must be > 100",
211                    universal_compaction_target_ratio
212                ));
213            },
214            parallelism: match parallelism {
215                Some(parallelism) => {
216                    if parallelism < 1 {
217                        return Err(anyhow::anyhow!(
218                            "parallelism({}) must be > 1, or not specified",
219                            universal_compaction_target_ratio
220                        ));
221                    }
222                    Some(parallelism)
223                }
224                None => None,
225            },
226            compression_type,
227            bottommost_compression_type,
228            batch_size,
229            retry_max_duration,
230            stats_log_interval_seconds,
231            stats_persist_interval_seconds,
232            point_lookup_block_cache_size_mb,
233            shrink_buffers_by_ratio,
234            write_buffer_manager_memory_bytes,
235            write_buffer_manager_memory_fraction,
236            write_buffer_manager_allow_stall,
237        })
238    }
239}
240
241/// The 2 primary compaction styles in RocksDB`. See `RocksDBTuningParameters::compaction_style`
242/// for more information.
243#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug, Arbitrary)]
244pub enum CompactionStyle {
245    Level,
246    Universal,
247}
248
249impl FromStr for CompactionStyle {
250    type Err = anyhow::Error;
251
252    fn from_str(s: &str) -> Result<Self, Self::Err> {
253        let s = UncasedStr::new(s);
254        if s == "level" {
255            Ok(Self::Level)
256        } else if s == "universal" {
257            Ok(Self::Universal)
258        } else {
259            Err(anyhow::anyhow!("{} is not a supported compaction style", s))
260        }
261    }
262}
263
264impl std::fmt::Display for CompactionStyle {
265    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
266        match self {
267            CompactionStyle::Level => write!(f, "level"),
268            CompactionStyle::Universal => write!(f, "universal"),
269        }
270    }
271}
272
273/// Mz-supported compression types in RocksDB`. See `RocksDBTuningParameters::compression_type`
274/// for more information.
275#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug, Arbitrary)]
276pub enum CompressionType {
277    Zstd,
278    Snappy,
279    Lz4,
280    None,
281}
282
283impl FromStr for CompressionType {
284    type Err = anyhow::Error;
285
286    fn from_str(s: &str) -> Result<Self, Self::Err> {
287        let s = UncasedStr::new(s);
288        if s == "zstd" {
289            Ok(Self::Zstd)
290        } else if s == "snappy" {
291            Ok(Self::Snappy)
292        } else if s == "lz4" {
293            Ok(Self::Lz4)
294        } else if s == "none" {
295            Ok(Self::None)
296        } else {
297            Err(anyhow::anyhow!("{} is not a supported compression type", s))
298        }
299    }
300}
301
302impl std::fmt::Display for CompressionType {
303    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
304        match self {
305            CompressionType::Zstd => write!(f, "zstd"),
306            CompressionType::Snappy => write!(f, "snappy"),
307            CompressionType::Lz4 => write!(f, "lz4"),
308            CompressionType::None => write!(f, "none"),
309        }
310    }
311}
312
313impl RustType<ProtoRocksDbTuningParameters> for RocksDBTuningParameters {
314    fn into_proto(&self) -> ProtoRocksDbTuningParameters {
315        use proto_rocks_db_tuning_parameters::{
316            ProtoCompactionStyle, ProtoCompressionType, proto_compaction_style,
317            proto_compression_type,
318        };
319
320        fn compression_into_proto(compression_type: &CompressionType) -> ProtoCompressionType {
321            ProtoCompressionType {
322                kind: Some(match compression_type {
323                    CompressionType::Zstd => proto_compression_type::Kind::Zstd(()),
324                    CompressionType::Snappy => proto_compression_type::Kind::Snappy(()),
325                    CompressionType::Lz4 => proto_compression_type::Kind::Lz4(()),
326                    CompressionType::None => proto_compression_type::Kind::None(()),
327                }),
328            }
329        }
330        ProtoRocksDbTuningParameters {
331            compaction_style: Some(ProtoCompactionStyle {
332                kind: Some(match self.compaction_style {
333                    CompactionStyle::Level => proto_compaction_style::Kind::Level(()),
334                    CompactionStyle::Universal => proto_compaction_style::Kind::Universal(()),
335                }),
336            }),
337            optimize_compaction_memtable_budget: u64::cast_from(
338                self.optimize_compaction_memtable_budget,
339            ),
340            level_compaction_dynamic_level_bytes: self.level_compaction_dynamic_level_bytes,
341            universal_compaction_target_ratio: self.universal_compaction_target_ratio,
342            parallelism: self.parallelism,
343            compression_type: Some(compression_into_proto(&self.compression_type)),
344            bottommost_compression_type: Some(compression_into_proto(
345                &self.bottommost_compression_type,
346            )),
347            batch_size: u64::cast_from(self.batch_size),
348            retry_max_duration: Some(self.retry_max_duration.into_proto()),
349            stats_log_interval_seconds: self.stats_log_interval_seconds,
350            stats_persist_interval_seconds: self.stats_persist_interval_seconds,
351            point_lookup_block_cache_size_mb: self.point_lookup_block_cache_size_mb,
352            shrink_buffers_by_ratio: u64::cast_from(self.shrink_buffers_by_ratio),
353            write_buffer_manager_memory_bytes: self
354                .write_buffer_manager_memory_bytes
355                .map(u64::cast_from),
356            write_buffer_manager_memory_fraction: self.write_buffer_manager_memory_fraction,
357            write_buffer_manager_allow_stall: self.write_buffer_manager_allow_stall,
358        }
359    }
360
361    fn from_proto(proto: ProtoRocksDbTuningParameters) -> Result<Self, TryFromProtoError> {
362        use proto_rocks_db_tuning_parameters::{
363            ProtoCompactionStyle, ProtoCompressionType, proto_compaction_style,
364            proto_compression_type,
365        };
366
367        fn compression_from_proto(
368            compression_type: Option<ProtoCompressionType>,
369        ) -> Result<CompressionType, TryFromProtoError> {
370            match compression_type {
371                Some(ProtoCompressionType {
372                    kind: Some(proto_compression_type::Kind::Zstd(())),
373                }) => Ok(CompressionType::Zstd),
374                Some(ProtoCompressionType {
375                    kind: Some(proto_compression_type::Kind::Snappy(())),
376                }) => Ok(CompressionType::Snappy),
377                Some(ProtoCompressionType {
378                    kind: Some(proto_compression_type::Kind::Lz4(())),
379                }) => Ok(CompressionType::Lz4),
380                Some(ProtoCompressionType {
381                    kind: Some(proto_compression_type::Kind::None(())),
382                }) => Ok(CompressionType::None),
383                Some(ProtoCompressionType { kind: None }) => Err(TryFromProtoError::MissingField(
384                    "ProtoRocksDbTuningParameters::compression_type::kind".into(),
385                )),
386                None => Err(TryFromProtoError::MissingField(
387                    "ProtoRocksDbTuningParameters::compression_type".into(),
388                )),
389            }
390        }
391        Ok(Self {
392            compaction_style: match proto.compaction_style {
393                Some(ProtoCompactionStyle {
394                    kind: Some(proto_compaction_style::Kind::Level(())),
395                }) => CompactionStyle::Level,
396                Some(ProtoCompactionStyle {
397                    kind: Some(proto_compaction_style::Kind::Universal(())),
398                }) => CompactionStyle::Universal,
399                Some(ProtoCompactionStyle { kind: None }) => {
400                    return Err(TryFromProtoError::MissingField(
401                        "ProtoRocksDbTuningParameters::compaction_style::kind".into(),
402                    ));
403                }
404                None => {
405                    return Err(TryFromProtoError::MissingField(
406                        "ProtoRocksDbTuningParameters::compaction_style".into(),
407                    ));
408                }
409            },
410            optimize_compaction_memtable_budget: usize::cast_from(
411                proto.optimize_compaction_memtable_budget,
412            ),
413            level_compaction_dynamic_level_bytes: proto.level_compaction_dynamic_level_bytes,
414            universal_compaction_target_ratio: proto.universal_compaction_target_ratio,
415            parallelism: proto.parallelism,
416            compression_type: compression_from_proto(proto.compression_type)?,
417            bottommost_compression_type: compression_from_proto(proto.bottommost_compression_type)?,
418            batch_size: usize::cast_from(proto.batch_size),
419            retry_max_duration: proto
420                .retry_max_duration
421                .into_rust_if_some("ProtoRocksDbTuningParameters::retry_max_duration")?,
422            stats_log_interval_seconds: proto.stats_log_interval_seconds,
423            stats_persist_interval_seconds: proto.stats_persist_interval_seconds,
424            point_lookup_block_cache_size_mb: proto.point_lookup_block_cache_size_mb,
425            shrink_buffers_by_ratio: usize::cast_from(proto.shrink_buffers_by_ratio),
426            write_buffer_manager_memory_bytes: proto
427                .write_buffer_manager_memory_bytes
428                .map(usize::cast_from),
429            write_buffer_manager_memory_fraction: proto.write_buffer_manager_memory_fraction,
430            write_buffer_manager_allow_stall: proto.write_buffer_manager_allow_stall,
431        })
432    }
433}
434
435#[derive(Clone, Debug)]
436pub struct RocksDbWriteBufferManagerConfig {
437    /// Optional write buffer manager bytes. This needs to be set to enable write buffer manager
438    /// across all rocksdb instances
439    pub write_buffer_manager_memory_bytes: Option<usize>,
440    /// Optional write buffer manager memory limit as a percentage of cluster limit
441    pub write_buffer_manager_memory_fraction: Option<f64>,
442    /// Config to enable stalls with write buffer manager
443    pub write_buffer_manager_allow_stall: bool,
444    /// Cluster memory limit used to calculate write buffer manager limit
445    /// if `write_buffer_manager_memory_fraction` is provided
446    pub cluster_memory_limit: Option<usize>,
447}
448
449/// The following are defaults (and default strings for LD parameters)
450/// for `RocksDBTuningParameters`.
451pub mod defaults {
452    use std::time::Duration;
453
454    use super::*;
455
456    pub const DEFAULT_COMPACTION_STYLE: CompactionStyle = CompactionStyle::Level;
457
458    /// From here: <https://github.com/facebook/rocksdb/blob/main/include/rocksdb/options.h#L102>
459    /// And then setting it to 1/3rd from our testing in production
460    pub const DEFAULT_OPTIMIZE_COMPACTION_MEMTABLE_BUDGET: usize = 512 * 1024 * 1024 / 3;
461
462    pub const DEFAULT_LEVEL_COMPACTION_DYNAMIC_LEVEL_BYTES: bool = true;
463
464    /// From here: <https://docs.rs/rocksdb/latest/rocksdb/struct.UniversalCompactOptions.html>
465    pub const DEFAULT_UNIVERSAL_COMPACTION_RATIO: i32 = 200;
466
467    pub const DEFAULT_PARALLELISM: Option<i32> = None;
468
469    pub const DEFAULT_COMPRESSION_TYPE: CompressionType = CompressionType::Lz4;
470
471    pub const DEFAULT_BOTTOMMOST_COMPRESSION_TYPE: CompressionType = CompressionType::Lz4;
472
473    /// A reasonable default batch size for gets and puts in RocksDB. Based
474    /// on advice here: <https://github.com/facebook/rocksdb/wiki/RocksDB-FAQ>.
475    /// Based on our testing we are using 20 times that.
476    pub const DEFAULT_BATCH_SIZE: usize = 20 * 1024;
477
478    /// The default max duration for retrying the retry-able errors in rocksdb.
479    pub const DEFAULT_RETRY_DURATION: Duration = Duration::from_secs(1);
480
481    /// The default for spilling from memory to rocksdb is 2 write buffers. Some initial tests
482    /// found that 2 write buffers were the minimum memory usage of rocksdb when processing small
483    /// amounts of data.
484    ///
485    /// The calculation is based on the `MEMTABLE_BUDGET`, and is inverting the logic here:
486    /// <https://github.com/facebook/rocksdb/blob/bc0db33483d5e79b281ba3137ebf286b2d1efd8d/options/options.cc#L632-L637>
487    pub const DEFAULT_AUTO_SPILL_MEMORY_THRESHOLD: usize =
488        DEFAULT_OPTIMIZE_COMPACTION_MEMTABLE_BUDGET / 4 * 2;
489
490    /// Default is 10 minutes, from <https://docs.rs/rocksdb/latest/rocksdb/struct.Options.html#method.set_stats_dump_period_sec>
491    pub const DEFAULT_STATS_LOG_INTERVAL_S: u32 = 600;
492
493    /// Default is 10 minutes, from <https://docs.rs/rocksdb/latest/rocksdb/struct.Options.html#method.set_stats_persist_period_sec>
494    pub const DEFAULT_STATS_PERSIST_INTERVAL_S: u32 = 600;
495
496    /// Default is 0, i.e. shrinking will be disabled
497    pub const DEFAULT_SHRINK_BUFFERS_BY_RATIO: usize = 0;
498
499    /// Not allowing stalls for write buffer manager. Only applicable if write buffer manager is enabled by other flags.
500    pub const DEFAULT_WRITE_BUFFER_MANAGER_ALLOW_STALL: bool = false;
501}
502
503#[cfg(test)]
504mod tests {
505    use mz_ore::assert_ok;
506    use mz_proto::protobuf_roundtrip;
507    use proptest::prelude::*;
508
509    use super::*;
510
511    #[mz_ore::test]
512    fn defaults_equality() {
513        let r = RocksDBTuningParameters::from_parameters(
514            defaults::DEFAULT_COMPACTION_STYLE,
515            defaults::DEFAULT_OPTIMIZE_COMPACTION_MEMTABLE_BUDGET,
516            defaults::DEFAULT_LEVEL_COMPACTION_DYNAMIC_LEVEL_BYTES,
517            defaults::DEFAULT_UNIVERSAL_COMPACTION_RATIO,
518            defaults::DEFAULT_PARALLELISM,
519            defaults::DEFAULT_COMPRESSION_TYPE,
520            defaults::DEFAULT_BOTTOMMOST_COMPRESSION_TYPE,
521            defaults::DEFAULT_BATCH_SIZE,
522            defaults::DEFAULT_RETRY_DURATION,
523            defaults::DEFAULT_STATS_LOG_INTERVAL_S,
524            defaults::DEFAULT_STATS_PERSIST_INTERVAL_S,
525            None,
526            defaults::DEFAULT_SHRINK_BUFFERS_BY_RATIO,
527            None,
528            None,
529            defaults::DEFAULT_WRITE_BUFFER_MANAGER_ALLOW_STALL,
530        )
531        .unwrap();
532
533        assert_eq!(r, RocksDBTuningParameters::default());
534    }
535
536    #[mz_ore::test]
537    #[cfg_attr(miri, ignore)] // too slow
538    fn rocksdb_tuning_roundtrip() {
539        proptest!(|(expect in any::<RocksDBTuningParameters>())| {
540            let actual = protobuf_roundtrip::<_, ProtoRocksDbTuningParameters>(&expect);
541            assert_ok!(actual);
542            assert_eq!(actual.unwrap(), expect);
543
544        });
545    }
546}