[Edit 2: I've added further analysis and modified some of the explanations, esp. with respect to Refresh
. Still far from complete, I fear.]
First of all, I find if I set SetSystemOptions["DynamicUpdateInterval" -> 0.005]
, then I cannot perceive a difference in performance with or without the Animator
running. I see a very few hiccups in both scenarios, but I suspect the hiccups are due to system granularity (or too much beer).
On to some findings. I tested things by setting SetSystemOptions["DynamicUpdateInterval" -> 0.5]
, which allowed me better to perceive slow versus fast.
Hypothesis 1 - Animator
overrides SystemOptions["DynamicUpdateInterval"]
This is obvious. But how?
Edit. Manipulator
affects dynamic updating in a way similar to Animator
. If the slider is moved or animated, updating is rapid.
Hypothesis 2 (modified) - Dynamic@Refresh[..., UpdateInterval -> t]
can bypass "DynamicUpdateInterval"
Edit:
Originally I reported Refresh
sporadically overriding "DynamicUpdateInterval". After further playing with various permutations, Refresh
appears not to override "DynamicUpdateInterval", at least not consistently. If I copy and paste two or more copies the output of
Dynamic@Refresh[Clock[], UpdateInterval -> 0.01]
I usually get rapidly updating clocks that switch between slow and rapid updating over long periods.
Hypothesis 3 - Clocks of the form Clock[{0, Infinity, dt}]
behave differently than those of the form Clock[{0, Infinity}]
or Clock[]
Compare the output of the original with the following modification, with the Animator
running:
pacman[xposFun_, angleFun_] := {Yellow,
Disk[{Dynamic@xposFun[Clock[{0, Infinity, 0.01}]], 0`}, 1`,
Dynamic[{Pi/6 Abs@Sin[2 Pi Clock[{0, Infinity, 0.01}]],
angleFun[Clock[{0, Infinity, 0.01}]]} /. {val_, ang_} :> {val+ang, 2 Pi-val}]]}
In both versions, the position is updated smoothly. But in the original code the mouth is updated every 0.5 sec., and in the above modification the mouth is updated smoothly.
Two or more clocks of the form Clock[{0, Infinity, 0.01}]
randomly alternate between slow and rapid updating, while the other forms, such as Clock[]
, remain slow (unless wrapped in Refresh
as in Hyp. 2 above):
Dynamic@Clock[]
Dynamic@Clock[{0, Infinity, 0.01}]
Dynamic@Clock[{0, Infinity, 0.01}]
Another difference is that Clock[{0, Infinity, 0.01}]
calls Floor
and Mod
, while the other forms of Clock
do not.
Hypothesis 4 - The system updates dynamic outputs ahead of schedule when convenient
I vaguely mean that for some reason updating the position of pacman
is linked with updating the Animator
, perhaps because of some connection to Clock
.
@Rojo noticed that in the second case below, the animator does not cause Clock[{0, Infinity, 0.01}]
to be updated continuously.
Module[{v}, Animator@Dynamic@v]
DynamicModule[{v}, Animator@Dynamic@v]
The distinction seems to be that if v
is a kernel variable, then clocks are updated continuously, but not if v
is a front end variable. However, this principle is not generally true, because both of the following cause the clock to be updated.
Module[{v = 0}, Dynamic@v++]
DynamicModule[{v = 0}, Dynamic@v++]
Neither of these expressions are limited by "DynamicUpdateInterval"
, even if the kernel is fed a long computation simultaneously, which seems at odds with the documentation
By default, dynamic outputs triggered by changes in variable values are updated no faster than twenty times per second (this rate can be changed with the SystemOption
"DynamicUpdateInterval"
).
Hypothesis 5 - Animator
is implemented in the front end
Following up the remark by @Rojo, I noticed the following. If you monitor CPU activity of the front end and kernel, one can see by comparing the preceding two animators that the second seems to be run entirely or almost entirely in the front end (paste several outputs to magnify the effect). In the Module
case, kernel usage increases as more copies of the animator are pasted, whereas in the the DynamicModule
case, kernel usage does not change. All forms of Clock
, on the other hand, seem to use a small amount of kernel time.
Concluding conjectures
First, Animator
is owned by the front end and bypasses "DynamicUpdateInterval"
, whose purpose is to limit interruptions of the kernel. Animator
is represented by AnimatorBox
in the output cell and it appears to run wholely in the front end; so it appears to be a basic element of the Dynamic
system. For example, it is the basis for the various *Animate
commands.
Second, Mathematica treats Clock[{t1, t2, dt}]
in special way, triggering updates that are normally blocked. It is clear that it happens, but it is not so clear exactly how and under what conditions it happens. One question is whether the system is designed to do this. It seems unlikely, since the behavior seems sporadic or random. Another question is whether Animator
is designed to cause clocks to update in the observed way and why.
Third, there is some connection between calls to the kernel and updates bypassing "DynamicUpdateInterval"
. This happens when the Animator
variable is a kernel variables, sometimes with Clock
, and even with Dynamic@v++
even when v
is a DynamicModule
variable perhaps because Increment
is computed in the kernel. This connection is still mysterious.
Unresolved
After playing around for a while, with extra dynamic clocks added and deleted for testing, pacman
would sometimes freeze (dropped down dead drunk, I suspect). The Animator
would run, but pacman
would stay at the start. The clocks would stop, too. Further evidence that Animator
gets special treatment. Quitting the kernel and reevaluating fixed this. Also, Mathematica crashed on me a couple of times.
ListPlay
. What isUpsample
-- is a V9 function? $\endgroup$Disk[{Dynamic[bla], 0}, 1, Dynamic[bla]]
inpacman
definition toDynamic[Disk[{bla, 0}, 4, bla]]
seems to make it smoother on my MMA 9. Maybe when multipleDynamic
s are used, they compete against each other? Or MMA must choose oneDynamic
to update for any one frame? $\endgroup$