Internally, setFrameLimit uses sf::sleep anyway.
void Window::display()
{
// Display the backbuffer on screen
if (setActive())
m_context->display();
// Limit the framerate if needed
if (m_frameTimeLimit != Time::Zero)
{
sleep(m_frameTimeLimit - m_clock.getElapsedTime());
m_clock.restart();
}
}
The problem with either is sf::sleep uses the operating system sleep, which can be inaccurate. For example on windows the sleep will be at least what you specify, but may also be longer. So you may not get a consistent framerate. Vsync is more reliable since the drivers are waiting for a fixed rate hardware event.
A basic busy loop will use more cpu, but will be more reliable without vsync.
You could try a combo, check how long is remaining until the next frame, then sleep for a small amount (like 1ms) if the remaining is greater than maybe 2ms. Otherwise busy loop. So a sleep that's too short or long probably won't affect it.