Understanding the results of the "Stack Length" library object...
bill190
Posts: 769
Ok, I want to get this stack length business down if I can...
For a test I'm running TestSquareWaveMethod.spin from the PE kit / Methods and Cogs Lab folder.
TestSquareWaveMethod.spin assigns a stack space of...
long swStack[noparse][[/noparse]120]
...for 3 new cogs it runs as follows...
swCog[noparse][[/noparse]0] := cognew(SquareWave(5, clkfreq/20, clkfreq/10), @swStack)
swCog[noparse][[/noparse]1] := cognew(SquareWave(6, clkfreq/100, clkfreq/5), @swStack[noparse][[/noparse]40])
swCog[noparse][[/noparse]2] := cognew(SquareWave(9, clkfreq/2000, clkfreq/500), @swStack[noparse][[/noparse]80])
So 40 longs of stack space for each new cog being run and 120 longs total stack space. OK...
Then I added the "Stack Length" object to measure how much stack space was being used. I added the following at the top of the file/object TestSquareWaveMethod.spin after the end of the CON block (where it sets the clock speed as is also needed for Stack Length)...
OBJ
· Stk·· :······ "Stack Length"····· 'Include Stack Length Object
PUB TestStack
· Stk.Init(@swStack, 120)········ 'Initialize reserved Stack space (reserved below)
· TestSquareWave··············· 'Run method below.
· waitcnt(clkfreq * 3 + cnt)·· 'Wait ample time for max stack usage
· Stk.GetLength(30, 19200)···· 'Transmit results serially out P30 at 19,200 baud
Then I click on run and compile current to load in the EEPROM.
Then I startup the Parallax Serial Terminal, select the same com port as the Propeller is on (Com 4 in my case), and 19200 baud. Then click on Enable.
Then I press the reset button on the Propeller...
(Stack Length sends the information back sooner than you can get the get the Parallax Serial Terminal up and running, so need to have this loaded into EEPROM and then reset the propeller to send the information again.)
Then I get the message on the terminal...
Stack Usage: 90
Next I commented out the last two new cogs being started up so I had this...
··· swCog[noparse][[/noparse]0] := cognew(SquareWave(5, clkfreq/20, clkfreq/10), @swStack)
'··· swCog[noparse][[/noparse]1] := cognew(SquareWave(6, clkfreq/100, clkfreq/5), @swStack[noparse][[/noparse]40])
'··· swCog[noparse][[/noparse]2] := cognew(SquareWave(9, clkfreq/2000, clkfreq/500), @swStack[noparse][[/noparse]80])
Then I loaded that into EEPROM, got the terminal up and running, then got this...
Stack Usage: 10
Next I commented out just the last one like this...
··· swCog[noparse][[/noparse]0] := cognew(SquareWave(5, clkfreq/20, clkfreq/10), @swStack)
··· swCog[noparse][[/noparse]1] := cognew(SquareWave(6, clkfreq/100, clkfreq/5), @swStack[noparse][[/noparse]40])
'··· swCog[noparse][[/noparse]2] := cognew(SquareWave(9, clkfreq/2000, clkfreq/500), @swStack[noparse][[/noparse]80])
...and I get...
Stack Usage: 50
Questions...
So I conclude that the stack usage "per cog" is 10 longs, correct?
And that the Stack Length object would only be valid while measuring the stack space used for one cog, but not multiple cogs at the same time correct?
So now the question is....
If I use Stack Length and it says my object is using 10 longs of stack space, then I would not want to declare *just* 10 longs, rather a little more to add a bit of leeway? Perhaps 12? Or what is best once you determine the actual stack space needed for an object?
For a test I'm running TestSquareWaveMethod.spin from the PE kit / Methods and Cogs Lab folder.
TestSquareWaveMethod.spin assigns a stack space of...
long swStack[noparse][[/noparse]120]
...for 3 new cogs it runs as follows...
swCog[noparse][[/noparse]0] := cognew(SquareWave(5, clkfreq/20, clkfreq/10), @swStack)
swCog[noparse][[/noparse]1] := cognew(SquareWave(6, clkfreq/100, clkfreq/5), @swStack[noparse][[/noparse]40])
swCog[noparse][[/noparse]2] := cognew(SquareWave(9, clkfreq/2000, clkfreq/500), @swStack[noparse][[/noparse]80])
So 40 longs of stack space for each new cog being run and 120 longs total stack space. OK...
Then I added the "Stack Length" object to measure how much stack space was being used. I added the following at the top of the file/object TestSquareWaveMethod.spin after the end of the CON block (where it sets the clock speed as is also needed for Stack Length)...
OBJ
· Stk·· :······ "Stack Length"····· 'Include Stack Length Object
PUB TestStack
· Stk.Init(@swStack, 120)········ 'Initialize reserved Stack space (reserved below)
· TestSquareWave··············· 'Run method below.
· waitcnt(clkfreq * 3 + cnt)·· 'Wait ample time for max stack usage
· Stk.GetLength(30, 19200)···· 'Transmit results serially out P30 at 19,200 baud
Then I click on run and compile current to load in the EEPROM.
Then I startup the Parallax Serial Terminal, select the same com port as the Propeller is on (Com 4 in my case), and 19200 baud. Then click on Enable.
Then I press the reset button on the Propeller...
(Stack Length sends the information back sooner than you can get the get the Parallax Serial Terminal up and running, so need to have this loaded into EEPROM and then reset the propeller to send the information again.)
Then I get the message on the terminal...
Stack Usage: 90
Next I commented out the last two new cogs being started up so I had this...
··· swCog[noparse][[/noparse]0] := cognew(SquareWave(5, clkfreq/20, clkfreq/10), @swStack)
'··· swCog[noparse][[/noparse]1] := cognew(SquareWave(6, clkfreq/100, clkfreq/5), @swStack[noparse][[/noparse]40])
'··· swCog[noparse][[/noparse]2] := cognew(SquareWave(9, clkfreq/2000, clkfreq/500), @swStack[noparse][[/noparse]80])
Then I loaded that into EEPROM, got the terminal up and running, then got this...
Stack Usage: 10
Next I commented out just the last one like this...
··· swCog[noparse][[/noparse]0] := cognew(SquareWave(5, clkfreq/20, clkfreq/10), @swStack)
··· swCog[noparse][[/noparse]1] := cognew(SquareWave(6, clkfreq/100, clkfreq/5), @swStack[noparse][[/noparse]40])
'··· swCog[noparse][[/noparse]2] := cognew(SquareWave(9, clkfreq/2000, clkfreq/500), @swStack[noparse][[/noparse]80])
...and I get...
Stack Usage: 50
Questions...
So I conclude that the stack usage "per cog" is 10 longs, correct?
And that the Stack Length object would only be valid while measuring the stack space used for one cog, but not multiple cogs at the same time correct?
So now the question is....
If I use Stack Length and it says my object is using 10 longs of stack space, then I would not want to declare *just* 10 longs, rather a little more to add a bit of leeway? Perhaps 12? Or what is best once you determine the actual stack space needed for an object?
Comments
If you have tested every code path (different code executes depending on if a condition is true or false, or different code could run depending on the parameters passed).
AND, if you are not going to make any more changes to the code, and you'll remember to add more stack if you ever do make a change, then you can set the stack space exactly.
Otherwise, if you have the space, just add like 16 more bytes than what it needs. No reason to stress yourself out.
If you have got every byte accounted for, it's a tough position to be in.
I've never seen 100% efficient memory utilization in a commercial product. There's always something left over at the end for changes or bugfixes.
I would think of the stack object as being very useful in terms of what order of magnitude of bytes you need: Do I need 10?, 100?, 1000? bytes for the stack?
Also I've been playing around with this a bit more. It seems it actually uses 11 longs rather than 10. (Counting 0!)
So yes, 10 is the stack usage for one cog. Using exactly that is OK. Myself, I use +2 (just a feeling, no rational reason(s)).
I modified it so I can pass the starting address of one specific cog and the ending address of that cog via the size.
So I can run all 3 cogs now and measure the stack size used on just one cog - any of the 3.
This is what I modified it to (perhaps this modification could be·written better?)...
VAR
· long StackBegin
· long StackSize
OBJ
· Stk :· "Bill_Stack_Length"··· 'Include Stack Length Object
PUB TestStack
· StackBegin := @swStack[noparse][[/noparse]40]· ' Beginning location of stack for one cog.
· StackSize :=·39············ ' Size of the cogs stack.
· Stk.Init(StackBegin, StackSize)·
·TestSquareWave·············· 'Run method below.
· waitcnt(clkfreq * 5 + cnt)·· 'Wait ample time for max stack usage
· Stk.GetLength(30, 19200)···· 'Transmit results serially out P30 at 19,200 baud
Post Edited (bill190) : 4/26/2010 3:37:58 PM GMT
The following adds 1 to the count so the stack size reported·is the correct size...
· if ++USize == Size+1························································· 'If stack is full
··· USize~~···································································· '· flag as inconclusive
· 'Bill modification to add 1 to string count
· If USize > 1
··· USize++
·
· {Convert to string}
· Num.Init
Then in the following I add character 13 (carrage return) to the serial output so each new message sent to the serial terminal will begin on a new line...
· bytefill(@Text + 13, 0, 5)······················· 'Zero-terminate friendly string
· bytemove(@Text + 12, UsedLongsStr, strsize(UsedLongsStr))
' Bill modification to add carrige return
· bytemove(@Text + 12 + strsize(UsedLongsStr), string(13) , 1 )
· UsedLongsStr := USize := @Text····························
What I did was reduce the size of the stack. Actually with just one cog running. When I reduced it to 10, I got an error. But with a stack size of 11, it worked ok and said my stack size was 10.
As I recall the error returned was -1.
So set stack size to 10 and I got a -1 error.
Set stack size to 11 and it said my stack size was 10...
·
Returns:··· Pointer to string indicating actual utilization of stack, in form: "Stack Usage: #" where # is as follows:
············· -1 = inconclusive; stack may be too small, increase size and try again.
·············· 0 = stack never utilized.
············· >0 = maximum utilization (in longs) of stack up to this moment.
It's just a matter of interpreting the result [noparse]:)[/noparse]
Post Edited (kuroneko) : 4/27/2010 3:00:01 AM GMT
Good points! I guess it would not be able to tell an exact size thinking about the way it works.
Place markers to see if they are overwritten...
XXXXXXXXXX
Then the cog overwrites *all* the markers...
YYYYYYYYYY
Then stack length can't find any of its markers it left, so -1
Thanks, I'm learning. I'll remove that modification...
Thanks, Dan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"She may not be very pretty now, but she was somebody's baby once." Bugs Bunny
Thanks kuroneko, Dan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"She may not be very pretty now, but she was somebody's baby once." Bugs Bunny