A Few Questions about Clocks

Hi all -

Currently, I’m in the midst of a project where I’d like to store GUI values with information about how long they have been set. I could potentially do this with either the AppClock or the SystemClock - though the System clock purports to be more accurate.

I’m thinking about having a continual control bus with a constant feed of time values that I can pull from, as necessary.

Are there major CPU disadvantages to this approach? Are there better ways of accomplishing the same goal? How much accuracy would be sacrificed?
Thanks for the advice.

Maybe you want to use Main.elapsedTime?

(
var startTime=0, elapsedTime=0;
w = Window.new("The Four Noble Truths");

b = Button(w, Rect(20, 20, 340, 30))
.states_([
	["On", Color.black, Color.red],
	["Time", Color.white, Color.black]
])
.action_({ arg butt;
	if(butt.value==1){
		startTime = Main.elapsedTime
		
	}{
		elapsedTime = Main.elapsedTime-startTime;
		elapsedTime.postln;
	}
});
w.front;
)

Sam

1 Like

The current logical time is SystemClock.seconds. I would recommend this.

AppClock.seconds may or may not be subject to drift. I wouldn’t try to read an accurate time value from it.

Main.elapsedTime is the current physical time, which includes the time taken to execute instructions so far. (There is a difference between logical and physical time. I have a feeling that many recommendations for Main.elapsedTime are not deliberately choosing to measure physical time, but rather choosing the method name that sounds more like it has to do with timing. I generally prefer to measure logical time with SystemClock.)

Would it be better perhaps to have the button send a trigger to a synth, and let the synth continually measure time (using Sweep)? “Constant feed” sounds like a signal. If you’re sending time measurements from the language, either you’ll have to send them many times per second (CPU drain) or less often, but they’ll be inaccurate.

hjh

1 Like

You can do the tests yourself to match your specific needs.

Make the clock a variable and then change it as necessary.

There are several ways to schedule a thread with clock selection.

(

this.k_

(
	Clock.allSubclasses.printAll.first // AppClock
)

.r_ 

{
	Thread.instVarNames.do
	{
		|x| 
	
		{
			postln
			(
				x -> thisThread.perform(x)
			)
		}
		try:
		{
			// eliminate inaccessible methods
		}
	}
} 

.r // Routine

// .p // Prout 

)

// r fork: k 

// k play: r

// k.sched(3, r)
1 Like

Just to clarify, you would use Sweep as the clock here - it wouldn’t be a scenario using Sweep to poll SystemClock.

Also, re: logical vs. physical - if I understand correctly, the distinction here is that Main.elapsedTime will have slightly imperfect measurements due to latency, whereas measuring from SystemClock (or using Sweep?) would be an “objective” relationship to universal time.

// language way

s.boot;

(
var start, routine;

~timeBus = Bus.control(s, 1);

b = Button(nil, Rect(800, 200, 100, 30))
.front
.states_([["go"]])
.action_({
	start = SystemClock.seconds;
	if(routine.isNil) {

		// does the language really have to do all this work?
		
		routine = Routine {
			loop {
				~timeBus.set(SystemClock.seconds - start);
				0.01.wait;
			}
		}
	}
});

b.onClose = { routine.stop };
)


~timeBus.free;


// server way

(
var start, timeSynth;

~timeBus = Bus.control(s, 1);

// meanwhile, the server is designed for
// continuously updating signals...
timeSynth = { |t_trig = 0, rate = 1|
	Sweep.kr(t_trig, rate)
}.play(outbus: ~timeBus);

b = Button(nil, Rect(800, 200, 100, 30))
.front
.states_([["go"]])
.action_({
	timeSynth.set(\t_trig, 1);
});

b.onClose = { timeSynth.free };
)

Not exactly “latency” – rather, the physical time it takes to execute instructions.

Here’s an illustration.

(
{
	var f = { [SystemClock.seconds, Main.elapsedTime] };
	(SystemClock.seconds.roundUp - SystemClock.seconds).wait;
	f.value.debug("first");
	0.0.wait;
	f.value.debug("after waiting 0");
	1.0.wait;
	f.value.debug("after waiting 1");
}.fork(SystemClock);
)

first: [ 481.0, 481.000256393 ]
after waiting 0: [ 481.0, 481.000492859 ]
after waiting 1: [ 482.0, 482.000247757 ]

hjh