We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5380 - SDL_PollEvent/SDL_PumpEvents for keyboard events takes 4-5 ms. It's too slow
Summary: SDL_PollEvent/SDL_PumpEvents for keyboard events takes 4-5 ms. It's too slow
Status: ASSIGNED
Alias: None
Product: SDL
Classification: Unclassified
Component: events (show other bugs)
Version: don't know
Hardware: x86_64 Linux
: P2 normal
Assignee: Ryan C. Gordon
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-12-05 15:27 UTC by Roman Shuvalov
Modified: 2020-12-08 17:24 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Roman Shuvalov 2020-12-05 15:27:19 UTC
If a window has keyboard events pending, SDL_PumpEvents or first call of SDL_PollEvent takes around 4-5 milliseconds which is too slow. For example, each frame of 60 fps game lasts only 1000/60 = 16.7 ms, and wasting 4 ms just for resolving keyboard events is huge performance issue. 

Here is minimal program to reproduce a problem. Tested on Debian 10. 

Mouse moving above the window causes only around 300 microseconds (0.3 ms) delay which is absolutely fine. But hitting even a single key increases delay to 4000+ microseconds. Holding a key probably "stacks" delay times up to 20-30 ms which is insane.

-----------------------------------

#include <SDL2/SDL.h>
#include <time.h>

uint64_t get_time_us() {
    struct timespec tspec;
    clock_gettime(CLOCK_MONOTONIC_RAW, &tspec);
    uint64_t sec = tspec.tv_sec;
    uint64_t usec = tspec.tv_nsec / 1000;
    return sec*1000000L + usec;
}

int main (int argc, char ** args) {
    if( SDL_Init( SDL_INIT_EVERYTHING ) != 0 ) {
        return 1;
    }
    SDL_Window* window = SDL_CreateWindow("SDL2 Event Delay Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 300, SDL_WINDOW_SHOWN);
    if ( window == NULL ) {
        return 1;
    };
    int quit = 0;
    SDL_Event e;
    while ( !quit ) {
        uint64_t t[3];
        t[0] = get_time_us();
        SDL_PumpEvents(); // or it will be called on first SDL_PollEvent() and cause same delay
        t[1] = get_time_us();
        while( SDL_PollEvent( &e ) != 0 ) {
            if( e.type == SDL_QUIT ) {
                quit = 1;
            };
        };
        printf("SDL_PumpEvents() took %ld us (%ld ms)\n", t[1]-t[0], (t[1]-t[0])/1000 );
        SDL_Delay(100);
    };
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
};
Comment 1 Sam Lantinga 2020-12-05 20:37:27 UTC
I haven't seen that here. Can you build SDL with timing sprinkled inside the X11 keyboard code to see where the delay is happening?
Comment 2 Roman Shuvalov 2020-12-05 21:24:26 UTC
Found source of a problem, it's X11_DispatchEvent() call (/src/video/x11/SDL_x11events.c, line 1463). If argument is keyboard event, X11_DispatchEvent() takes 3-4 milliseconds.
Comment 3 Roman Shuvalov 2020-12-05 21:30:14 UTC
Whoops, it's implemented right there in same file, continuing searching inside X11_DispatchEvent()...
Comment 4 Roman Shuvalov 2020-12-05 22:30:24 UTC
Found:

dbus.connection_send_with_reply_and_block() causes delay.

It's called in src/core/linux/SDL_dbus.c:189, used if SDL_USE_IME and (probably) IBUS enabled. 

"Backtrace": 

X11_DispatchEvent - SDL_IME_ProcessKeyEvent - SDL_IBus_ProcessKeyEvent - SDL_DBus_CallMethodOnConnection - SDL_DBus_CallMethodInternal - dbus.connection_send_with_reply_and_block.
Comment 5 Sam Lantinga 2020-12-07 07:51:25 UTC
Hey Ryan, any idea what to do here?
Comment 6 Cameron Gutman 2020-12-08 17:24:18 UTC
If you don't actually need IME support in your program, you can call SDL_StopTextInput(). That will avoid calling out to the IME.