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

Summary: SDL_PollEvent/SDL_PumpEvents for keyboard events takes 4-5 ms. It's too slow
Product: SDL Reporter: Roman Shuvalov <roman>
Component: eventsAssignee: Ryan C. Gordon <icculus>
Status: ASSIGNED --- QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 CC: cameron.gutman
Version: don't know   
Hardware: x86_64   
OS: Linux   

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.