Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

erts: Make select message into a non-msg signal #157

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

garazdawi
Copy link
Owner

@garazdawi garazdawi commented Nov 27, 2024

Summary by Sourcery

Enhance the I/O event handling by converting select messages into non-message signals, improving the efficiency of the system. Update the internal documentation to include a detailed overview of the check I/O subsystem. Add new test cases to ensure the correct functionality of the scheduler polling mechanism for NIFs.

Enhancements:

  • Convert select message into a non-message signal to improve efficiency in handling I/O events.

Documentation:

  • Add a new internal documentation file 'CheckIO.md' that provides an overview of the check I/O subsystem, its components, and how it operates.

Tests:

  • Introduce new test cases in 'nif_SUITE.erl' to verify the functionality of the scheduler polling for NIFs, including tests for socket pairs and scheduler pollset operations.

@garazdawi garazdawi force-pushed the lukas/erts/enif_scheduler_pollset branch from bdf7979 to 59c4a7e Compare November 29, 2024 20:10
@garazdawi
Copy link
Owner Author

@sourcery-ai review

Copy link

sourcery-ai bot commented Dec 4, 2024

Reviewer's Guide by Sourcery

This pull request modifies the ERTS check I/O subsystem to optimize NIF select message handling by introducing a non-message signal mechanism and scheduler pollset optimizations. The changes aim to improve performance by reducing message copying and better handling of I/O events in scheduler pollsets.

Sequence diagram for NIF select message handling

sequenceDiagram
    participant NIF
    participant Scheduler
    participant Process
    participant IO

    NIF->>Scheduler: enif_select
    Scheduler->>IO: erts_io_handle_nif_select
    IO->>Scheduler: Return message
    Scheduler->>Process: Send signal
    Process->>Scheduler: Acknowledge signal
    Scheduler->>NIF: Signal processed
Loading

Class diagram for ERTS check I/O subsystem changes

classDiagram
    class ErtsNifSelectSignalData {
        Eterm message
        ErlNifEvent evt
    }

    class erts_nif_select_event {
        ErtsMessage* mp
        Eterm pid
    }

    class ErtsSchedulerData {
        ErtsSysFdType nif_select_fds[5]
    }

    class ErtsMessage {
        ErlHeapFragment hfrag
    }

    class ErlHeapFragment {
        size_t used_size
        size_t alloc_size
    }

    ErtsNifSelectSignalData --> erts_nif_select_event : used in
    erts_nif_select_event --> ErtsMessage : contains
    ErtsSchedulerData --> ErtsSysFdType : uses
    ErtsMessage --> ErlHeapFragment : contains
    ErlHeapFragment : used_size
    ErlHeapFragment : alloc_size
    ErtsSchedulerData : nif_select_fds[5]
Loading

File-Level Changes

Change Details Files
Introduce non-message signal mechanism for NIF select events
  • Add new ERTS_SIG_Q_OP_NIF_SELECT operation for handling NIF select events
  • Implement signal handling infrastructure for NIF select events
  • Add support for converting NIF select messages to signals
  • Modify message creation to support extra space for signal data
erts/emulator/beam/erl_proc_sig_queue.c
erts/emulator/beam/erl_proc_sig_queue.h
erts/emulator/beam/erl_nif.c
Optimize scheduler pollset handling for NIF select events
  • Add NIF select state tracking in scheduler data structure
  • Implement automatic migration of FDs to scheduler pollset after threshold
  • Add cleanup mechanism for NIF select handles in scheduler
  • Modify poll control logic to handle scheduler pollset operations
erts/emulator/sys/common/erl_check_io.c
erts/emulator/beam/erl_process.h
erts/emulator/beam/erl_process.c
Add comprehensive test coverage for scheduler pollset functionality
  • Add new select_scheduler test case
  • Implement test utilities for scheduler pollset verification
  • Add test cases for FD migration and cleanup
  • Add test cases for parallel FD handling
erts/emulator/test/nif_SUITE.erl
erts/emulator/test/nif_SUITE_data/nif_SUITE.c
Add documentation for Check I/O subsystem
  • Document polling mechanisms on Unix and Windows
  • Explain Check I/O subsystem architecture
  • Document NIF and Port interactions with Check I/O
  • Add implementation details for different polling methods
erts/emulator/internal_doc/CheckIO.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time. You can also use
    this command to specify where the summary should be inserted.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @garazdawi - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 3 issues found
  • 🟢 Security: all looks good
  • 🟡 Testing: 1 issue found
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +2817 to 2818
else if (n == 0 || errno == ECONNRESET) {
return atom_eof;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (testing): Test needed for ECONNRESET error condition in read_nif

A new test case should be added to verify that ECONNRESET is properly handled and returns atom_eof. This is an important edge case that should be explicitly tested.

and by NIFs through [`enif_select`](erl_nif.md#enif_select).

The main user of the check I/O subsystem is network communication though `m:gen_tcp`, `m:gen_udp`, `m:gen_sctp` and `m:socket` (On Unix, on Windows `m:socket` used its own internal check I/O implementation based on completion ports.),
but it is also used by various other parts such as when doing `os:cmd/1` or readying from the terminal.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): Fix typo: 'readying' should be 'reading'

At the writing of this document they are: [epoll] (Linux), [kqueue] (MacOS + *Bsd), [/dev/poll] (Solaris), [poll] and [select]. [epoll]+[kqueue]+[/dev/poll] are referred to as
"kernel polling" methods, as the information about which FDs are currently monitored
lives in the OS kernel, while [poll]+[select] are "user polling" methods as the
caller needs to supply all FDs of interest to the kernel everything `erts_poll_wait`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): Fix typo: 'everything' should be 'everytime'

caller needs to supply all FDs of interest to the kernel everything `erts_poll_wait`
is called.

By default all Unix'es use a "kernel polling" method, but has a fallback pollset that
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): Correct the plural form of 'Unix'

The plural form should be 'Unixes' rather than 'Unix'es'

if (op == ERTS_POLL_OP_DEL && (flags & ERTS_EV_FLAG_SCHEDULER)) {
erts_poll_control(get_scheduler_pollset(fd), fd, op, pe, wake_poller);
flags &= ~ERTS_EV_FLAG_IN_SCHEDULER;
if (!(flags & ERTS_EV_FLAG_SCHEDULER)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider extracting helper functions for scheduler polling and NIF select handling logic

The scheduler polling and NIF select handling logic adds significant complexity through nested flag manipulation. Consider extracting helper functions to improve readability:

static ERTS_INLINE void
update_scheduler_state(ErtsDrvEventState *state, ErtsPollEvents pe, ErtsPollOp op) 
{
    if (state->flags & ERTS_EV_FLAG_SCHEDULER) {
        if (!(state->flags & ERTS_EV_FLAG_IN_SCHEDULER))
            op = ERTS_POLL_OP_ADD;
        ErtsPollEvents res = erts_poll_control(get_scheduler_pollset(), 
            state->fd, op, pe & ERTS_POLL_EV_IN, NULL);
        if (op == ERTS_POLL_OP_ADD && res & ERTS_POLL_EV_IN)
            state->flags |= ERTS_EV_FLAG_IN_SCHEDULER;
        else if (op == ERTS_POLL_OP_DEL)
            state->flags &= ~ERTS_EV_FLAG_IN_SCHEDULER;
    }
}

This would simplify erts_io_control_wakeup() by encapsulating the scheduler state transitions. Similar helper functions could be extracted for NIF select handling to reduce the overall complexity while maintaining functionality.

@garazdawi garazdawi force-pushed the lukas/erts/enif_scheduler_pollset branch from 1693960 to e78e1de Compare December 6, 2024 14:42
@garazdawi garazdawi force-pushed the lukas/erts/enif_scheduler_pollset branch 2 times, most recently from 21b97d2 to b119aa9 Compare December 19, 2024 16:08
@garazdawi garazdawi force-pushed the lukas/erts/enif_scheduler_pollset branch 2 times, most recently from 389ba04 to 9cc5222 Compare January 8, 2025 12:34
@garazdawi garazdawi force-pushed the lukas/erts/enif_scheduler_pollset branch 3 times, most recently from 89fc8b6 to 0a3cb7f Compare January 13, 2025 13:46
@garazdawi garazdawi force-pushed the lukas/erts/enif_scheduler_pollset branch from 0a3cb7f to 7dfda88 Compare January 13, 2025 13:49
@garazdawi garazdawi force-pushed the lukas/erts/enif_scheduler_pollset branch from f40a3df to 6b2d431 Compare January 21, 2025 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant