Home / Class/ AutoScalingEventExecutorChooser Class — netty Architecture

AutoScalingEventExecutorChooser Class — netty Architecture

Architecture documentation for the AutoScalingEventExecutorChooser class in AutoScalingEventExecutorChooserFactory.java from the netty codebase.

Entity Profile

Dependency Diagram

graph TD
  bb4797cf_7318_6bbb_4c87_1f53888dd980["AutoScalingEventExecutorChooser"]
  409fa4eb_44da_665a_7f39_b9b5f929789e["AutoScalingEventExecutorChooserFactory.java"]
  bb4797cf_7318_6bbb_4c87_1f53888dd980 -->|defined in| 409fa4eb_44da_665a_7f39_b9b5f929789e
  c4b40701_4326_dfe6_f06e_30628fb77b04["AutoScalingEventExecutorChooser()"]
  bb4797cf_7318_6bbb_4c87_1f53888dd980 -->|method| c4b40701_4326_dfe6_f06e_30628fb77b04
  178c3324_6aa0_719a_b4ab_65660a5ce63c["EventExecutor()"]
  bb4797cf_7318_6bbb_4c87_1f53888dd980 -->|method| 178c3324_6aa0_719a_b4ab_65660a5ce63c
  a4304eb6_db6c_91df_93c2_2b3acb53fc85["tryScaleUpBy()"]
  bb4797cf_7318_6bbb_4c87_1f53888dd980 -->|method| a4304eb6_db6c_91df_93c2_2b3acb53fc85
  07fd7ee2_1ff7_6bde_d1c3_009b67256717["activeExecutorCount()"]
  bb4797cf_7318_6bbb_4c87_1f53888dd980 -->|method| 07fd7ee2_1ff7_6bde_d1c3_009b67256717
  70c7dffa_2836_7cea_ddab_508d8f03649b["executorUtilizations()"]
  bb4797cf_7318_6bbb_4c87_1f53888dd980 -->|method| 70c7dffa_2836_7cea_ddab_508d8f03649b

Relationship Graph

Source Code

common/src/main/java/io/netty/util/concurrent/AutoScalingEventExecutorChooserFactory.java lines 155–420

    private final class AutoScalingEventExecutorChooser implements ObservableEventExecutorChooser {
        private final EventExecutor[] executors;
        private final EventExecutorChooser allExecutorsChooser;
        private final AtomicReference<AutoScalingState> state;
        private final List<AutoScalingUtilizationMetric> utilizationMetrics;

        AutoScalingEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
            List<AutoScalingUtilizationMetric> metrics = new ArrayList<>(executors.length);
            for (EventExecutor executor : executors) {
                metrics.add(new AutoScalingUtilizationMetric(executor));
            }
            utilizationMetrics = Collections.unmodifiableList(metrics);
            allExecutorsChooser = DefaultEventExecutorChooserFactory.INSTANCE.newChooser(executors);

            AutoScalingState initialState = new AutoScalingState(maxChildren, 0L, executors);
            state = new AtomicReference<>(initialState);

            ScheduledFuture<?> utilizationMonitoringTask = GlobalEventExecutor.INSTANCE.scheduleAtFixedRate(
                    new UtilizationMonitor(), utilizationCheckPeriodNanos, utilizationCheckPeriodNanos,
                    TimeUnit.NANOSECONDS);

            if (executors.length > 0) {
                executors[0].terminationFuture().addListener(future -> utilizationMonitoringTask.cancel(false));
            }
        }

        /**
         * This method is only responsible for picking from the active executors list.
         * The monitor handles all scaling decisions.
         */
        @Override
        public EventExecutor next() {
            // Get a snapshot of the current state.
            AutoScalingState currentState = this.state.get();

            if (currentState.activeExecutors.length == 0) {
                // This is only reachable if minChildren is 0 and the monitor has just suspended the last active thread.
                // To prevent an error and ensure the group can recover, we wake one up and use the
                // chooser that contains all executors as a safe temporary choice.
                tryScaleUpBy(1);
                return allExecutorsChooser.next();
            }
            return currentState.activeExecutorsChooser.next();
        }

        /**
         * Tries to increase the active thread count by waking up suspended executors.
         * This method is thread-safe and updates the state atomically.
         *
         * @param amount    The desired number of threads to add to the active count.
         */
        private void tryScaleUpBy(int amount) {
            if (amount <= 0) {
                return;
            }

            for (;;) {
                AutoScalingState oldState = state.get();
                if (oldState.activeChildrenCount >= maxChildren) {
                    return;
                }

                int canAdd = Math.min(amount, maxChildren - oldState.activeChildrenCount);
                List<EventExecutor> wokenUp = new ArrayList<>(canAdd);
                final long startIndex = oldState.nextWakeUpIndex;

                for (int i = 0; i < executors.length; i++) {
                    EventExecutor child = executors[(int) Math.abs((startIndex + i) % executors.length)];

                    if (wokenUp.size() >= canAdd) {
                        break; // We have woken up all the threads we reserved.
                    }
                    if (child instanceof SingleThreadEventExecutor) {
                        SingleThreadEventExecutor stee = (SingleThreadEventExecutor) child;
                        if (stee.isSuspended()) {
                            stee.execute(NO_OOP_TASK);
                            wokenUp.add(stee);
                        }
                    }
                }

Frequently Asked Questions

What is the AutoScalingEventExecutorChooser class?
AutoScalingEventExecutorChooser is a class in the netty codebase, defined in common/src/main/java/io/netty/util/concurrent/AutoScalingEventExecutorChooserFactory.java.
Where is AutoScalingEventExecutorChooser defined?
AutoScalingEventExecutorChooser is defined in common/src/main/java/io/netty/util/concurrent/AutoScalingEventExecutorChooserFactory.java at line 155.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free