> You see this on scroll ups, because they are slightly slower than
> scroll downs, and the difference is enough to trigger this with
> higher probability when you go up.

Closely related, I define these commands (byte compiled):

  (defvar my-leap-scroll-size 16)
  (define-key evil-normal-state-map ";" nil)
  (define-key evil-motion-state-map ";"
    (lambda ()
      (interactive)
      (scroll-up my-leap-scroll-size)
      (evil-next-line my-leap-scroll-size)))
  (define-key evil-normal-state-map "'" nil)
  (define-key evil-motion-state-map "'"
    (lambda ()
      (interactive)
      (scroll-down my-leap-scroll-size)
      (evil-previous-line my-leap-scroll-size)))

In the same C++ buffer as before, when I hold to repeat the above
command that scrolls up*, the display doesn't update at all until I
release the key to stop the repeat. As you indicated it may, the
scroll down can keep up in this case. I turned font locking off and
the scroll up redisplay keeps up. I also tried this in a Python buffer
with font lock on and these commands keep up much better. Is it that
the C/C++ font locking is more complex? Has C/C++ major mode been
performance tuned for this use case? Maybe I can experiment with my
local configuration to temporarily disable font locking while I'm
scrolling up fast -- seeing non font locked code fly by would be
better than nothing at all.

* Assume I use "up" and "down" in the majority usage, opposite of
  Emacs terminology