There is a bug somewhere. Possibly I have found the origin, see below.
The new VM2.8 for Linux (Tims port) eats almost all of the processor cycles; typical values for a running VM2.8 Squeak *without* any computations are: 3189 sr 16 0 25236 24M 3832 R 0 99.0 15.8 1:04 squeak "VM2.8" and: 3186 sr 19 0 25208 24M 3844 R 0 8.1 15.8 0:16 _orig_squeak "VM2.7" for the VM2.7, both with same image #2345.
Is anybody able to confirm this observation?
Where could this processor cycles diminish? How to dig in deeper?
Morphic:
Pressing Alt-. leads to
MorphicEvent class>>new HandMorph>>processEvents [] in PasteUpMorph>>doOneCycleNow Array(SequenceableCollection)>>do: PasteUpMorph>>handsDo: PasteUpMorph>>doOneCycleNow PasteUpMorph>>doOneCycle [] in Project>>spawnNewProcess [] in BlockContext>>newProcess
in the debugger.
Increasing PasteUpMorph>>MinCycleLapse doesn't change the situation.
Digging deeper:
The idle process calls ProcessorScheduler>>relinquishProcessorForMicroseconds:, which itself leads to a call of
sqXWindow.c line 1517/3563:
int ioRelinquishProcessorForMicroseconds(int microSeconds) { /* sleep in select() for immediate response to socket i/o */ #ifdef HEADLESS if ( socketPollFunction ) { socketPollFunction(microSeconds,0);} /* aioPollForIO(microSeconds, 0); */ #else if ( socketPollFunction ) { socketPollFunction(microSeconds,stXfd);} /* aioPollForIO(microSeconds, stXfd); */ #endif return microSeconds; }
There is a socketPollFunction, which has to be set by setSocketPollFunction( int spf), because it is initialized to 0; grep'ing for setSocketPollFunction() reveals:
sr@Klaus:~/Squeak/2.8/src > grep setSocketPollFunction *.c *.h ../interp.c sqXWindow.c:void setSocketPollFunction( int spf) {
. It won't be called! So ioRelinquishProcessorForMicroseconds() returns *very* fast and the idle process doesn't give processor cycles to the OS.
If these thoughts are correct, then I have found the bug!
Stephan
In message 395A8532.6272A67E@evolgo.de you wrote:
There is a bug somewhere. Possibly I have found the origin, see below.
[snip]
There is a socketPollFunction, which has to be set by setSocketPollFunction( int spf), because it is initialized to 0; grep'ing for setSocketPollFunction() reveals:
sr@Klaus:~/Squeak/2.8/src > grep setSocketPollFunction *.c *.h ../interp.c sqXWindow.c:void setSocketPollFunction( int spf) {
. It won't be called! So ioRelinquishProcessorForMicroseconds() returns *very* fast and the idle process doesn't give processor cycles to the OS.
Well, sorta. The setSocketPollFunction is called by the socket plugin (remember, you have to grep _all_ the sources) in its initialiseModule() code. So if you haven't done a socket call, then yes I guess you never go to sleep.
Hmm, anyone know how to handle something like this? Is there a sleep type of call that will do partial seconds? Seems kind of poor to require people to do a socket call in order to sleep!
tim
Tim Rowledge wrote:
In message 395A8532.6272A67E@evolgo.de you wrote:
There is a bug somewhere. Possibly I have found the origin, see below.
[snip]
There is a socketPollFunction, which has to be set by setSocketPollFunction( int spf), because it is initialized to 0; grep'ing for setSocketPollFunction() reveals:
sr@Klaus:~/Squeak/2.8/src > grep setSocketPollFunction *.c *.h ../interp.c sqXWindow.c:void setSocketPollFunction( int spf) {
. It won't be called! So ioRelinquishProcessorForMicroseconds() returns *very* fast and the idle process doesn't give processor cycles to the OS.
Well, sorta. The setSocketPollFunction is called by the socket plugin (remember, you have to grep _all_ the sources)
Ooops, sorry, I have missed this.
in its initialiseModule() code. So if you haven't done a socket call, then yes I guess you never go to sleep.
That's it.
Hmm, anyone know how to handle something like this? Is there a sleep type of call that will do partial seconds? Seems kind of poor to require people to do a socket call in order to sleep!
Solution:
Just evaluate NetNameResolver resolverError (shouldn't do too much ;-) ) and the module will be initialized: initialiseModule() -> socketInit() -> setSocketPollFunction() .
This is a workaround!
Greetings,
Stephan
tim
-- Tim Rowledge, tim@sumeru.stanford.edu, http://sumeru.stanford.edu/tim Useful Latin Phrases:- Ventis secundis, tene cursum. = Go with the flow.
Below there is described a better solution for sleeping parts of seconds in the idle process.
I wrote:
Tim Rowledge wrote:
In message 395A8532.6272A67E@evolgo.de you wrote:
There is a bug somewhere. Possibly I have found the origin, see below.
[snip]
There is a socketPollFunction, which has to be set by setSocketPollFunction( int spf), because it is initialized to 0; grep'ing for setSocketPollFunction() reveals:
sr@Klaus:~/Squeak/2.8/src > grep setSocketPollFunction *.c *.h ../interp.c sqXWindow.c:void setSocketPollFunction( int spf) {
. It won't be called! So ioRelinquishProcessorForMicroseconds() returns *very* fast and the idle process doesn't give processor cycles to the OS.
Well, sorta. The setSocketPollFunction is called by the socket plugin (remember, you have to grep _all_ the sources)
Ooops, sorry, I have missed this.
in its initialiseModule() code. So if you haven't done a socket call, then yes I guess you never go to sleep.
That's it.
Hmm, anyone know how to handle something like this? Is there a sleep type of call that will do partial seconds? Seems kind of poor to require people to do a socket call in order to sleep!
Solution:
Just evaluate NetNameResolver resolverError (shouldn't do too much ;-) ) and the module will be initialized: initialiseModule() -> socketInit() -> setSocketPollFunction() .
This is a workaround!
A better solution is desribed in the following.
This C-function allows sleeping partial seconds:
NANOSLEEP(2) Linux Programmer's Manual NANOSLEEP(2)
NAME nanosleep - pause execution for a specified time
SYNOPSIS #include <time.h>
int nanosleep(const struct timespec *req, struct timespec *rem);
DESCRIPTION nanosleep delays the execution of the program for at least the time specified in *req. The function can return ear lier if a signal has been delivered to the process. In this case, it returns -1, sets errno to EINTR, and writes the remaining time into the structure pointed to by rem unless rem is NULL. The value of *rem can then be used to call nanosleep again and complete the specified pause.
The structure timespec is used to specify intervals of time with nanosecond precision. It is specified in <time.h> and has the form
struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ };
The value of the nanoseconds field must be in the range 0 to 999 999 999.
Compared to sleep(3) and usleep(3), nanosleep has the advantage of not affecting any signals, it is standardized by POSIX, it provides higher timing resolution, and it allows to continue a sleep that has been interrupted by a signal more easily.
...
BUGS The current implementation of nanosleep is based on the normal kernel timer mechanism, which has a resolution of
Linux 1.3.85 1996-04-10 1
NANOSLEEP(2) Linux Programmer's Manual NANOSLEEP(2)
1/HZ s (i.e, 10 ms on Linux/i386 and 1 ms on Linux/Alpha). Therefore, nanosleep pauses always for at least the speci fied time, however it can take up to 10 ms longer than specified until the process becomes runnable again. For the same reason, the value returned in case of a delivered signal in *rem is usually rounded to the next larger mul tiple of 1/HZ s. ...
Probably a 10 ms resolution is sufficient.
sqXWindow.c ioRelinquishProcessorForMicroseconds() could be changed from
int ioRelinquishProcessorForMicroseconds(int microSeconds) { /* sleep in select() for immediate response to socket i/o */ #ifdef HEADLESS if ( socketPollFunction ) { socketPollFunction(microSeconds,0);} /* aioPollForIO(microSeconds, 0); */ #else if ( socketPollFunction ) { socketPollFunction(microSeconds,stXfd);} /* aioPollForIO(microSeconds, stXfd); */ #endif return microSeconds; }
to
int ioRelinquishProcessorForMicroseconds(int microSeconds) { if ( socketPollFunction ) { /* sleep in select() for immediate response to socket i/o */ #ifdef HEADLESS socketPollFunction(microSeconds,0); /* aioPollForIO(microSeconds, 0); */ #else socketPollFunction(microSeconds,stXfd); /* aioPollForIO(microSeconds, stXfd); */ #endif } else { struct timespec sleepTime, reminderTime; sleepTime.tv_sec = microSeconds / 1000000; sleepTime.tv_nsec = microSeconds % 1000000 * 1000; nanosleep(&sleepTime, &reminderTime); } return microSeconds; "BTW: What's the sense of this return here? [sr]" }
Stephan
Greetings,
Stephan
tim
-- Tim Rowledge, tim@sumeru.stanford.edu, http://sumeru.stanford.edu/tim Useful Latin Phrases:- Ventis secundis, tene cursum. = Go with the flow.
-- Stephan Rudlof (sr@evolgo.de) "Genius doesn't work on an assembly line basis. You can't simply say, 'Today I will be brilliant.'" -- Kirk, "The Ultimate Computer", stardate 4731.3
squeak-dev@lists.squeakfoundation.org