From past experimentation (not all of which I remember) here are several things that contribute to the time it takes to display graphics, including:
converting the Graphics expression to boxes (in the kernel)
compressing the result if it's very large (if you examine large graphics cells, you'll notice that they're compressed)
transferring the (possibly compressed) box expression to the Front End through MathLink
rendering the graphics
I played with these a little bit in the past, trying to figure out what contributes the most to the timing. Unfortunately I don't remember all the details (and I won't have time to do all the tests again now), but I do know that: 1. converting to boxes might take longer than the rendering itself in some cases 2. compression may take measurable time too.
If you want to measure the full time needed to display a Graphics, then I recommend something like
s = AbsoluteTime[];
ballGrid[30]
AbsoluteTime[] - s
In order or this to give correct results, each command must be in a separate cell.
This gives me 4.9 seconds, which is about the same time I measure with my watch.
The following should be a good approximation to the total display time too, but it'll usually take a little longer to evaluate (5.1 seconds here):
ExportString[ballGrid[30], "BMP"]; // AbsoluteTiming
This will measure box generation only (1.2 seconds):
AbsoluteTiming[ToBoxes[ballGrid[30]];]
You can add compression on top of that (1.8 seconds), AbsoluteTiming[Compress@ToBoxes[ballGrid[30]];], but I'm not sure that the same compression method implemented in Compress is used when sending the data to the FE.
Your method (AbsoluteTiming[Print@ballGrid[30]]) should include at least box generation and compression, and possibly MathLink transfer too (just a guess, I'm not sure about this last one). It gives 2.0 seconds on my machine, but I can measure 5 seconds with a watch before I actually see the graphics.
I hope this answer will help you in digging deeper into what happens exactly when graphics are displayed and how to time the process correctly ... I simply wanted to point out that doing this is not quite as straightforward as it might seem at first.