Skip to main content

reth_node_core/args/
jit.rs

1//! clap [Args](clap::Args) for revmc JIT configuration.
2
3use clap::Args;
4use humantime::parse_duration;
5use std::time::Duration;
6
7/// Parameters for JIT compilation of EVM bytecode via revmc.
8#[derive(Debug, Clone, Args, PartialEq, Eq)]
9#[command(next_help_heading = "JIT")]
10pub struct JitArgs {
11    /// Enable JIT compilation of EVM bytecode.
12    #[arg(id = "jit.enabled", long = "jit", default_value_t = false, help_heading = "JIT")]
13    pub enabled: bool,
14
15    /// Number of observed misses before a bytecode is promoted to JIT compilation.
16    #[arg(long = "jit.hot-threshold", default_value_t = Self::DEFAULT_HOT_THRESHOLD, help_heading = "JIT")]
17    pub hot_threshold: usize,
18
19    /// Number of JIT compilation worker threads.
20    #[arg(long = "jit.worker-count", help_heading = "JIT")]
21    pub worker_count: Option<usize>,
22
23    /// Capacity of the lookup-observed event channel.
24    /// Events are silently dropped when the channel is full.
25    #[arg(long = "jit.channel-capacity", default_value_t = Self::DEFAULT_CHANNEL_CAPACITY, help_heading = "JIT")]
26    pub channel_capacity: usize,
27
28    /// Maximum number of pending JIT compilation jobs.
29    #[arg(long = "jit.max-pending-jobs", default_value_t = Self::DEFAULT_MAX_PENDING_JOBS, help_heading = "JIT")]
30    pub max_pending_jobs: usize,
31
32    /// Maximum bytecode length eligible for JIT compilation.
33    /// Contracts with bytecode larger than this are never promoted to JIT.
34    /// 0 means no limit.
35    #[arg(long = "jit.max-bytecode-len", default_value_t = Self::DEFAULT_MAX_BYTECODE_LEN, help_heading = "JIT")]
36    pub max_bytecode_len: usize,
37
38    /// Maximum total resident compiled code size in bytes.
39    /// When exceeded, the backend evicts least-recently-used entries.
40    /// 0 means no limit.
41    #[arg(long = "jit.code-cache-bytes", default_value_t = Self::DEFAULT_CODE_CACHE_BYTES, help_heading = "JIT")]
42    pub code_cache_bytes: usize,
43
44    /// Duration after which a compiled program with no lookup hits is evicted.
45    #[arg(
46        long = "jit.idle-evict-duration",
47        default_value = humantime::format_duration(Self::DEFAULT_IDLE_EVICT_DURATION).to_string(),
48        help_heading = "JIT",
49        value_parser = parse_duration,
50    )]
51    pub idle_evict_duration: Duration,
52
53    /// Enable compiler debug dumps.
54    ///
55    /// IR, assembly, and bytecode are written to `<datadir>/jit/<spec_id>/<code_hash>/` for each
56    /// compiled contract.
57    /// Note that this is not ever cleaned up, and has a non negligible performance overhead.
58    #[arg(long = "jit.debug", default_value_t = false, help_heading = "JIT")]
59    pub debug: bool,
60
61    /// Blocking mode: synchronously JIT-compile every contract on first encounter.
62    /// Intended for debugging only.
63    #[doc(hidden)]
64    #[arg(long = "jit.blocking", default_value_t = false, help_heading = "JIT", hide = true)]
65    pub blocking: bool,
66}
67
68impl JitArgs {
69    const DEFAULT_HOT_THRESHOLD: usize = 8;
70    const DEFAULT_CHANNEL_CAPACITY: usize = 4096;
71    const DEFAULT_MAX_PENDING_JOBS: usize = 2048;
72    const DEFAULT_MAX_BYTECODE_LEN: usize = 0;
73    const DEFAULT_CODE_CACHE_BYTES: usize = 1024 * 1024 * 1024; // 1 GiB
74    const DEFAULT_IDLE_EVICT_DURATION: Duration = Duration::from_hours(1);
75}
76
77impl Default for JitArgs {
78    fn default() -> Self {
79        Self {
80            enabled: false,
81            hot_threshold: Self::DEFAULT_HOT_THRESHOLD,
82            worker_count: None,
83            channel_capacity: Self::DEFAULT_CHANNEL_CAPACITY,
84            max_pending_jobs: Self::DEFAULT_MAX_PENDING_JOBS,
85            max_bytecode_len: Self::DEFAULT_MAX_BYTECODE_LEN,
86            code_cache_bytes: Self::DEFAULT_CODE_CACHE_BYTES,
87            idle_evict_duration: Self::DEFAULT_IDLE_EVICT_DURATION,
88            debug: false,
89            blocking: false,
90        }
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97    use clap::Parser;
98
99    /// A helper type to parse Args more easily
100    #[derive(Parser)]
101    struct CommandParser<T: Args> {
102        #[command(flatten)]
103        args: T,
104    }
105
106    #[test]
107    fn jit_args_default_sanity_test() {
108        let args = CommandParser::<JitArgs>::parse_from(["reth"]).args;
109        assert_eq!(args, JitArgs::default());
110    }
111}