Line data Source code
1 : /* The nohz-full stage checks that Firedancer tile CPUs run in full 2 : dynticks ("nohz_full") mode. 3 : 4 : On a nohz_full CPU running exactly one runnable task, the kernel 5 : stops the periodic scheduler tick, and (since kernel 4.17) offloads 6 : even the residual 1Hz tick to a housekeeping CPU via the global 7 : workqueue (see the kworkers stage, which keeps that workqueue off 8 : tile CPUs). This removes ~CONFIG_HZ (typically 250/s) timer 9 : interrupts per second per tile CPU, each costing ~2-5us plus cache 10 : and branch predictor pollution. See also the rcu-nocbs stage: 11 : nohz_full CPUs need rcu_nocbs to reach full silence. 12 : 13 : nohz_full is a boot-time kernel parameter: it cannot be configured 14 : at runtime, so this stage cannot have an init step. It is a 15 : check-only stage (like hyperthreads) that WARNS with the exact 16 : suggested parameter rather than failing, since Firedancer runs 17 : correctly (with slightly degraded jitter) without it. 18 : 19 : The kernel exposes the active set in 20 : /sys/devices/system/cpu/nohz_full (cpulist; may contain "(null)" or 21 : be absent when CONFIG_NO_HZ_FULL is off). 22 : 23 : A CPU listed in nohz_full but running multiple tasks just keeps its 24 : tick, so listing extra CPUs is harmless. Hence the suggested 25 : parameter covers ALL fixed tile CPUs. One CPU must remain outside 26 : the set for timekeeping; since the topology never covers every host 27 : CPU (other stages enforce housekeeping CPUs exist), the tile set is 28 : always safe to suggest. */ 29 : 30 : #include "configure.h" 31 : #include "fd_cpu_isolation.h" 32 : 33 : #define NAME "nohz-full" 34 : 35 : #define NOHZ_FULL_PATH "/sys/devices/system/cpu/nohz_full" 36 : 37 : static configure_result_t 38 : check( config_t const * config, 39 0 : int check_type ) { 40 0 : if( !( check_type==FD_CONFIGURE_CHECK_TYPE_CHECK || 41 0 : check_type==FD_CONFIGURE_CHECK_TYPE_RUN ) ) CONFIGURE_OK(); 42 : 43 : /* Jitter tuning only matters for production validators against a 44 : live cluster, don't nag in development. */ 45 0 : if( FD_LIKELY( !config->is_live_cluster || config->is_dev ) ) CONFIGURE_OK(); 46 : 47 0 : FD_CPUSET_DECL( tile_cpus ); 48 0 : fd_cpu_isolation_tile_cpus( tile_cpus, &config->topo ); 49 0 : if( FD_UNLIKELY( !fd_cpuset_cnt( tile_cpus ) ) ) CONFIGURE_OK(); 50 : 51 0 : char suggested[ FD_CPU_ISOLATION_LIST_MAX ]; 52 0 : fd_cpu_isolation_format_list( suggested, sizeof(suggested), tile_cpus ); 53 : 54 0 : FD_CPUSET_DECL( nohz ); 55 0 : if( FD_UNLIKELY( !fd_cpu_isolation_read_list( NOHZ_FULL_PATH, nohz ) ) ) { 56 0 : FD_LOG_WARNING(( "kernel has no nohz_full support %s(missing " NOHZ_FULL_PATH ")%s. Firedancer tiles will be " 57 0 : "interrupted by periodic timer ticks. For lower jitter, use a kernel with CONFIG_NO_HZ_FULL " 58 0 : "and boot with %snohz_full=%s%s.", 59 0 : fd_log_style_dim(), fd_log_style_normal(), 60 0 : fd_log_style_bold(), suggested, fd_log_style_normal() )); 61 0 : CONFIGURE_OK(); 62 0 : } 63 : 64 0 : FD_CPUSET_DECL( missing ); 65 0 : fd_cpuset_subtract( missing, tile_cpus, nohz ); 66 0 : if( FD_UNLIKELY( !fd_cpuset_is_null( missing ) ) ) { 67 0 : char missing_str[ FD_CPU_ISOLATION_LIST_MAX ]; 68 0 : fd_cpu_isolation_format_list( missing_str, sizeof(missing_str), missing ); 69 0 : FD_LOG_WARNING(( "tile cpus %s are not in the kernel nohz_full= set and will be interrupted by " 70 0 : "periodic timer ticks. For lower jitter, boot with %snohz_full=%s%s.", 71 0 : missing_str, fd_log_style_bold(), suggested, fd_log_style_normal() )); 72 0 : } 73 : 74 0 : CONFIGURE_OK(); 75 0 : } 76 : 77 : configure_stage_t fd_cfg_stage_nohz_full = { 78 : .name = NAME, 79 : .always_recreate = 0, 80 : .enabled = NULL, 81 : .init_perm = NULL, 82 : .fini_perm = NULL, 83 : .init = NULL, 84 : .fini = NULL, 85 : .check = check, 86 : }; 87 : 88 : #undef NAME 89 : #undef NOHZ_FULL_PATH