AbtTimedWait versus Delay

287 views
Skip to first unread message

Julian Ford

unread,
Jul 2, 2020, 11:36:53 AM7/2/20
to VA Smalltalk
Hello all...

A while back, I saw a post from Bob which mentioned AbtTimedWait, and how it offered
a reliable delay, without pinning the CPU.


There are a few instances in my software, where I need to use a delay of some kind,
and I have been using Delay.

One example, is to start a repeating procedure on a specified interval.
For this, I would fork a Process, then use a delay, followed by the appropriate code.
Yes, there are also checks to ensure the procedure is still enabled, and such...but at its
base level, it is mainly wait for x seconds, do the thing, and repeat.

I have never noticed anything untoward, by using (Delay forMilliseconds: x) wait,
but I like the idea of the AbtTimedWait minimizing CPU cycles.

The reason I am asking about this, is that there are no references to AbtTimedWait
in the VA base code (at least in what I have loaded), but numerous references to Delay.
Is that simply because AbtTimedWait is newer?
Or are there downsides to using it?

I appreciate any thoughts....

Best Regards,
Julian Ford

Mariano Martinez Peck

unread,
Jul 2, 2020, 11:55:42 AM7/2/20
to VA Smalltalk
Hi Julian,

I think "Delay >> wait" will block the current Smalltalk process.... So you may want to do that in a separate Smalltalk process...not the UI process. The AbtTimedWait does slightly different.  In Windows, for example, this is just calling the Windows API "Sleep" function on a separate thread so it won't block the main vm process (see AbtTimedWait >> #useThreadMethod).

Aside from that, AbtTimedWait allows a much higher resolution on the time to wait. The default 'Delay class >> interruptPeriod' is 100 ms. So if you need less than that, then you should use AbtTimedWait or else change Delay's  interruptPeriod.

Finally, you might want to look at SstCron (Load Sst Base feature) as it can manage long running tasks. For example, to print "Fire!" to the Transcript every 5 seconds, you would do:

SstCron default add: (
        SstCronEntry new
            workBlock: [Transcript show: 'Fire!'];
            seconds: 5).

Others may have additional thoughts. 

Best regards,


--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to va-smalltalk...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/va-smalltalk/f835ffd8-8eaf-4bad-a683-ae8354ee3231o%40googlegroups.com.


--
Mariano Martinez Peck
Software Engineer, Instantiations Inc.

Julian Ford

unread,
Jul 2, 2020, 12:37:29 PM7/2/20
to VA Smalltalk
Hi, Mariano.

Thank you for the reply!

I should have mentioned that I am using strictly a Windows environment.

Yes, I am always using the Delay in a separate Smalltalk Process.
The idea is along the lines of....

[
   [ self loopIsEnabled ] whileTrue: [
      AbtTimedWait forSeconds: 5.
      self loopIsEnabled ifTrue: [ self doSomethingInteresting ].
   ].
] fork.

The resolution is good to know about, but probably not as significant an issue.
I use this sort of thing, for example, to have the system check for incoming SMS Text messages
every 10 minutes, or to perform a database dump every hour.

I will definitely look up SstCron, as you suggested....sounds interesting!

I hope you and your family are safe and healthy!!!!!!

Regards,
Julian



To unsubscribe from this group and stop receiving emails from it, send an email to va-sma...@googlegroups.com.

Joachim Tuchel

unread,
Jul 3, 2020, 1:56:36 AM7/3/20
to VA Smalltalk
Julian,

Mariano brought up SstCron, which also was my first thought when I read your question. We've been using it in Kontolino! for years now to regularly log the health status of our servers, which can then easily be monitored by external tools. We also do some job scheduling for maintenance of our DB and such. It's rock solid and reliable and doesn't put a load burden onto our server images. Plus: it's just like cron, so if you are familiar with Cron jobs and the crontab file on linux, you know exactly how to use SstCron.

There is one caveat, however:
What it doesn't do is wait a certain amount of time after a job is done. It just starts off a new copy of it in defined intervals. So if you need to make sure the last run is finished before a new job starts, you have to implement something to keep the new/next job(s) from starting as long a s another one is still active. AFAIK, there is no built-in mechanism for such a thing in VAST (just like in Cron). So if your requirement is that some job may take 5 seconds or maybe sometimes 12 minutes and you want the next one to start exactly 2 minutes aftre the last one finished, SstCron is probably not your best friend.

Joachim
(still looking for Mirto rosso in my local stores)

Adriaan van Os

unread,
Jul 8, 2020, 3:58:22 PM7/8/20
to VA Smalltalk
I just observed 100% CPU usage with something like '[(Delay forSeconds: 5) wait] repeat' under Linux. Using AbtTimedWait works fine.

Cheers,
Adriaan.

Marten Feldtmann

unread,
Jul 8, 2020, 4:19:32 PM7/8/20
to va-sma...@googlegroups.com, Adriaan van Os
You are waiting in the Main-Execution (U) thread - this is called busy waiting.

Am 08.07.20 um 21:58 schrieb Adriaan van Os:
I just observed 100% CPU usage with something like '[(Delay forSeconds: 5) wait] repeat' under Linux. Using AbtTimedWait works fine.

Cheers,
Adriaan.
--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to va-smalltalk...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/va-smalltalk/c9f8c97c-7f5b-409f-85f6-3b76d457063do%40googlegroups.com.


Adriaan van Os

unread,
Jul 8, 2020, 4:33:33 PM7/8/20
to VA Smalltalk
I forgot to mention, this was with a headless runtime....

Esteban Maringolo

unread,
Jul 8, 2020, 4:57:18 PM7/8/20
to va-sma...@googlegroups.com
It's still the main thread. If you fork it you won't get that.

Esteban A. Maringolo
> --
> You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to va-smalltalk...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/va-smalltalk/0297df8a-a3bb-4d30-a4d5-fff4f8d4a443o%40googlegroups.com.

Adriaan van Os

unread,
Jul 8, 2020, 5:05:40 PM7/8/20
to VA Smalltalk
Ah, forget all I wrote. The actual code was missing the 'wait'.... :-s

Richard Sargent

unread,
Jul 8, 2020, 6:35:03 PM7/8/20
to VA Smalltalk
On Wednesday, July 8, 2020 at 2:05:40 PM UTC-7, Adriaan van Os wrote:
Ah, forget all I wrote. The actual code was missing the 'wait'.... :-s

I'm sorry. I laughed at that. (Knowing how many times I have done something similar!)

Adriaan van Os

unread,
Aug 23, 2021, 2:10:05 PM8/23/21
to VAST Community Forum
So... you shouldn't use Delay with a value less then 100ms. What will happen if you do it anyway?

I noticed that, for instance AbtEwHoverHelpManager>>#backgroundRunDelay is using a shorter delay and SciDispatcher>>#callLoopingRecvWith:with:with:with: potentially too. Does that mean those methods are a little bit broken?

The one in SciDispatcher also has an interesting feat: it does just a yield when the delay is shorter than 16ms. Would having a 'smart' delay that just yields for short delays be a good idea? And would that be useful for Delay and not so much for AbtTimedWait?

Any thoughts?

Cheers,
Adriaan.

Mariano Martinez Peck

unread,
Aug 24, 2021, 7:49:46 AM8/24/21
to VA Smalltalk
Hi Adriaan, 

On Mon, Aug 23, 2021 at 3:10 PM Adriaan van Os <adriaa...@gmail.com> wrote:
So... you shouldn't use Delay with a value less then 100ms. What will happen if you do it anyway?



What happens is that since the default 'Delay class >> interruptPeriod' is 100 ms, it could take more time than the one you specified. It all depends on when the Delay thread wakes up and executes. 

 
I noticed that, for instance AbtEwHoverHelpManager>>#backgroundRunDelay is using a shorter delay and SciDispatcher>>#callLoopingRecvWith:with:with:with: potentially too. Does that mean those methods are a little bit broken?



So...those methods are not "broken" per-se but actually there may be runs where the total wait time is bigger than specified. 

 
The one in SciDispatcher also has an interesting feat: it does just a yield when the delay is shorter than 16ms. Would having a 'smart' delay that just yields for short delays be a good idea? And would that be useful for Delay and not so much for AbtTimedWait?

Any thoughts?



I think that making sure that such a smart delay is worthwhile would require a lot of investigation, tests, benchmarks, etc etc. That condition of #yield for < 16ms in SciDispatcher is from 2001 so it's hard to be sure 100% of the exact reasons. We think it is like that because on Windows, 16ms is a special value because of how the windows scheduler integrates with interrupts. https://randomascii.wordpress.com/2020/10/04/windows-timer-resolution-the-great-rule-change/

Processor yield may only make sense as an approximation IF sampling of it is done (on something like image startup) so you have some idea of how many yields are required / 1ms.  And you would need a real-time timer to measure that.  Windows is not a real-time os and so this granularity of 16ms is, on average, what you can get down to.


Hope this helps, 



--

Mariano Martinez Peck

Senior Software Engineer

 mp...@instantiations.com
 @MartinezPeck
 /mariano-martinez-peck
 instantiations.com
TwitterLinkedInVAST Community ForumGitHubYouTubepub.dev

Adriaan van Os

unread,
Aug 24, 2021, 10:09:58 AM8/24/21
to VAST Community Forum
Hi Mariano,

Thanks for your answer. That is what we see indeed at places where we use Delay with less then 100ms: unexpected longer delays that even look like a hangups. We're looking at using AbtTimedWait for those.

As for the 'smart' delay, I'm not sure I was clear enough, but I didn't mean to have multiple yields for a single short delay. Just one yield as a very short delay. I understand that the threshold for doing a yield vs a real delay would have to be arbitrary.

Cheers,
Adriaan.

Mariano Martinez Peck

unread,
Aug 24, 2021, 10:23:32 AM8/24/21
to VA Smalltalk
On Tue, Aug 24, 2021 at 11:10 AM Adriaan van Os <adriaa...@gmail.com> wrote:
Hi Mariano,

Thanks for your answer. That is what we see indeed at places where we use Delay with less then 100ms: unexpected longer delays that even look like a hangups. We're looking at using AbtTimedWait for those.



Yes, I would use AbtTimedWait for those cases (and EsTimedWait in 10.x).

 
As for the 'smart' delay, I'm not sure I was clear enough, but I didn't mean to have multiple yields for a single short delay. Just one yield as a very short delay. I understand that the threshold for doing a yield vs a real delay would have to be arbitrary.



I understood your original question so you were clear :) . You can give it a try if you want, but you are correct that it would have to be an arbitrary threshold (which, for Windows, it seems a reasonable was 16 ms). I guess it's a matter of experimenting... certainly let us know if you find something interesting. 

Best, 


Louis LaBrunda

unread,
Aug 24, 2021, 11:31:39 AM8/24/21
to VAST Community Forum
Hi Everyone,

Delay is one of my favorite topics.  I studied it awhile ago, learned a lot and hopefully remember most of it.

First, it should be known that the 100 ms interval is NOT fixed and can be changed with:

Delay interruptPeriod: 16.

It is a private method but if you want a smaller interrupt period, it is probably worth the risk.

It is the value used to set the hardware timer interrupt.

My old tests showed that the smallest value that would result in short delays was 14 ms.  I haven't tested lately but I think 16 ms is about as low a one can go based upon Windows 10 changes see: https://randomascii.wordpress.com/2020/10/04/windows-timer-resolution-the-great-rule-change/ for more details.

I have looked at #EsTimedWait and I'm not fond of it because it uses an OS sleep, which doesn't let other Smalltalk forks run.  It just gives up the CPU to the OS.  If that is what you want, that's fine, you should just know that is what it is going to do.

All of that being said, I suggest that a change should be made to Delay>checkDelayedTasks.  This is the method that runs when the OS timer expires.  I'm not 100% sure of this next statement but I think it doesn't matter if another Smalltalk fork is running or not, if the OS will allow the program to run, it will give it the CPU and go there.  This is how the 100 ms delay keeps the GUI fork running and happy.

Delay>checkDelayedTasks checks the Smalltalk forks and will give control to the first one in its list that is ready to run.  If none are ready to run, the OS will be given the CPU for 100 ms.  This is what I think should be changed.  The fork at the top of the list may not be ready to run, because it delayed itself, but there may only be 50 ms left on that delay.  I think the code could easily be changed to do a little math and calculate how much longer that fork should be delayed and set the next OS timed interrupt to whatever is smaller, 100 ms or the time left for the next fork.

This change would automatically make Delays more accurate, not perfect but more accurate.  And unlike  #EsTimedWait, it keeps the Smalltalk code running if any of it is ready to run.

Delay has been around forever and Instantiations and some of us users may be reluctant to change code at this level.  But I can't see any program depending upon Delay not being very accurate.  I have a hard time coming up with a test that would show a problem with greater Delay accuracy.

For what it is worth, I think this is how Squeak works.

Lou

Seth Berman

unread,
Aug 24, 2021, 11:49:55 AM8/24/21
to VAST Community Forum
Hi Lou,

"I have looked at #EsTimedWait and I'm not fond of it because it uses an OS sleep, which doesn't let other Smalltalk forks run."
- I don't think this is correct.  Indeed, EsSleep on Windows will call the Windows Sleep() function which "Suspends the execution of the current thread until the time-out interval elapses."
  However, this is invoked via an asynchronous call...so that suspended thread is not the main Smalltalk vm thread, its a thread from the VM thread pool.
  That calling smalltalk process will block for the duration of the async call, but not other Smalltalk processes.
  Now, if you call that from the UI thread...then you're asking the UI process to block while the timer completes.  But this is a separate issue that has to do with the fact that your blocking the smalltalk process that is associated with processing windows events.

Delay interruptPeriod: 16.
You can do this, but you will need to pay more attention to overall cpu usage.  That will increase significantly since your interrupt periods are so low.
But if you don't care about that, then it certainly would work.

- Seth

Richard Sargent

unread,
Aug 24, 2021, 12:18:43 PM8/24/21
to VAST Community Forum
On Tuesday, August 24, 2021 at 8:31:39 AM UTC-7 L...@Keystone-Software.com wrote:
Hi Everyone,

Delay is one of my favorite topics.  I studied it awhile ago, learned a lot and hopefully remember most of it.

First, it should be known that the 100 ms interval is NOT fixed and can be changed with:

Delay interruptPeriod: 16.

It is a private method but if you want a smaller interrupt period, it is probably worth the risk.

It is the value used to set the hardware timer interrupt.

My old tests showed that the smallest value that would result in short delays was 14 ms.  I haven't tested lately but I think 16 ms is about as low a one can go based upon Windows 10 changes see: https://randomascii.wordpress.com/2020/10/04/windows-timer-resolution-the-great-rule-change/ for more details.

I did some timing tests on this, too, for GBS. I found that 10 ms gave the best results. Less than 10 ms showed no further improvement.
I don't understand why 10 would be better than 16, but it was. I suspect 16 ms increases the number of times your wait will have to wait one full interval.

Louis LaBrunda

unread,
Aug 24, 2021, 12:40:33 PM8/24/21
to VAST Community Forum
Hi Seth,

Thanks.  Okay, I should have looked a little closer at #EsTimedWait and its #useThreadMethod method.  What happens to the fork that the PlatformFunction was called.  Doesn't its process end up in the Delay list as not ready (or not in the list, I forget)?  I guess it will become ready when the PlatformFunction returns but will Delay be able to dispatch it right away or will it be waiting on the last 100 ms timer?

I agree with you about setting the interrupt period to less than 100 ms but developers shouldn't be setting short delays if they don't really want them and are willing to pay the price.  Changing the interrupt period gives them the short delays.

Now, I don't really like setting the interrupt period to less than 100 ms.  I have seldom found it useful and have changed code to get the value as a setting, just incase it might help.

I think my suggestion for changing the Delay avoids setting the interrupt period to less than 100 ms, when it isn't helpful.  The interrupt period will be 100 ms unless the developer has set delays that cause it to be shorter.  A 150 ms delay may only set it to 50 ms once.  I admit that it is hard to say how often this will help programs work better.  But with this change, can come close to getting the delay they intended and not a longer one for no reason.

Lou

Richard Sargent

unread,
Aug 24, 2021, 12:56:43 PM8/24/21
to VAST Community Forum
On Tuesday, August 24, 2021 at 9:40:33 AM UTC-7 L...@Keystone-Software.com wrote:
Hi Seth,

Thanks.  Okay, I should have looked a little closer at #EsTimedWait and its #useThreadMethod method.  What happens to the fork that the PlatformFunction was called.  Doesn't its process end up in the Delay list as not ready (or not in the list, I forget)?  I guess it will become ready when the PlatformFunction returns but will Delay be able to dispatch it right away or will it be waiting on the last 100 ms timer?

I agree with you about setting the interrupt period to less than 100 ms but developers shouldn't be setting short delays if they don't really want them and are willing to pay the price.  Changing the interrupt period gives them the short delays.

Now, I don't really like setting the interrupt period to less than 100 ms.  I have seldom found it useful and have changed code to get the value as a setting, just incase it might help.

Bear in mind, the code that uses 100 ms was written in the early 90s! I think may even have predated 60 MHz Pentiums. CPUs are now 50-100x faster than they were then. 100 ms was actually quite an aggressive interval back then.

Seth Berman

unread,
Aug 24, 2021, 1:20:24 PM8/24/21
to VAST Community Forum
Hi Richard,

This is true, but we noticed an impact on devices like RasPi which is why it was brought up.
There is a high-priority timer thread that is constantly running in the background that fires at Delay intervals and sends messages through the async queue.
So, as you approach 0 on the delay, you are hammering the async queue harder and harder.
But as I think is in the spirit of what you are saying....going from 100ms to 50ms is probably not really a big deal.  Its as you approach the lower bounds you may be inadvertently impacting
other parts of the program by keeping the async queue fuller.  This impact on Linux may be more noticeable than on Windows based on how the UI works between the 2.

- Seth

Richard Sargent

unread,
Aug 24, 2021, 8:14:18 PM8/24/21
to VAST Community Forum
On Tuesday, August 24, 2021 at 10:20:24 AM UTC-7 Seth Berman wrote:
Hi Richard,

This is true, but we noticed an impact on devices like RasPi which is why it was brought up.
There is a high-priority timer thread that is constantly running in the background that fires at Delay intervals and sends messages through the async queue.
So, as you approach 0 on the delay, you are hammering the async queue harder and harder.

Yes. Even under Windows, I noticed that values < 10 considerably increased the idle CPU load. I don't have the data, but I seem to recall that at 10 ms, I saw the idle load for VA running about 0.5-1.0% (on my machine) but running at 4-5% when lower than 10 ms.

One definitely needs to balance performance against other requirements when tuning the interrupt period.

But as I think is in the spirit of what you are saying....going from 100ms to 50ms is probably not really a big deal.  Its as you approach the lower bounds you may be inadvertently impacting
other parts of the program by keeping the async queue fuller.  This impact on Linux may be more noticeable than on Windows based on how the UI works between the 2.

I have no idea about the differences. Is it something you can easily summarize?

Louis LaBrunda

unread,
Aug 26, 2021, 10:15:53 AM8/26/21
to VAST Community Forum
Hi Seth,

In my last post I awkwardly asked a few questions about how #EsTimedWait and its #useThreadMethod method worked.  Let me try to do better.  The method, #useThreadMethod, uses a PlatformFunction to do an EsSleep and tell the OS to sleep.  As you said, the EsSleep is done in a separate thread, not the main thread that processes Smalltalk code, and therefore doesn't stop the processing of Smalltalk code as I feared.  When the sleep ends, the process that issued #useThreadMethod, can be set as ready or runnable.  Then one of two states can exist (let me know if these are wrong or if there are more).  1) some other process is running, if so, this is fine, the newly ready process will run based upon its priority.  2) The main Smalltalk processing thread is not running, waiting for the interval timer.  This may be okay if the thread that did the EsSleep, wakes up the main process thread.  If not, 100 ms can elapse before processing resumes.  So, how do things work when the sleeping thread (or any thread other than the main thread) restarts?

Lou

Seth Berman

unread,
Aug 26, 2021, 10:45:06 AM8/26/21
to VAST Community Forum
Hi Lou,

I kinda got lost after your point 2).
"The main Smalltalk processing thread".  I'm not sure what this means.  Do you mean the UI Process in Smalltalk or are you talking about the main native vm thread (the one all Smalltalk processes are multiplexed on)?

There is a native thread that is kicked off in the vm at startUp which just sits there and loops every 'InterruptPeriod' and then calls the Smalltalk DirectedMessage 'Delay class>>checkDelayedTasks' via posting it to the asynchronous queue.
After its successfully queued, it will be processed at the next vm interrupt point.  So this might be after a particular process performs a jump bytecode or some sort of transfer-of-control in the code stream.
Any smalltalk process can be blocked, but as long as someone is executing an instruction stream and then an interrupt point is reached...then delayed tasks will have an opportunity to run.

The EsTimedWait is far simpler.  It just takes advantage of the fact that we can make an asychronous call on a separate thread that only blocks the calling Smalltalk process AND their exists an OS function that allows us to put just the calling native thread to sleep (i.e. Sleep() on Win and nanosleep() on Linux).  There is not much more to it than that.

Hope that helps.

- Seth

Louis LaBrunda

unread,
Aug 26, 2021, 1:43:37 PM8/26/21
to VAST Community Forum
Hi Seth,

Sorry for not being clear.  I'm going to respond to your reply a little out of order.

The EsTimedWait is far simpler.  It just takes advantage of the fact that we can make an asychronous call on a separate thread that only blocks the calling Smalltalk process AND their exists an OS function that allows us to put just the calling native thread to sleep (i.e. Sleep() on Win and nanosleep() on Linux).  There is not much more to it than that.

I get the above, no problem.

I kinda got lost after your point 2).
"The main Smalltalk processing thread".  I'm not sure what this means.  Do you mean the UI Process in Smalltalk or are you talking about the main native vm thread (the one all Smalltalk processes are multiplexed on)?

My 1) and 2) are about the same thread thread that executes Smalltalk code, so your second guess, the main native VM thread.  My 1) says this thread is working on Smalltalk processes.  My 2) says the thread has no ready  Smalltalk processes to work on.  In that case, I'm guessing it gave the CPU up to the OS with some kind of sleep, that will end when the interval timer fires.  When the EsTimedWait comes back, the Smalltalk process that called it is now ready to run.  But it can't run if the main VM thread is sleeping.  Does something wake it up or do we just wait until the interval timer fires?

After reading this:

There is a native thread that is kicked off in the vm at startUp which just sits there and loops every 'InterruptPeriod' and then calls the Smalltalk DirectedMessage 'Delay class>>checkDelayedTasks' via posting it to the asynchronous queue.
After its successfully queued, it will be processed at the next vm interrupt point.  So this might be after a particular process performs a jump bytecode or some sort of transfer-of-control in the code stream.
Any smalltalk process can be blocked, but as long as someone is executing an instruction stream and then an interrupt point is reached...then delayed tasks will have an opportunity to run.

I'm thinking that there may be two threads.  One that does nothing but loop setting and waiting for the interval timer and one that works on the Smalltalk processes.  As far as my above question goes, I don't think it matters if there are one or two threads.  The thread that works on the Smalltalk processes, has to sleep sometime or a lot of CPU is used.  And if it sleeps, something needs to wake it up when the thread that slept for the EsTimedWait wakes up.

Lou

Seth Berman

unread,
Aug 26, 2021, 2:11:57 PM8/26/21
to VAST Community Forum
Hi Lou,

Indeed the vm does go to sleep:
@see EmSystemConfiguration>>sleep.

And Indeed it does wakeup:
Depending on the GUI context or not, and the OS...there are several different mechanisms for how that sleep/wake is done
from windows api calls like WaitMessage() when in a UI context on Windows, an OS semaphore with Windows messages like WaitForSingleObject/ReleaseSemaphore for non-gui, EsPthread_sem_wait/EsPthread_sem_post for *nix and
wakeup after posting to the async queue (which the delay timer thread will do when it posts a directed message to the async queue to call #checkDelayedTasks).

Its a pretty complex orchestration for me to describe in full (as I don't carry those details around in my head), but I think I got that mostly right:) 

Hope that answers your question better.

- Seth

Louis LaBrunda

unread,
Aug 28, 2021, 9:48:22 AM8/28/21
to VAST Community Forum
HI Seth,

Thanks for you last post and answers.  It confirms how I thought things worked.  When the thread that did the sleep for EsTimedWait wakes up, does it wake up the thread that processes Smalltalk code if it is sleeping?

I'm guessing there isn't a check to see if the tread that is preforming platform functions did an OS call for a sleep (it could).  So, do threads that preform platform functions wake up the thread that processes Smalltalk code if it is sleeping?  This could be because it could be assumed that the platform functions was important and we would want to get back to doing Smalltalk code right away.  Or, it could just wait until the next interval timer fires.  If that is the case, EsTimedWaits might take longer than expected.

Enough for now, later I will ask about my idea about my proposed change to Delay's use of the interval timer.
Lou

thomas....@natural-software.eu

unread,
Sep 9, 2021, 11:17:44 AM9/9/21
to VAST Community Forum
Hi

I migrated some of our "(Delay forSeconds: xxx) wait" calls now to AbtTimedWait. There is a slight difference however between these 2 methods.

AbtTimedWait only accepts integers. For example, the following code crashes with an invalid argument

[
AbtTimedWait forSeconds: 3.1.
] fork.

I would suggest to change the forSeconds: and forMilliseconds: methods in AbtTimedWait to accept whatever number is being sent to it. So e.g.

EsTimedWait >> forSeconds:
forSeconds: anInteger
"Public-Cause the current process to wait for an integer
  number of seconds; do not return until the interval is up."

^ self new
waitInterval: (anInteger * 1000) asInteger;
wait.


--Thomas

 

Mariano Martinez Peck

unread,
Sep 10, 2021, 11:42:40 AM9/10/21
to VA Smalltalk
Thank you Thomas for the suggestion. We will consider this and come back to you. 



--
You received this message because you are subscribed to the Google Groups "VAST Community Forum" group.

To unsubscribe from this group and stop receiving emails from it, send an email to va-smalltalk...@googlegroups.com.

Mariano Martinez Peck

unread,
Sep 14, 2021, 2:48:28 PM9/14/21
to VA Smalltalk
Hi Thomas,

I opened dev case "68273: EsTimedWait >> #forSeconds: and #forMilliseconds: should also allow non integers numbers" and this will be integrated in the next release of the product. 

Below are the changes. 

Cheers,


forSeconds: aNumber

"Cause the current process to wait for a 

number of seconds; do not return until the interval is up.

Arguments:

aNumber - <Number> number of seconds to wait"


^self forMilliseconds: (aNumber * 1000)


---


forMilliseconds: aNumber

"Cause the current process to wait for a

number of milliseconds; do not return until the interval is up.

Arguments:

aNumber - <Number> number of milliseconds to wait"


^self new

waitInterval: aNumber asInteger;

wait





thomas....@natural-software.eu

unread,
Sep 14, 2021, 2:58:19 PM9/14/21
to VAST Community Forum
Hi Mariano

GREAT!

--Thomas

thomas....@natural-software.eu

unread,
Jun 6, 2022, 12:55:28 PM6/6/22
to VAST Community Forum
Hi All

Just got some weird behaviour from AbtTimedWait which I don't quite understand. Somehow AbtTimedWait does not really like it when the underlying Smalltalk process gets terminated.

Also if the same block creates another AbtTimedWait object, the waiting time seems to accumulate.

Little example

| waitingProces aBlock |
Transcript show: Time now printString; cr.
aBlock := [
    AbtTimedWait forSeconds: 5.
    Transcript show: Time now printString; cr.
    Transcript show: 'DONE';cr.
].
waitingProcess := aBlock fork.
[
    AbtTimedWait forSeconds: 1.
    waitingProcess terminate.
    Transcript show: 'Killed it';cr.
    Transcript show: Time now printString; cr.
    waitingProcess := aBlock fork.
] fork.


This results in the following transcript output

18:50:09
Killed it
18:50:10
18:50:19
DONE

The script started at 18:50:09 creating an AbtWait for 5 seconds. The process got killed at 18:50:10. Immediately thereafter a new process from the block with the AbtTimedWait gets started for 5 seconds. However the times does not trigger at 18:50:15 (as expected) but at 18:50:19 (10 seconds after the first execution of the block).

If I do this even more often, the Wait time gets added to the previous timer for each step.

This , of course, resulted in some really strange behaviour

--Thomas

Louis LaBrunda

unread,
Jun 6, 2022, 2:37:00 PM6/6/22
to VAST Community Forum
Hi Thomas,

AbtTimedWait uses a platform function (EsSleep).  It looks to me like when you terminate the Smalltalk process that contains the platform function and is waiting, you really don't terminate the wait, just the Smalltalk process.  The OS still comes back to the VM after the wait with an interrupt.  The VM no-longer has a process to return to but decides to be nice and not do anything bad to the program.  It just ignores the interrupt (the return from EsSleep).

When you do more AbtTimedWaits (EsSleep calls) they stack up, possibly because the VM makes them from the same OS thread (I'm not sure of that).

Can you tell us a little more about what you are trying to accomplish?

Lou

Wayne Johnston

unread,
Jun 6, 2022, 2:40:17 PM6/6/22
to VAST Community Forum
Interesting, different results than with a Delay.

Marcus Wagner

unread,
Jun 6, 2022, 3:05:22 PM6/6/22
to VAST Community Forum
Hi Thomas,
I cross checked your script with ancient VAST 5.0 (under Windows NT 4.0 ~~ 1998 in a VM before the millenium) here is the result

20:49:34
Killed it
20:49:35
20:49:40
DONE
I assume this is the behaviour you expected.

And I checked it with the older VAST version 8.6 under Windows 8.1 (before implementation of clock / async enhancements)
20:41:59
Killed it
20:42:00
20:42:09
DONE
It seems to me that the different behavior crept silently in many years ago and many versions before / and there is the possibility of a OS dependency contributing to that.
-
Marcus

Seth Berman

unread,
Jun 6, 2022, 3:19:05 PM6/6/22
to VAST Community Forum
These are the results on the latest release.
And it seems like this is correct?

3:14:44 PM
Killed it
3:14:45 PM
3:14:50 PM
DONE

Louis LaBrunda

unread,
Jun 6, 2022, 4:21:57 PM6/6/22
to VAST Community Forum
Hi Guys,

I tried three different versions of VA Smalltalk with at least two different VMs (see below).  The oldest two, show the waits stacked.  The latest version 11, works as if the wait was killed.  The V8.6.1 VM is I think the old X86 assembly language VM.  The V9.2.2 and V11.0 are the newer LLVM VMs (Seth can tell us for sure).  I expect the two older VMs work the way I theorized, with one thread issuing the EsSleep and the latest VM using more than one thread, each issuing a Sleep.  Seth or someone who knows the VM code or can look at it, will have to tell us.

Lou


VA Smalltalk V8.6.1; Image: 8.6.3 [378]
VM Timestamp: 4.0,(NC) 7/24/2014 (86)

4:02:51 PM
Killed it
4:02:52 PM
4:03:01 PM
DONE

4:03:34 PM
Killed it
4:03:35 PM
4:03:44 PM
DONE


VA Smalltalk V9.2.2 (32-bit); Image: 9.2.2 [2]
VM Timestamp: 4.0, 05/15/20 (102)

4:01:24 PM
Killed it
4:01:25 PM
4:01:34 PM
DONE

4:01:56 PM
Killed it
4:01:57 PM
4:02:06 PM
DONE


VAST Platform V11.0 (32-bit); Image: 11.0 [510]
VM Timestamp: 4.0, 04/26/22 (115)

4:06:43 PM
Killed it
4:06:44 PM
4:06:49 PM
DONE

4:06:54 PM
Killed it
4:06:55 PM
4:07:00 PM
DONE

thomas....@natural-software.eu

unread,
Jun 8, 2022, 4:05:57 AM6/8/22
to VAST Community Forum
Hi @all

Thanks for all the tests.

I noticed the effect an older version of our system still using VA 9.2.2 (should have mentioned it in the original post).

And yes - with the latest VA version, the system works as it should. So, I believe this issue is fixed in the newer versions of VA.
Reply all
Reply to author
Forward
0 new messages