So, i am/was investigating inconsistent frametimes/stuttering in my gameengine/renderloop and (after a bit of profiling) found out that the culprit lies within the polling of messages with SDL_PollEvent() (and SDL_PumpEvents())
OS is Windows 10 64bit
std::array< SDL_Event, 64> events;
Engine::Util::DurationTimer duration; //timestamp class
SDL_PumpEvents();
int total = 0;
{
int eventCount;
do
{
eventCount = SDL_PeepEvents(&events[0], events.size(), SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
for (int i = 0; i < eventCount; ++i)
{
}
total += eventCount;
} while (eventCount == events.size());
}
Engine::Debug::println("TIME [ms]: "+ std::to_string(duration.getMilliseconds()) + " / Messages:" + std::to_string(total));
The console/timestamp logging prints this:
TIME [ms]: 0 / Messages:1
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:1
TIME [ms]: 0 / Messages:15
TIME [ms]: 0 / Messages:0
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:1
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:1
TIME [ms]: 6 / Messages:8
TIME [ms]: 14 / Messages:16 ///<<<?????
TIME [ms]: 3 / Messages:11
TIME [ms]: 0 / Messages:9
TIME [ms]: 0 / Messages:1
TIME [ms]: 2 / Messages:9
TIME [ms]: 0 / Messages:10
TIME [ms]: 1 / Messages:17
TIME [ms]: 0 / Messages:1
TIME [ms]: 1 / Messages:16
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:2
TIME [ms]: 0 / Messages:15
TIME [ms]: 0 / Messages:1
TIME [ms]: 0 / Messages:15
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:1
TIME [ms]: 0 / Messages:15
TIME [ms]: 0 / Messages:1
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:1
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:1
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:16
TIME [ms]: 0 / Messages:1
TIME [ms]: 0 / Messages:16
you can see that sometimes you get lagspikes in the double digit range (even sometimes in triple digit territory) which you can imagine is not optimal if you try to make sure that your gameloop (both logic and rendering) fits within the 16ms window (per frame) for a minimum 60 fps experience.
At first i thought maybe that SDL was the culprit so i tried recreating the same thing in GLFW (took the example almost 1:1 of their website)
#include <GLFW/glfw3.h>
#include "DurationTimer.h"
#include <iostream>
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
// Retrieve times:
Engine::Util::DurationTimer t;
glfwPollEvents();
auto m = t.getMilliseconds();
if (m > 0) {
std::cout << m << std::endl;
}
}
glfwTerminate();
return 0;
}
The console output of the GLFW sample is this: (after simply moving my mouse around a bit and typing on a keyboard)
Times in milliseconds:
1
1
3
1
4
3
1
6
1
1
552 //<<<?????
2
1
1
1
1
1
1
1
1
1
3
1
1
1
1
13
1
1
1
1
2
1
1
1
1
1
1
1
1
1
2
12
4
1
1
1
1
1
1
2
8
1
2
1
1
1
6
1
1
1
1
2
1
1
1
1
2
2
1
1
1
1
22
1
1
1
1
13
2
4
2
2
3
1
1
1
2
27
2
1
13
6
1
1
2
23
3
2
1
1
1
1
8
7
1
1
1
9
1
1
1
1
1
1
1
1
1
7
10
2
2
2
1
1
1
8
1
1
1
1
12
1
1
1
1
1
1
1
1
9
1
1
1
1
1
1
1
1
9
6
1
1
1
1
16
1
28
3
1
1
9
1
1
1
1
1
1
14
2
1
So then i pulled the GLFW source code from github and did some digging.
Turns out that the spikes are being caused by “PeekMessageW” loop in the pollevents call: (win32_window.c file)
void _glfwPollEventsWin32(void)
{
auto time = timePoint();
MSG msg;
HWND handle;
_GLFWwindow* window;
// >>> THIS LOOP IS THE CULPRIT
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
// NOTE: While GLFW does not itself post WM_QUIT, other processes
// may post it to this one, for example Task Manager
// HACK: Treat WM_QUIT as a close on all windows
window = _glfw.windowListHead;
while (window)
{
_glfwInputWindowCloseRequest(window);
window = window->next;
}
}
else
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
...
Did some research on google and this issue seems to crop up sometimes but i was not able to find any kind of solution to this problem.
Has anyone any idea as to what is going on and or has anyone any suggestion as to how this could be worked around?