I compared with Jon Hylands and discovered a big difference between my Ubuntu and his Windows results.
Time millisecondsToRun: [10 timesRepeat: [(Delay forMilliseconds: 1000) wait]] 10015
Time millisecondsToRun: [100 timesRepeat: [(Delay forMilliseconds: 100) wait]] 10015
Time millisecondsToRun: [1000 timesRepeat: [(Delay forMilliseconds: 10) wait]] 13405
Time millisecondsToRun: [10000 timesRepeat: [(Delay forMilliseconds: 1) wait]] 45728
He did the third test and got something like 10250 instead of my 13405.
Is this behavior well-known and understood or is there something wrong with my install?
Thanks for any help. It's a big problem for my robot (and therefore me) at the moment.
- Robert
2008/2/28 Robert F. Scheer rfscheer@speakeasy.net:
I compared with Jon Hylands and discovered a big difference between my Ubuntu and his Windows results.
Time millisecondsToRun: [10 timesRepeat: [(Delay forMilliseconds: 1000) wait]] 10015
Time millisecondsToRun: [100 timesRepeat: [(Delay forMilliseconds: 100) wait]] 10015
Time millisecondsToRun: [1000 timesRepeat: [(Delay forMilliseconds: 10) wait]] 13405
Time millisecondsToRun: [10000 timesRepeat: [(Delay forMilliseconds: 1) wait]] 45728
He did the third test and got something like 10250 instead of my 13405.
Is this behavior well-known and understood or is there something wrong with my install?
Thanks for any help. It's a big problem for my robot (and therefore me) at the moment.
With low numbers (like 1 ms) there is a big deviation in accuracy. Also, keep in mind that different OSes having different minimal measurable clock step.
- Robert
On Feb 27, 2008, at 9:50 PM, Robert F. Scheer wrote:
Time millisecondsToRun: [1000 timesRepeat: [(Delay forMilliseconds: 10) wait]] 13405
Time millisecondsToRun: [10000 timesRepeat: [(Delay forMilliseconds:
wait]] 45728
For the curious the os-x carbon vm does
Time millisecondsToRun: [1000 timesRepeat: [(Delay forMilliseconds: 10) wait]] 10196
Time millisecondsToRun: [10000 timesRepeat: [(Delay forMilliseconds: 1) wait]] 100916
The place you need to look at is your platform's
int ioRelinquishProcessorForMicroseconds(int microSeconds) { /* This operation is platform dependent. */
Yes very platform dependent, and VM flavour dependent.
When you do the code above you really are saying gee let's sleep alot. Then ioRelinquishProcessorForMicroseconds runs to judge when next best to wake up to service the end of the Delay. Also on unix if the operating system says the increment for process switch is oh 10 milliseconds then why you cannot actually sleep for 1 ms.
Time to break out the debugger and your source code reader and carefully examine what ioRelinquishProcessorForMicroseconds() is doing.
In the far past we would just put the VM to sleep for 10 ms or 1 ms, but a few years back I changed that to put the vm to sleep upto the next point where it needed to wake up (we know that because we know at what time delays will trigger in the future). Tempering that is code that aborts the sleep if a keyboard/file handle/someting interrupt comes in, so that can be serviced right away.
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
Thanks, this is very helpful.
I had just checked with a little C program to see that CLOCKS_PER_SEC on my system(s) is 1000000 so that shouldn't be the limiter.
I have a feeling that my robot is about to go down the rabbit hole.
- Robert
On Wed, 2008-02-27 at 21:17 -0800, John M McIntosh wrote:
On Feb 27, 2008, at 9:50 PM, Robert F. Scheer wrote:
Time millisecondsToRun: [1000 timesRepeat: [(Delay forMilliseconds: 10) wait]] 13405
Time millisecondsToRun: [10000 timesRepeat: [(Delay forMilliseconds:
wait]] 45728
For the curious the os-x carbon vm does
Time millisecondsToRun: [1000 timesRepeat: [(Delay forMilliseconds: 10) wait]] 10196
Time millisecondsToRun: [10000 timesRepeat: [(Delay forMilliseconds:
- wait]] 100916
The place you need to look at is your platform's
int ioRelinquishProcessorForMicroseconds(int microSeconds) { /* This operation is platform dependent. */
Yes very platform dependent, and VM flavour dependent.
When you do the code above you really are saying gee let's sleep alot. Then ioRelinquishProcessorForMicroseconds runs to judge when next best to wake up to service the end of the Delay. Also on unix if the operating system says the increment for process switch is oh 10 milliseconds then why you cannot actually sleep for 1 ms.
Time to break out the debugger and your source code reader and carefully examine what ioRelinquishProcessorForMicroseconds() is doing.
In the far past we would just put the VM to sleep for 10 ms or 1 ms, but a few years back I changed that to put the vm to sleep upto the next point where it needed to wake up (we know that because we know at what time delays will trigger in the future). Tempering that is code that aborts the sleep if a keyboard/file handle/someting interrupt comes in, so that can be serviced right away.
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
Robert F. Scheer wrote:
Is this behavior well-known and understood or is there something wrong with my install?
This is a very well known issue. Different operating systems have very different minimal timer resolutions. Generally speaking, on Windows and Mac OS the timer resolution is very close to 1ms whereas most Linux kernels have *awful* timer resolutions. I have been told that you can recompile your kernel to fix it but I'm not sure how. The classic benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1. bag := Bag new. 1000 timesRepeat:[bag add: [delay wait] timeToRun]. bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means that 94.1% of the delays are true 1msec delays.
Cheers, - Andreas
2008/2/28 Andreas Raab andreas.raab@gmx.de:
Robert F. Scheer wrote:
Is this behavior well-known and understood or is there something wrong with my install?
This is a very well known issue. Different operating systems have very different minimal timer resolutions. Generally speaking, on Windows and Mac OS the timer resolution is very close to 1ms whereas most Linux kernels have *awful* timer resolutions. I have been told that you can recompile your kernel to fix it but I'm not sure how. The classic benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1. bag := Bag new. 1000 timesRepeat:[bag add: [delay wait] timeToRun]. bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means that 94.1% of the delays are true 1msec delays.
Here the numbers for HydraVM. a SortedCollection(895->2 91->1 14->3)
It can't be so precise as old VM, because delay timeouts are signaled in separate thread as event, which is then consumed by Interpreter as soon as possible, but it takes a little more time (switching threads e.t.c). Things can be more precise on multicore system.
I had a hard time fighting with delays lately.. what i can say.. this is one of the weakest and critical points in VM and language side.
Cheers,
- Andreas
On Thu, 2008-02-28 at 07:59 +0200, Igor Stasenko wrote:
2008/2/28 Andreas Raab andreas.raab@gmx.de:
Robert F. Scheer wrote:
Is this behavior well-known and understood or is there something wrong with my install?
This is a very well known issue. Different operating systems have very different minimal timer resolutions. Generally speaking, on Windows and Mac OS the timer resolution is very close to 1ms whereas most Linux kernels have *awful* timer resolutions. I have been told that you can recompile your kernel to fix it but I'm not sure how. The classic benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1. bag := Bag new. 1000 timesRepeat:[bag add: [delay wait] timeToRun]. bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means that 94.1% of the delays are true 1msec delays.
Here the numbers for HydraVM. a SortedCollection(895->2 91->1 14->3)
How does this compare to standard VM on your OS?
What is your OS?
It can't be so precise as old VM, because delay timeouts are signaled in separate thread as event, which is then consumed by Interpreter as soon as possible, but it takes a little more time (switching threads e.t.c). Things can be more precise on multicore system.
I had a hard time fighting with delays lately.. what i can say.. this is one of the weakest and critical points in VM and language side.
Cheers,
- Andreas
2008/2/28 Robert F. Scheer rfscheer@speakeasy.net:
On Thu, 2008-02-28 at 07:59 +0200, Igor Stasenko wrote:
2008/2/28 Andreas Raab andreas.raab@gmx.de:
Robert F. Scheer wrote:
Is this behavior well-known and understood or is there something wrong with my install?
This is a very well known issue. Different operating systems have very different minimal timer resolutions. Generally speaking, on Windows and Mac OS the timer resolution is very close to 1ms whereas most Linux kernels have *awful* timer resolutions. I have been told that you can recompile your kernel to fix it but I'm not sure how. The classic benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1. bag := Bag new. 1000 timesRepeat:[bag add: [delay wait] timeToRun]. bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means that 94.1% of the delays are true 1msec delays.
Here the numbers for HydraVM. a SortedCollection(895->2 91->1 14->3)
How does this compare to standard VM on your OS?
Using croquet VM: a SortedCollection(951->2 47->1 1->11 1->35)
Using squeak VM: a SortedCollection(952->2 48->1)
Surprisingly, but HydraVM seem more precise :)
What is your OS?
Window$
os-x carbon a SortedCollection(830->10 149->11 13->1 6->12 1->13 1->14)
well but it depends on the unix code to do things and that's a bit fuzzy at time, mind Andreas example below led to many sleepless hours... If you peek at the mac code it did at one time do this which gave 99.9% accuracy.
err = pthread_mutex_lock(&gSleepLock); err = pthread_cond_timedwait_relative_np (&gSleepLockCondition,&gSleepLock,&tspec); err = pthread_mutex_unlock(&gSleepLock);
But then someone reported dropped socket accepts because the pthread_cond_timedwait_relative_np would fail to service the Socket requests and I had to revert to Ian's unix code, which on os-x is less accurate but better than some unix machines.
From emails from 2002 Ian said.
NetBSD ppc: a SortedCollection(950->20 19->19 19->21 3->18 3->22 2->30 1->25 1->8 1->10 1->14)
Linux 386: a SortedCollection(294->1 213->2 146->3 100->4 84->5 55->6 33->7 33->8 11->10 9->11 8->9 6->13 5->12 1->14 1->17 1->18)
I noted 3.2.7b4 Mac VM gives a SortedCollection(533->2 278->3 46->23 31->24 24->22 21->1 15->4 11-
21 8->5 6->25 4->26 3->27 2->6 2->14 2->18 2->28 2->35 2->42 2->43 1- 12 1->15 1->20 1->29 1->41 1->47)
On Feb 27, 2008, at 9:37 PM, Andreas Raab wrote:
Robert F. Scheer wrote:
Is this behavior well-known and understood or is there something wrong with my install?
This is a very well known issue. Different operating systems have very different minimal timer resolutions. Generally speaking, on Windows and Mac OS the timer resolution is very close to 1ms whereas most Linux kernels have *awful* timer resolutions. I have been told that you can recompile your kernel to fix it but I'm not sure how. The classic benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1. bag := Bag new. 1000 timesRepeat:[bag add: [delay wait] timeToRun]. bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means that 94.1% of the delays are true 1msec delays.
Cheers,
- Andreas
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
2008/2/28 John M McIntosh johnmci@smalltalkconsulting.com:
os-x carbon a SortedCollection(830->10 149->11 13->1 6->12 1->13 1->14)
well but it depends on the unix code to do things and that's a bit fuzzy at time, mind Andreas example below led to many sleepless hours... If you peek at the mac code it did at one time do this which gave 99.9% accuracy.
err = pthread_mutex_lock(&gSleepLock); err =
pthread_cond_timedwait_relative_np (&gSleepLockCondition,&gSleepLock,&tspec); err = pthread_mutex_unlock(&gSleepLock);
But then someone reported dropped socket accepts because the pthread_cond_timedwait_relative_np would fail to service the Socket requests and I had to revert to Ian's unix code, which on os-x is less accurate but better than some unix machines.
I hope if you add my sleepless hours i spent making delays for hydra, you can come out with better results. :)
On Feb 27, 2008, at 10:40 PM, Igor Stasenko wrote:
I hope if you add my sleepless hours i spent making delays for hydra, you can come out with better results. :)
-- Best regards, Igor Stasenko AKA sig.
Well as the last person to fiddle with checkForInterrupts (with help from Tim) and to make the external semaphore signal queues work with interrupt driven code I admire your courage to rewrite it all.
Noting that the semaphoresUseBufferA and semaphoresUseBufferB exist because I was forbidden to use an operating system semaphore become some operating systems couldn't support it.
Welcome to look for holes in the logic tho.
"You know my plugin signals that external semaphore and the VM never sees it? Really? Got a test case? Proof?"
Why is the limit 500? Is that big enough? Aren't machines faster? Somehow I think a ioMutexLock() might lurk in the future?
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
Thanks for the most useful responses on this question of delay timing.
It's clear that the robot program architecture must change drastically as a result. Currently, there are perhaps 10 concurrent processes looping 50 times per second servicing various serial lines carrying sensor information or actuating motors and so forth. Although real time processing isn't required, it is mandatory that all processes and the main decision loop complete every 20ms, no matter what.
It seems like the best approach is to split the serial handlers outside of Squeak, which I can do in C without too much hassle. The question becomes, if the interfaces with Squeak transform to sockets and all the concurrent loops in Squeak reduce to one single loop, polling each socket in turn, would that complete within 20ms no matter what or are there similar problems with statistical delays involved with sockets?
I'll talk to Jon Hylands tomorrow and hope he'll save the Squeak but at this point I'm trying to avoid the quick reaction (some might say panic) that I just need to go back and do it all over in C.
Thanks for your very quick and understanding replies. This is the most helpful community I've seen online.
- Robert
On Wed, 2008-02-27 at 22:13 -0800, John M McIntosh wrote:
os-x carbon a SortedCollection(830->10 149->11 13->1 6->12 1->13 1->14)
well but it depends on the unix code to do things and that's a bit fuzzy at time, mind Andreas example below led to many sleepless hours... If you peek at the mac code it did at one time do this which gave 99.9% accuracy.
err = pthread_mutex_lock(&gSleepLock); err =
pthread_cond_timedwait_relative_np (&gSleepLockCondition,&gSleepLock,&tspec); err = pthread_mutex_unlock(&gSleepLock);
But then someone reported dropped socket accepts because the pthread_cond_timedwait_relative_np would fail to service the Socket requests and I had to revert to Ian's unix code, which on os-x is less accurate but better than some unix machines.
From emails from 2002 Ian said.
NetBSD ppc: a SortedCollection(950->20 19->19 19->21 3->18 3->22 2->30 1->25 1->8 1->10 1->14)
Linux 386: a SortedCollection(294->1 213->2 146->3 100->4 84->5 55->6 33->7 33->8 11->10 9->11 8->9 6->13 5->12 1->14 1->17 1->18)
I noted 3.2.7b4 Mac VM gives a SortedCollection(533->2 278->3 46->23 31->24 24->22 21->1 15->4 11-
21 8->5 6->25 4->26 3->27 2->6 2->14 2->18 2->28 2->35 2->42 2->43 1- 12 1->15 1->20 1->29 1->41 1->47)
On Feb 27, 2008, at 9:37 PM, Andreas Raab wrote:
Robert F. Scheer wrote:
Is this behavior well-known and understood or is there something wrong with my install?
This is a very well known issue. Different operating systems have very different minimal timer resolutions. Generally speaking, on Windows and Mac OS the timer resolution is very close to 1ms whereas most Linux kernels have *awful* timer resolutions. I have been told that you can recompile your kernel to fix it but I'm not sure how. The classic benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1. bag := Bag new. 1000 timesRepeat:[bag add: [delay wait] timeToRun]. bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means that 94.1% of the delays are true 1msec delays.
Cheers,
- Andreas
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
Robert F. Scheer wrote:
It's clear that the robot program architecture must change drastically as a result. Currently, there are perhaps 10 concurrent processes looping 50 times per second servicing various serial lines carrying sensor information or actuating motors and so forth. Although real time processing isn't required, it is mandatory that all processes and the main decision loop complete every 20ms, no matter what.
I am not sure why your architecture has to change dramatically as a result. If your main problem is to make sure that that a loop is done every 20msecs and you need to adjust for statistical delay variations, you can simply compute the actual time the wait took and do something like:
nextDesiredTick := Time millisecondClockValue + 20. [true] whileTrue:[ self doControl. "note: for very, very long doControl the waitTime could be negative. you have to decide whether it's better to skip or to run an extra doControl in this case." waitTime := nextDesiredTick - Time millisecondClockValue. (Delay forMilliseconds: waitTime) wait. "Next desired tick is twenty msecs from last one" nextDesiredTick := nextDesiredTick + 20. ].
Not only will this adjust to statistical variations in delay but it will also take into account the amount of time spent in doControl, including eventual time spent in other processes due to preemption. In other words, the above is as close to 20msecs as it possibly gets.
Also, keep in mind that no amount of C coding will increase the accuracy of your OS' default timer. But if you happen to have a high-quality timer it would be quite trivial to link this timer to the TimerSemaphore and use it instead of whatever the VM gives you.
Cheers, - Andreas
On Feb 27, 2008, at 11:38 PM, Andreas Raab wrote:
Also, keep in mind that no amount of C coding will increase the accuracy of your OS' default timer. But if you happen to have a high- quality timer it would be quite trivial to link this timer to the TimerSemaphore and use it instead of whatever the VM gives you.
Cheers,
- Andreas
I can't speak for Windows works but the magic on unix systems happens in ioRelinquishProcessorForMicroseconds
getNextWakeupTick() is the known time we must wakeup to service the next delay, that is the delay wants to terminate then.
setInterruptCheckCounter(0); <= this ensure the interpreter interrupt logic fires really soon after we finish this call to switch perhaps to the other runable process
now = (ioMSecs() & MillisecondClockMask); if (getNextWakeupTick() <= now) if (getNextWakeupTick() == 0) <- with morphic this never happens realTimeToWait = 16; <--- this value might be platform dependent else { return 0; <= if time now is after the time of the next wakeup don't sleep. } else realTimeToWait = getNextWakeupTick() - now; <==== this is where we estimate how long to sleep.
platformSleep(realTimeToWait*1000); <=== accuracy dictates how delay behaves.
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
John M McIntosh wrote:
I can't speak for Windows works but the magic on unix systems happens in ioRelinquishProcessorForMicroseconds
But none of it contradicts what I said earlier - if platformSleep uses the system's default timer (which it should) then the accuracy of C code will be no better than the accuracy of Squeak. And if it doesn't, well then the code is broken and you should fix it. It sure as hell works on Windows (perhaps I can shame you into fixing it? ;-)
Cheers, - Andreas
Yawn, there has to be a reason why most of the VM maintainers are up at midnight, well assuming it's midnight for Igor. But I'm too tired now, so will respond tomorrow.
On Feb 27, 2008, at 11:58 PM, Andreas Raab wrote:
John M McIntosh wrote:
I can't speak for Windows works but the magic on unix systems happens in ioRelinquishProcessorForMicroseconds
But none of it contradicts what I said earlier - if platformSleep uses the system's default timer (which it should) then the accuracy of C code will be no better than the accuracy of Squeak. And if it doesn't, well then the code is broken and you should fix it. It sure as hell works on Windows (perhaps I can shame you into fixing it? ;-)
Cheers,
- Andreas
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
I forgot to be very clear about this in the last post, there is one main reason why C would have no trouble keeping these loops all serviced.
The reads would block. While waiting for the first byte of a packet to come in for the next cycle, no processing cycles would be consumed. No delays inside loops would be needed.
- Robert
2008/2/28 Robert F. Scheer rfscheer@speakeasy.net:
I forgot to be very clear about this in the last post, there is one main reason why C would have no trouble keeping these loops all serviced.
The reads would block. While waiting for the first byte of a packet to come in for the next cycle, no processing cycles would be consumed. No delays inside loops would be needed.
Doesn't plugins for working with serial port(s) provide you a schemes where you can use semaphores? So , you can block a process until some data available.
- Robert
Robert F. Scheer wrote:
I forgot to be very clear about this in the last post, there is one main reason why C would have no trouble keeping these loops all serviced.
The reads would block. While waiting for the first byte of a packet to come in for the next cycle, no processing cycles would be consumed. No delays inside loops would be needed.
I see. Well, if you'd be willing to throw a couple of native threads at the problem to service these lines, you could deal with the problem easily simply by writing the blocking read in C and have that (once it reads the data) signal a semaphore in Squeak which makes the associated Squeak process wake up and retrieve and process the data you just read.
Cheers, - Andreas
On Thu, 2008-02-28 at 00:26 -0800, Andreas Raab wrote:
Robert F. Scheer wrote:
I forgot to be very clear about this in the last post, there is one main reason why C would have no trouble keeping these loops all serviced.
The reads would block. While waiting for the first byte of a packet to come in for the next cycle, no processing cycles would be consumed. No delays inside loops would be needed.
I see. Well, if you'd be willing to throw a couple of native threads at the problem to service these lines, you could deal with the problem easily simply by writing the blocking read in C and have that (once it reads the data) signal a semaphore in Squeak which makes the associated Squeak process wake up and retrieve and process the data you just read.
Cheers,
- Andreas
I can do it this way, sure. Just have to figure out how to do the signalling and interprocess communication. Would you use sockets for the ipc?
Robert F. Scheer wrote:
I can do it this way, sure. Just have to figure out how to do the signalling and interprocess communication. Would you use sockets for the ipc?
Yes. It's the easiest way to get things going given your time constraints. If you had more time I would recommend learning enough slang and vm plugin coding to signal a semaphore directly since this would take out one additional set of hops in the middle.
Cheers, - Andreas
On Thu, 28 Feb 2008 02:00:38 -0800, "Robert F. Scheer" rfscheer@speakeasy.net wrote:
I can do it this way, sure. Just have to figure out how to do the signalling and interprocess communication. Would you use sockets for the ipc?
The other thing you can try (to do this all in Squeak), which is what I normally do, is this:
- use a higher priority process in Squeak (forkAt: Processor userInterruptPriority) to run your serial loop
[ [done] whileFalse: [ data := serialPort readBytes. (data notNil and: [data notEmpty]) ifTrue: [sharedQueue nextPut: data]. (Delay forMilliseconds: 1) wait]] forkAt: Processor userInterruptPriority named: 'Serial-Reader'.
This way the normal processing loop just waits on a SharedQueue (basically waiting on a semaphore), and it becomes a blocking read. You can either feed all of your raw data into one shared queue (appropriately tagged) or have different ones for different things.
Later, Jon
-------------------------------------------------------------- Jon Hylands Jon@huv.com http://www.huv.com/jon
Project: Micro Raptor (Small Biped Velociraptor Robot) http://www.huv.com/blog
A more extensive, obsolete code sample http://www.smalltalkconsulting.com/papers/tipsAndThoughts/source/JMM-Network...
On Feb 28, 2008, at 3:55 AM, Jon Hylands wrote:
On Thu, 28 Feb 2008 02:00:38 -0800, "Robert F. Scheer" rfscheer@speakeasy.net wrote:
I can do it this way, sure. Just have to figure out how to do the signalling and interprocess communication. Would you use sockets for the ipc?
The other thing you can try (to do this all in Squeak), which is what I normally do, is this:
- use a higher priority process in Squeak (forkAt: Processor
userInterruptPriority) to run your serial loop
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
On Thu, 2008-02-28 at 06:55 -0500, Jon Hylands wrote:
The other thing you can try (to do this all in Squeak), which is what I normally do, is this:
- use a higher priority process in Squeak (forkAt: Processor
userInterruptPriority) to run your serial loop
[ [done] whileFalse: [ data := serialPort readBytes. (data notNil and: [data notEmpty]) ifTrue: [sharedQueue nextPut: data]. (Delay forMilliseconds: 1) wait]] forkAt: Processor userInterruptPriority named: 'Serial-Reader'.
Later, Jon
I tested the higher priority fork against a simple user loop and the forked loop came out the loser.
[ delay := Delay forMilliseconds: 1. bag1 := Bag new. 1000 timesRepeat:[bag1 add: [delay wait] timeToRun]. ] forkAt: Processor userInterruptPriority bag1 sortedCounts "a SortedCollection(746->1 86->16 69->14 65->15 32->13 1->2 1->22)"
delay := Delay forMilliseconds: 1. bag2 := Bag new. 1000 timesRepeat:[bag2 add: [delay wait] timeToRun].
bag2 sortedCounts "a SortedCollection(982->1 6->16 5->13 4->14 1->15 1->6 1->7)" I then ran both loops at the same time to see how they'd interact and got an interesting result.
delay1 := Delay forMilliseconds: 1. bag1 := Bag new. delay2 := Delay forMilliseconds: 1. bag2 := Bag new. [ 1000 timesRepeat:[bag1 add: [delay1 wait] timeToRun]. ] forkAt: Processor userInterruptPriority. 1000 timesRepeat:[bag2 add: [delay2 wait] timeToRun].
bag1 sortedCounts "a SortedCollection(914->1 39->16 17->15 14->13 14->14 1->4 1->6)" bag2 sortedCounts "a SortedCollection(914->1 39->16 17->15 14->13 14->14 1->5 1->6)"
My conclusion is not to use 1ms delays anywhere in the time critical loops of the robot. I'm off to look at the interprocess semaphore methods that David and Andreas have alluded to. It looks like C serial handlers are the way to go atm.
Thanks for all the suggestions everyone.
- Robert
On Feb 28, 2008, at 20:26 , Robert F. Scheer wrote:
My conclusion is not to use 1ms delays anywhere in the time critical loops of the robot. I'm off to look at the interprocess semaphore methods that David and Andreas have alluded to. It looks like C serial handlers are the way to go atm.
Well, I had satisfactory results reading from a pipe using AsyncFile (had to add a utility method though):
http://tinlizzie.org/updates/olpc/updates/0995sugar-bf.cs
In this code, #readChar blocks until data is actually available - it might work to just open /dev/tty... and start reading in a process, similar to what I did in #fetchCommandsFrom:.
- Bert -
On Thu, 2008-02-28 at 20:26 +0100, Bert Freudenberg wrote:
On Feb 28, 2008, at 20:26 , Robert F. Scheer wrote:
My conclusion is not to use 1ms delays anywhere in the time critical loops of the robot. I'm off to look at the interprocess semaphore methods that David and Andreas have alluded to. It looks like C serial handlers are the way to go atm.
Well, I had satisfactory results reading from a pipe using AsyncFile (had to add a utility method though):
http://tinlizzie.org/updates/olpc/updates/0995sugar-bf.cs
In this code, #readChar blocks until data is actually available - it might work to just open /dev/tty... and start reading in a process, similar to what I did in #fetchCommandsFrom:.
- Bert -
This is tantalizingly close to working. I can open, close and write something to serial ports as pipes with the AsyncFile methods but can't successfully read. As Jon Hylands pointed out, it's probably because they have no ability to negotiate baud rates and other minor serial port stuff.
The exciting part was opening '/dev/ttyUSB0' instead of having to symlink ttySx to ttyUSBx and pretending the USB port is a tty.
But at this point, I don't see how to get it working with serial lines unless I put C handlers in the way and use maybe RAM disk shared files as transfer pipes.
- Robert
On Thu, Feb 28, 2008 at 09:11:28PM -0800, Robert F. Scheer wrote:
This is tantalizingly close to working. I can open, close and write something to serial ports as pipes with the AsyncFile methods but can't successfully read. As Jon Hylands pointed out, it's probably because they have no ability to negotiate baud rates and other minor serial port stuff.
I assume that you are familiar with the unix "stty" command for setting serial port parameters, but I'll mention it just in case.
Dave
On Sat, 2008-03-01 at 09:59 -0500, David T. Lewis wrote:
On Thu, Feb 28, 2008 at 09:11:28PM -0800, Robert F. Scheer wrote:
This is tantalizingly close to working. I can open, close and write something to serial ports as pipes with the AsyncFile methods but can't successfully read. As Jon Hylands pointed out, it's probably because they have no ability to negotiate baud rates and other minor serial port stuff.
I assume that you are familiar with the unix "stty" command for setting serial port parameters, but I'll mention it just in case.
Dave
I was not but am now and thanks for the thoughtful followup. If it works, you've saved Squeak! Well, for me at least.
- Robert
David,
You're a life-saver! AysncFile methods have no trouble reading and writing from a properly configured serial port. Just set up the port properly with stty and it's no sweat.
It's especially useful to be able to designate /dev/ttyUSBx for a serial port that is connected through USB instead of the old RS232 ports.
I'll do some further tests of timing and blocking but just wanted to say THANKS!!
- Robert
On Sat, 2008-03-01 at 09:59 -0500, David T. Lewis wrote:
On Thu, Feb 28, 2008 at 09:11:28PM -0800, Robert F. Scheer wrote:
This is tantalizingly close to working. I can open, close and write something to serial ports as pipes with the AsyncFile methods but can't successfully read. As Jon Hylands pointed out, it's probably because they have no ability to negotiate baud rates and other minor serial port stuff.
I assume that you are familiar with the unix "stty" command for setting serial port parameters, but I'll mention it just in case.
Dave
The extended serial plugin has all the api to fiddle with stty, etc.
On Mar 1, 2008, at 3:48 PM, Robert F. Scheer wrote:
David,
You're a life-saver! AysncFile methods have no trouble reading and writing from a properly configured serial port. Just set up the port properly with stty and it's no sweat.
It's especially useful to be able to designate /dev/ttyUSBx for a serial port that is connected through USB instead of the old RS232 ports.
I'll do some further tests of timing and blocking but just wanted to say THANKS!!
- Robert
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
On Sat, 2008-03-01 at 14:53 -0800, John M McIntosh wrote:
The extended serial plugin has all the api to fiddle with stty, etc.
This feels a bit out of place being discussed on the developer list but I'm kinda afraid of plugins, having no experience with them yet and having a long way to go with the robot in too short a time.
I started reading through the VM material and could see that it would be easy to use only after paying some dues. For example, I couldn't right away figure out where to get the right version of VMMaker for my 3.9.8 VM. To be honest I'm not even certain that's needed for plugins, but that was the impression after skimming some of the material.
I'll get back to this and a number of other issues after getting the basic robot loops working and controlling properly.
Thanks again for the help.
-Robert
On Mar 1, 2008, at 3:48 PM, Robert F. Scheer wrote:
David,
You're a life-saver! AysncFile methods have no trouble reading and writing from a properly configured serial port. Just set up the port properly with stty and it's no sweat.
It's especially useful to be able to designate /dev/ttyUSBx for a serial port that is connected through USB instead of the old RS232 ports.
I'll do some further tests of timing and blocking but just wanted to say THANKS!!
- Robert
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
On Feb 27, 2008, at 11:58 PM, Andreas Raab wrote:
John M McIntosh wrote:
I can't speak for Windows works but the magic on unix systems happens in ioRelinquishProcessorForMicroseconds
But none of it contradicts what I said earlier - if platformSleep uses the system's default timer (which it should) then the accuracy of C code will be no better than the accuracy of Squeak. And if it doesn't, well then the code is broken and you should fix it. It sure as hell works on Windows (perhaps I can shame you into fixing it? ;-)
Oh, no not me, you see years ago we used Open Transport for tcp/ip which was interrupt driven and then the non-portable thread sleep logic.
a SortedCollection(895->1 99->2 5->3 1->4) (2003) likely data would be better today on machines being much faster.
Then one weekend I convince Ian he had to change the unix socket code so that it would actually run my Socket SUnits. It helped that was 9 hours west of him because he kinda zoned out on me after 36 hours or so of coding. Well plus he discovered a bug in the NetBSD tcp/ ip stack which didn't help things and we had to document that for the BSD team.
After that I switch to the unix socket code, and later had to migrate to the unix aioPoll sleep logic because of Socket accept issues, which as you see gives jittery results. Fixing that requires more work from Ian...
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
On Wed, 2008-02-27 at 23:38 -0800, Andreas Raab wrote:
Robert F. Scheer wrote:
It's clear that the robot program architecture must change drastically as a result. Currently, there are perhaps 10 concurrent processes looping 50 times per second servicing various serial lines carrying sensor information or actuating motors and so forth. Although real time processing isn't required, it is mandatory that all processes and the main decision loop complete every 20ms, no matter what.
I am not sure why your architecture has to change dramatically as a result. If your main problem is to make sure that that a loop is done every 20msecs and you need to adjust for statistical delay variations, you can simply compute the actual time the wait took and do something like:
nextDesiredTick := Time millisecondClockValue + 20. [true] whileTrue:[ self doControl. "note: for very, very long doControl the waitTime could be negative. you have to decide whether it's better to skip or to run an extra doControl in this case." waitTime := nextDesiredTick - Time millisecondClockValue. (Delay forMilliseconds: waitTime) wait. "Next desired tick is twenty msecs from last one" nextDesiredTick := nextDesiredTick + 20. ].
Not only will this adjust to statistical variations in delay but it will also take into account the amount of time spent in doControl, including eventual time spent in other processes due to preemption. In other words, the above is as close to 20msecs as it possibly gets.
Yes, I see this could make a loop time average very close to exactly the desired value over many cycles, but my main problem is in the serial i/o loops.
Picture 5 serial lines. Each has a packet of a few to a few dozen bytes arriving every 20ms although they are not synchronous. The data arrives on time within a few microseconds every cycle and it must be captured.
I was trying to use delays of around 15ms to prevent the Squeak i/o processes from continuously tying up compute cycles trying to read the serial lines when no data was expected. Read a packet, delay 15ms, then go into a tighter loop trying every 1ms until the packet was read.
Now, I know this is a bad scheme. Even a 1ms programmed delay could become longer than 20ms sometimes. So let's get rid of all programmed delays inside the serial i/o loops.
Well, now don't we have a situation where the cpu is tied up 100% and the latency to switch between processes is very poor?
I probably don't understand the primitive serial methods well enough. They seem not to block while awaiting input so that requires continuously looping to read. Is there a blocking method?
Also, keep in mind that no amount of C coding will increase the accuracy of your OS' default timer. But if you happen to have a high-quality timer it would be quite trivial to link this timer to the TimerSemaphore and use it instead of whatever the VM gives you.
Cheers,
- Andreas
Robert F. Scheer wrote:
Picture 5 serial lines. Each has a packet of a few to a few dozen bytes arriving every 20ms although they are not synchronous. The data arrives on time within a few microseconds every cycle and it must be captured.
I was trying to use delays of around 15ms to prevent the Squeak i/o processes from continuously tying up compute cycles trying to read the serial lines when no data was expected. Read a packet, delay 15ms, then go into a tighter loop trying every 1ms until the packet was read.
Now, I know this is a bad scheme. Even a 1ms programmed delay could become longer than 20ms sometimes. So let's get rid of all programmed delays inside the serial i/o loops.
Ah. Now we are talking. What you want is the ability for a serial port to issue an interrupt / signal a semaphore so that your waiting process gets woken up when something happens. The way to do this is by fixing the (very, very naive) serial port primitives to add something that allows you to signal a semaphore upon data availability. There are examples for this kind of thing in other plugins (like the socket or async file plugin).
Also, I vaguely remember that John had built a better serial port plugin (don't remember where I saw this but I'm sure he'll chime in) which may very well support this out of the box.
I probably don't understand the primitive serial methods well enough. They seem not to block while awaiting input so that requires continuously looping to read. Is there a blocking method?
There isn't. Since Squeak doesn't use native threads internally (instead it uses so-called "green threads") a blocking read would block the entire VM and completely defeat the purpose of a blocking read. That's why all such primitives are designed to simply signal a semaphore so that the process in squeak just sits there doing something like:
dataArrived := Semaphore new. self registerSemaphoreForSignallingData: dataArrived. [true] whileTrue:[ dataArrived wait. self processData. ].
etc.
Cheers, - Andreas
On Thu, 2008-02-28 at 00:18 -0800, Andreas Raab wrote:
Robert F. Scheer wrote:
Picture 5 serial lines. Each has a packet of a few to a few dozen bytes arriving every 20ms although they are not synchronous. The data arrives on time within a few microseconds every cycle and it must be captured.
I was trying to use delays of around 15ms to prevent the Squeak i/o processes from continuously tying up compute cycles trying to read the serial lines when no data was expected. Read a packet, delay 15ms, then go into a tighter loop trying every 1ms until the packet was read.
Now, I know this is a bad scheme. Even a 1ms programmed delay could become longer than 20ms sometimes. So let's get rid of all programmed delays inside the serial i/o loops.
Ah. Now we are talking. What you want is the ability for a serial port to issue an interrupt / signal a semaphore so that your waiting process gets woken up when something happens. The way to do this is by fixing the (very, very naive) serial port primitives to add something that allows you to signal a semaphore upon data availability. There are examples for this kind of thing in other plugins (like the socket or async file plugin).
Also, I vaguely remember that John had built a better serial port plugin (don't remember where I saw this but I'm sure he'll chime in) which may very well support this out of the box.
I probably don't understand the primitive serial methods well enough. They seem not to block while awaiting input so that requires continuously looping to read. Is there a blocking method?
There isn't. Since Squeak doesn't use native threads internally (instead it uses so-called "green threads") a blocking read would block the entire VM and completely defeat the purpose of a blocking read. That's why all such primitives are designed to simply signal a semaphore so that the process in squeak just sits there doing something like:
dataArrived := Semaphore new. self registerSemaphoreForSignallingData: dataArrived. [true] whileTrue:[ dataArrived wait. self processData. ].
etc.
Cheers,
- Andreas
Yes, that's what I need. Unfortunately being a Squeak newbie and having one month till competition, this looks like an insurmountable gap to me atm. But if it existed, I'd be in heaven.
Thanks for the analysis.
- Robert
On Thu, Feb 28, 2008 at 01:53:26AM -0800, Robert F. Scheer wrote:
On Thu, 2008-02-28 at 00:18 -0800, Andreas Raab wrote:
Robert F. Scheer wrote:
I probably don't understand the primitive serial methods well enough. They seem not to block while awaiting input so that requires continuously looping to read. Is there a blocking method?
There isn't. Since Squeak doesn't use native threads internally (instead it uses so-called "green threads") a blocking read would block the entire VM and completely defeat the purpose of a blocking read. That's why all such primitives are designed to simply signal a semaphore so that the process in squeak just sits there doing something like:
dataArrived := Semaphore new. self registerSemaphoreForSignallingData: dataArrived. [true] whileTrue:[ dataArrived wait. self processData. ].
Yes, that's what I need. Unfortunately being a Squeak newbie and having one month till competition, this looks like an insurmountable gap to me atm. But if it existed, I'd be in heaven.
Robert,
I don't have time to read catch up with this thread, but FYI the kind of event driven input that Andreas describes is implemented in AioPlugin and OSProcess. CommandShell uses this heavily with pipes. I do not know if it will work with serial lines (/dev/ttyXX) but I can't think of any reason that it wouldn't.
With that sort of approach, you would use one Squeak process to service each inbound serial connection, and each process would wait on a semaphore, so no polling required. The Linux serial drivers handle the IO buffering etc, so it might work fine.
Sorry I don't have any performance numbers to quote, and I've never tried it on /dev/ttyXX.
HTH, Dave
On Feb 28, 2008, at 12:18 AM, Andreas Raab wrote:
Also, I vaguely remember that John had built a better serial port plugin (don't remember where I saw this but I'm sure he'll chime in) which may very well support this out of the box.
That would be the http://map.squeak.org/package/36c286ee-c0af-4853-98a4-42ea9540f571 It fully exposes all the BSD api for dealing with serial devices. It was done on i386 FreeBSD and powerPC os-x so I don't think there are any endian issues, well porting issues of course.
See the SVN squeak macintosh plugins folder for the SerialExtendedUnixPlugin xcode project.
On my ftp or idisk in the experimental folder there should be EnhancedSerialPorts-JMM.11.cs.gz and SerialExtendedUnixPlugin.bundle.zip
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
I'm curious/lazy here, I stuck this pattern in the Morphic event control loop years back to achieve the 60 fps morphic update rate. However as someone finally discovered last year this had sideeffect, on an MC server it would stop responding because it was discovered the higher priority UI loop would run the calculation of waitTime which was <= 0 Then it would not run the Delay which hung any incoming lower priority MC queries, and as we know, swirling the mouse restored sanity.
On a (Delay forMilliseconds: x) where x is <= 0 does it let other lower priority processes run for a bit?
On Feb 27, 2008, at 11:38 PM, Andreas Raab wrote:
I am not sure why your architecture has to change dramatically as a result. If your main problem is to make sure that that a loop is done every 20msecs and you need to adjust for statistical delay variations, you can simply compute the actual time the wait took and do something like:
nextDesiredTick := Time millisecondClockValue + 20. [true] whileTrue:[ self doControl. "note: for very, very long doControl the waitTime could be negative. you have to decide whether it's better to skip or to run an extra doControl in this case." waitTime := nextDesiredTick - Time millisecondClockValue. (Delay forMilliseconds: waitTime) wait. "Next desired tick is twenty msecs from last one" nextDesiredTick := nextDesiredTick + 20. ].
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
Very nice method.
My results are "a SortedCollection(937->1 26->16 15->14 11->13 10->15 1->3)"
I thought the 2.6.20 series of Linux kernels had greatly improved the timer issues in a big push to make multimedia applications behave well on the desktop, which they do now quite well.
- Robert
On Wed, 2008-02-27 at 21:37 -0800, Andreas Raab wrote:
Robert F. Scheer wrote:
Is this behavior well-known and understood or is there something wrong with my install?
This is a very well known issue. Different operating systems have very different minimal timer resolutions. Generally speaking, on Windows and Mac OS the timer resolution is very close to 1ms whereas most Linux kernels have *awful* timer resolutions. I have been told that you can recompile your kernel to fix it but I'm not sure how. The classic benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1. bag := Bag new. 1000 timesRepeat:[bag add: [delay wait] timeToRun]. bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means that 94.1% of the delays are true 1msec delays.
Cheers,
- Andreas
Hi--
For what it's worth, the Center for Contemporary Research in Music and Acoustics at Stanford University (CCRMA) offers packages to make RedHat and Fedora Core Linux suitable for very-low-latency multimedia use[1]. I've seen demos of it and it works.
-C
On Thu, 2008-02-28 at 12:59 -0800, Craig Latta wrote:
Hi--
For what it's worth, the Center for Contemporary Research in Music
and Acoustics at Stanford University (CCRMA) offers packages to make RedHat and Fedora Core Linux suitable for very-low-latency multimedia use[1]. I've seen demos of it and it works.
-C
And also for Ubuntu there's:
sudo apt-get install linux-rt
which I'm testing today.
- Robert
On Thu, 2008-02-28 at 14:51 -0800, Robert F. Scheer wrote:
On Thu, 2008-02-28 at 12:59 -0800, Craig Latta wrote:
Hi--
For what it's worth, the Center for Contemporary Research in Music
and Acoustics at Stanford University (CCRMA) offers packages to make RedHat and Fedora Core Linux suitable for very-low-latency multimedia use[1]. I've seen demos of it and it works.
-C
And also for Ubuntu there's:
sudo apt-get install linux-rt
which I'm testing today.
- Robert
I did a new install of ubuntu and squeak and compared linux-rt with the standard kernel.
The delay bag test results were so poor on the -rt kernel that there's no need to trouble with posting them from the test computer. Half the delays were 4ms. The rest were basically worse. Some up to 45ms.
The stock kernel was >98% at 1ms and the rest up to 16ms.
- Robert
On 2008 February 28, Andreas Raab wrote:
Robert F. Scheer wrote:
Is this behavior well-known and understood or is there something wrong with my install?
This is a very well known issue. Different operating systems have very different minimal timer resolutions. Generally speaking, on Windows and Mac OS the timer resolution is very close to 1ms whereas most Linux kernels have *awful* timer resolutions. I have been told that you can recompile your kernel to fix it but I'm not sure how. The classic benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1. bag := Bag new. 1000 timesRepeat:[bag add: [delay wait] timeToRun]. bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means that 94.1% of the delays are true 1msec delays.
as a comparison, following is squeak 3.9-8 on SuSE 10.3 (2.6.24 kernel):
[1151]a SortedCollection(530->44 305->1 34->43 21->2 17->45 11->8 11->41 10->48 10->3 9->42 7->5 6->52 6->4 5->40 2->10 2->11 2->12 2->47 1->7 1->53 1->828 1->17 1->19 1->26 1->31 1->32 1->36 1->955)
Cheers,
- Andreas
On Sun, 2008-03-02 at 17:48 +0000, Milan Zimmermann wrote:
On 2008 February 28, Andreas Raab wrote:
Robert F. Scheer wrote:
Is this behavior well-known and understood or is there something wrong with my install?
This is a very well known issue. Different operating systems have very different minimal timer resolutions. Generally speaking, on Windows and Mac OS the timer resolution is very close to 1ms whereas most Linux kernels have *awful* timer resolutions. I have been told that you can recompile your kernel to fix it but I'm not sure how. The classic benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1. bag := Bag new. 1000 timesRepeat:[bag add: [delay wait] timeToRun]. bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means that 94.1% of the delays are true 1msec delays.
as a comparison, following is squeak 3.9-8 on SuSE 10.3 (2.6.24 kernel):
[1151]a SortedCollection(530->44 305->1 34->43 21->2 17->45 11->8 11->41 10->48 10->3 9->42 7->5 6->52 6->4 5->40 2->10 2->11 2->12 2->47 1->7 1->53 1->828 1->17 1->19 1->26 1->31 1->32 1->36 1->955)
I found results like this during my testing on Ubuntu (2.6.22 kernel) on one machine that had the "wrong" version of VM installed. You may find that either the VM rpm (deb in my case) from squeak.org or from your SuSe repositories give better results.
Also, after installing the linux-rt ("realtime") kernel from Ubuntu repositories, the delay bag performance was horrible, as mentioned earlier, but not in the same league of hurt as the results you've just posted.
- Robert
Cheers,
- Andreas
On Mon, Mar 3, 2008 at 2:01 PM, Robert F. Scheer rfscheer@speakeasy.net wrote:
Also, after installing the linux-rt ("realtime") kernel from Ubuntu repositories, the delay bag performance was horrible, as mentioned earlier, but not in the same league of hurt as the results you've just posted.
I can't tell if there's just the one real-time Linux which has multiple names or if they're separate projects; I'm seeing linux-rt, Linux/RT, rtlinux, RT-Linux, ...
Anyway, if they're all the same thing, then you're not using any of the real-time features:
http://www.faqs.org/docs/Linux-HOWTO/RTLinux-HOWTO.html
In order to get real-time performance, it sounds like you need to write your real-time code as a kernel module, and the rest of your application (the parts that don't need to be real-time) would run in user-land and communicate using a real-time FIFO character device.
Also, by real-time, they really do mean real-time: "Worst case interrupt latency on a 486/33Mhz PC measures well under 30 microseconds, close to the hardware limit." (ref: http://www.linuxdevices.com/articles/AT3694406595.html, assuming it's the same RT-Linux).
Gulik.
On Mon, 2008-03-03 at 13:51 +1300, Michael van der Gulik wrote:
On Mon, Mar 3, 2008 at 2:01 PM, Robert F. Scheer rfscheer@speakeasy.net wrote: Also, after installing the linux-rt ("realtime") kernel from Ubuntu repositories, the delay bag performance was horrible, as mentioned earlier, but not in the same league of hurt as the results you've just posted.
I can't tell if there's just the one real-time Linux which has multiple names or if they're separate projects; I'm seeing linux-rt, Linux/RT, rtlinux, RT-Linux, ...
The version in the Ubuntu repository is really a low-latency kernel based on work by Thomas Gleixner and Ingo Molnar. It is basically the standard Ubuntu kernel with their patch tailored for some Ubuntu differences.
It is intended to support automation, robotics, telco and multimedia authoring for example.
Supposedly, it adds support for high resolution timers and full preemption. (I haven't had time to get into what that really means or requires, sorry).
It is not a real "real-time" Linux kernel by any means. It was an easy experiment that I did but not a very serious one.
- Robert
Anyway, if they're all the same thing, then you're not using any of the real-time features:
http://www.faqs.org/docs/Linux-HOWTO/RTLinux-HOWTO.html
In order to get real-time performance, it sounds like you need to write your real-time code as a kernel module, and the rest of your application (the parts that don't need to be real-time) would run in user-land and communicate using a real-time FIFO character device.
Also, by real-time, they really do mean real-time: "Worst case interrupt latency on a 486/33Mhz PC measures well under 30 microseconds, close to the hardware limit." (ref: http://www.linuxdevices.com/articles/AT3694406595.html, assuming it's the same RT-Linux).
Gulik.
-- http://people.squeakfoundation.org/person/mikevdg http://gulik.pbwiki.com/
On Mon, Mar 3, 2008 at 4:01 PM, Robert F. Scheer rfscheer@speakeasy.net wrote:
On Mon, 2008-03-03 at 13:51 +1300, Michael van der Gulik wrote:
On Mon, Mar 3, 2008 at 2:01 PM, Robert F. Scheer rfscheer@speakeasy.net wrote: Also, after installing the linux-rt ("realtime") kernel from Ubuntu repositories, the delay bag performance was horrible, as mentioned earlier, but not in the same league of hurt as the results you've just posted.
I can't tell if there's just the one real-time Linux which has multiple names or if they're separate projects; I'm seeing linux-rt, Linux/RT, rtlinux, RT-Linux, ...
The version in the Ubuntu repository is really a low-latency kernel based on work by Thomas Gleixner and Ingo Molnar. It is basically the standard Ubuntu kernel with their patch tailored for some Ubuntu differences.
It is intended to support automation, robotics, telco and multimedia authoring for example.
Supposedly, it adds support for high resolution timers and full preemption. (I haven't had time to get into what that really means or requires, sorry).
It is not a real "real-time" Linux kernel by any means. It was an easy experiment that I did but not a very serious one.
Do the numbers improve if you boost the Squeak process's priority significantly (i.e. "sudo nice -n-10 squeak")?
Gulik.
squeak-dev@lists.squeakfoundation.org