How long does a command take to process?

dgc188

New Member
Is there any form of definitive table (or even thoughts) as to how long a processor takes - at normal speed ("setfreq m4") - or with a higher (i.e. "setfreq m16") speed to process a command (any command)? And is the length of time-per-command processor type dependant (i.e. 18M2 vs 40X2)?

I have a short window of time in which to check a number of sensors (the sensors will only be active for around half a second at a time) during a relatively long routine and should such a (thought-)table be available I might have an appreciation of how many commands in the main routine I can process before I need to make that call to the check-sensor subroutine.

I've done a search for this subject on processor timings and came across two (very) old thread addresses - but as they date back to the days of 2005 and the rev-ed forum site, they appear to not be no longer available - gives a 404 error:
http://www.rev-ed.co.uk/picaxe/forum/Topic.asp?topic_id=2767
http://www.rev-ed.co.uk/picaxe/forum/Topic.asp?topic_id=2521

My thoughts may even have to come down to having a "slave" processor to check the sensors while the "main" processor runs the main routine - I still need to think this idea through. Still pondering on the best way forward with this.

Many thanks
Dave
 

AllyCat

Senior Member
Hi Dave,

The nearest to a definitive document is in this thread, started in 2011. Some of the values are now rather "optimistic" because the later PICaxe's have actually slowed down slightly (for a given clock speed), for example because they now need to address larger areas of internal memory. At post #12 I have described a method for a "real" (M2) PICaxe (not the Simulator) to measure its own instruction execution times (i.e. with no external hardware), with a few example timings.

I also keep my own spreadsheet of some of the primary execution times, but there are too many "variations" for it to be of general use. For any specific instructions it may be worth asking here, as there are quite a few "gotchas" if speed (or program size) is a particular issue.

Cheers, Alan.
 
Last edited:

dgc188

New Member
The nearest to a definitive document is in this thread, started in 2011.
Thanks Alan,

But I'm not sure if the "this thread" was supposed to be a link to the thread in question, if it was it didn't work for me (did nothing).

I appreciate there appears to be no hard and fast table of timings but a few guidelines would be useful for my needs - even if they are a bit arbitrary given the larger memory capacities that need addressing as you mention.

Would appreciate a resend of the link to the thread mentioned.

Again, thanks
Dave
 

dgc188

New Member
Thanks Alan

That link works fine (software, eh! {a rolling of the eyes! o_O }). All I need now is a few hours to digest the Rev.D pdf file (seems to be the latest iteration of the info) as well as the comments posted on the thread. Looks to be interesting and most useful.

I'm not sure where the "post #121" you mention comes into it all - only 24 posts on that forum.

Again, thanks for the link and the info therein.
Dave
 

AllyCat

Senior Member
Hi,

Ah, another "problem" with the forum software (and proportional fonts). What I actually wrote is "... #12 <space> I have....". But there's no point in writing <space> <space>, etc. for clarity, because the software takes any duplicate spaces out again. :(

I've only just looked at the downloaded document again and had forgotten how much detail about the "tokens" was included, which is largely irrelevant now (as the modern PICaxes have much more program memory space). The nitty gritty is in the table of section 5, and mainly for the 18M2 (I don't know about the X2 data as I have only used M2s).

Cheers, Alan.
 

lbenson

Senior Member
Far from definitive, but 2,000-4,000 statements per second has been given as a rough approximation of how many (non-blocking) instructions a picaxe running at 4mHz will perform.
 

AllyCat

Senior Member
Hi,

IMHO that's a little optimistic, at least for an M2 (at 4MHz). The fastest instructions (High and Low outputs and simple Maths/Logic operations, etc.) take about 400 - 600 us (around 2,000 per second) whilst basic Conditional and Jump (IF... GOTO, etc.) take 800 - 1200 us (1,,000 per second). Multiply and Divide a little longer (note it always works internally to 16-bit Word resolution), but then there are some instructions that can take many milliseconds. :(

However, even the humblest 08M2 can run 8 times faster (at 32 MHz), with the core still needing only around 3 mA. So 10 mW operation is quite possible, which leaves some of the "Alternatives" standing.

Cheers, Alan.
 

hippy

Technical Support
Staff member
My rule of thumb has always been 125us per token at 4MHz, or 250us per simple "HIGH B.0" command, being two tokens. "b0 = 12 + 34" would be 5 tokens, about 600us. It's not accurate but there is no way to be accurate.
 

dgc188

New Member
Many thanks to one and all - very much appreciated for the info and comments.

So, from what I can gather, there is "no" definitive list of command timings as there are so many variables in terms of the processor type (& F/W revision), type of variable being used, obviously its speed setting and where within a program listing each command sits - among other things such as, maybe, temperature.

But, if nothing else, I now do have a (very) rough guideline as to timings and (possibly) how many commands I can have in a given routine to fit into a given time period. As long as I take the worse case figures above, I should be ok.

As with most things, it will probably be a "suck-it-and-see" to see if the program as a whole does as I want it to within that time frame.

Again, to all respondents, a huge thank you for the comments made here and also to those that wrote and contributed to the (final) Rev.D of the Program size, Possible Optimisations and Command Timing pdf.

Dave
(It's all about the continual process of learning - remembering it is something else entirely!)
 

hippy

Technical Support
Staff member
As with most things, it will probably be a "suck-it-and-see" to see if the program as a whole does as I want it to within that time frame.
That's generally the case but you can test particularly time critical parts of the code by placing that in a subroutine, running that a thousand times or so, with a piezo beep or character output every time that completes. Then a stopwatch timing and divide by how ever many loops will give a good ballpark of how long something takes. For example -
Code:
#Picaxe 28X2
#Terminal 9600
#No_Data
#No_Table

Pause 2000
Do
  SerTxd( "X" )
  For w9 = 1 To 10000
    Gosub Test
  Next
Loop

Test:
  Return
Takes about 16 seconds. Add a "w0 = w1 + 1" into the test routine and that then takes about 21.5 seconds. So the time for a "w0 = w1 + 1" is (21.5-16)/10000 which is about 550us.

That "w0 = w1 + 1" is five tokens, and from my ballpark token figure earlier would be 5 x 125us, 625us, so there's a reasonable correlation, within 15% or so.

The above technique is what has usually been used to create the timings we have. When done with a scope or logic analyser, one can issue a HIGH before and a LOW after the call and just measure the time of the high pulse for a single call.

It is a laborious task for determining all timings and variances, but can be useful to see how long a particular chunk of code takes.
 

AllyCat

Senior Member
Hi,

Sometime I must revisit the program that I devised in #12 of the thread above, perhaps to make it more "User Friendly". It is a very powerful method for measuring typical execution times, using just an appropriate PICaxe connected to a computer running a Program Editor, with no additional hardware requirements, not even a LED, let alone a 'scope, Logic Analyser or stopwatch. Of course it can't accurately measure Interrupt Latency or commands which switch the clock frequency (expected or otherwise) but these are relatively unusual. Intrinsically it can make multiple, documented measurements as quickly as you can edit the test harness (program instructions) and download it to the target.

Also, just a couple of comments about the "tokens". Firstly, you can avoid some unexpected "surprises" by simply using the Syntax Checker in the Program Editor and noting the change in Program size. That may discourage you from using commands such as SWAP (and even WORD) in time-critical code. Secondly, I presume that RETURN is just one token, but it takes more than 2ms in M2 devices at 4 MHz (3ms with the matching CALL/GOSUB), which rather discourages the use of any subroutines in time-critical program sections. :(

Cheers, Alan.
 

hippy

Technical Support
Staff member
That may discourage you from using commands such as SWAP (and even WORD) in time-critical code.
That's true. Some of the commands are actually internal macros which generate multiple PICAXE comands under the hood, so lead to more memory being used than they would appear to. The WORD modifier, BINTOASCII, SWAP, PWMOUT and PWMDUTY commands are cases in point.

In most programs the code size, amount of code executed and the time taken, doesn't much matter, the benefits of being able to use a short on-liner of code outweighs the costs of what that generates.

For time critical sections it may be better to avoid those or code specifically what one needs.

Secondly, I presume that RETURN is just one token, but it takes more than 2ms in M2 devices at 4 MHz (3ms with the matching CALL/GOSUB), which rather discourages the use of any subroutines in time-critical program sections.
Yes, RETURN is a single token command, but the way the stack works on a PICAXE means there's an overhead in determining where any RETURN returns to.

Again, it's not a problem in most code, but can be an issue where speed is required.

If one wants to avoid having a GOSUB/RETURN in some code but do not want to put a big chunk of code where that would be, a #MACRO can be useful to keep that code separate ...
Code:
#Macro AddToTotal
  total = total + w0
  items = items + 1
#EndMacro

For w0 = 5 To 10
  AddToTotal              ; Would have likely been a Gosub AddToTotal
Next
average = total / items
SerTxd( "Total=", #Total, TAB, "Average=", #average, CR, LF )
 
Top