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

add sapp_input_wait() to fix high cpu usage while idle #640

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

rofl0r
Copy link

@rofl0r rofl0r commented Mar 8, 2022

a sokol_app produces constant cpu load because it keeps repainting
the screen whether something has changed or not. we can fix this
easily by simply calling XNextEvent(), which blocks if there are no
pending events. this causes the app to idle until the user interacts
with the program.

a new function sapp_input_wait() was added to control this behaviour,
which causes the sokol app to block until the next input is received.
afterwards, the input_wait flag is cleared and the user has to set
it again if so desired.

this PR currently only addresses linux, and uses a "dirty" goto, which can be avoided by factoring out the XNextEvent block into a separate function.

a sokol_app produces constant cpu load because it keeps repainting
the screen whether something has changed or not. we can fix this
easily by simply calling XNextEvent(), which blocks if there are no
pending events. this causes the app to idle until the user interacts
with the program.

a new function sapp_input_wait() was added to control this behaviour,
which causes the sokol app to block until the next input is received.
afterwards, the input_wait flag is cleared and the user has to set
it again if so desired.
@Manuzor
Copy link
Contributor

Manuzor commented Mar 8, 2022

Related: #301

@rofl0r
Copy link
Author

rofl0r commented Mar 8, 2022

interesting. the suggested solution there (just skipping draw) doesn't fix the problem entirely - the app will still be executing stuff over and over while "polling" for input. i tried this approach before and it resulted in roughly 4% constant cpu usage even without redrawing and some usleep()s built in.
the only way to get 0% cpu usage is to actually block waiting for events.
related: libsdl-org/SDL#3976

@floooh
Copy link
Owner

floooh commented Mar 10, 2022

Hmm, I could've sworn I had written a detailed reply to this PR already, oh well... ;)

The problem with the PR is that it doesn't fit into the frame-callback-based sokol_app.h backends (any backend which is not Windows or X11 basically), but I think that's already discussed in the issue thread linked by @Manuzor

@rofl0r
Copy link
Author

rofl0r commented Mar 10, 2022

The problem with the PR is that it doesn't fit into the frame-callback-based sokol_app.h backends

maybe you're misunderstanding, the function added doesn't block itself, it merely sets a flag which causes the event/frame dispatch loop in the header to block upon next execution.

a typical use case would look like:

// timestamp in microsecs of last user activity
static uint64_t user_activity = -1ULL;

static uint64_t get_ts(void) {
    struct timespec nowtime;
    clock_gettime(CLOCK_REALTIME, &nowtime);
    return nowtime.tv_sec * 1000000ul + nowtime.tv_nsec/1000000ul;
}   
static int need_render(void) {
    if (user_activity == -1ULL || !sim_get_paused()) return 1;
    uint64_t ts = get_ts();
    return (ts - user_activity < 200);
}           
static void app_frame(void) {
    if (!need_render()) {
       sapp_input_wait();
       return;  
    }
    gfx_new_frame(sapp_widthf(), sapp_heightf());
    ui_frame();
 ....
}
static void app_input(const sapp_event* ev) {
    input_handle_event(ev);
    user_activity = get_ts();
}       
sapp_desc sokol_main(int argc, char* argv[]) {
    sargs_setup(&(sargs_desc){ .argc = argc, .argv = argv });
    return (sapp_desc){
        .init_cb = app_init,
        .frame_cb = app_frame,
        .event_cb = app_input,
...
}

(from https://github.com/rofl0r/visualz80/blob/nofips/src/main.c )

qwx9 added a commit to qwx9/strangepg that referenced this pull request Sep 13, 2024
this removes cpu load when idle, and reduces it when moving the
mouse around, etc.
the implementation reflects the landscape of the magical world
of linux; xlib is not thread-safe so we can't push a dummy event,
and select can mark an fd ready even though io would block.

based on ideas from floooh/sokol#640
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.

3 participants