You are “dropping frames”. This happens when code takes too long to execute within one refresh period. The screen will update regardless of what our code does, so it will just continue to show what it was last given until the next win.flip() command gives it new content. So if you want to show a stimulus for one frame (16.66 ms duration) but a frame drop occurs, what happens looks like this:
0 1 2
If you are using frame-counting code, you don’t know that anything has gone wrong. You draw frame 0, and draw frame 1. It’s just that frame 1 actually occurs one period later than intended because the win.flip() happened too late to influence the scheduled screen update. So your 16.7 ms stimulus was actually shown for 33 ms.
With a one-frame duration stimulus, there isn’t much you can do about this except make the measurements you are currently doing, so you know the extent of any problem. With the 500 ms stimulus, however, you have the option of going back to time-based code. That way, you can correct for any dropped frames by ensuring that the stimulus is displayed for a total of 500 ms regardless of how many win.flip’s were issued (assuming the dropped frame doesn’t occur on the very last frame).
Why do dropped frames occur? In your case, the PsychoPy code seems fine, because normally you get things done in time (it is certainly possible for your own code to drop frames, for example if you are updating a stimulus by reading in a large image file from disk, which can easily take more than one refresh interval). But in your case, it is likely some other process that is intruding on your time. You need to have as “clean” a computer and operating system as possible. Disconnect from the net, strip out virus checkers and disable automatic updates during experiments, don’t install any software (e.g. Microsoft Office) that you don’t need to run the experiment. Many pieces of software create processes that run in the background and compete for CPU resources with PsychoPy.
This issue isn’t unique to PsychoPy: think of how many times when you’ve been using a computer that it seemed briefly to be unresponsive or to stutter when moving the mouse pointer. When running an experiment and doing careful testing like you are, you see the evidence of this at the millisecond level. From a software point of view, remove as many possible competing programs as possible and from a hardware point of view, use a computer with a fast CPU, decent amount of RAM, ideally solid state drives, and a good graphics card. That means that you can get more done within a single screen refresh period: your own code is currently quick enough, but this would help reduce the impact of other programs running at the same time.