Santa hath come early this year! This is a double-win -- because we can not only interrupt again but performance should be better too. This was for Igors attempt to improve the finalization mechanism, ironically for better performance back in 2010 I think -- and in which I was very interested because of how the hyper-activity of the finalization process was causing half of the processing time to be spent spinning through the weak references.
Not creating garbage will help a lot, even if it still seems like overkill to be finalizing every single weak collection on every single incremental GC -- I ran with a 10 second delay at the end of the whileTrue loop and noticed a noticeable gain in performance.. Unfortunately there are a few processes which rely on the results of GC..
Can't wait to try this out, thanks a lot Dave!
On Thu, Dec 22, 2011 at 3:24 PM, David T. Lewis lewis@mail.msen.com wrote:
On Fri, Dec 16, 2011 at 08:00:03AM +0100, Andreas Raab wrote:
On 12/16/2011 3:33, Levente Uzonyi wrote:
On Thu, 15 Dec 2011, Christopher Oliver wrote:
On Thu, 15 Dec 2011 11:35:55 +0100 I added a tty output debug to MorphicProject>>interruptName:preemptedProcess:, and I found that Processor>>preemptedProcess occasionally answers the system weak array finalization process. Yikes! This isn't what we want to debug at all. Are we being adequately clever in determining which process to debug?
I'm pretty sure that the currently running process is interrupted. After GC (which happens often during calculations with LargeIntegers) this is likely to be the finalization process.
Correct. To make matters worse, when an interrupt is signaled in the midst of GC, the signal will be delivered after the GC cycle completes, therefore almost guaranteeing that the interrupted process will be the finalization process.
And so the determination of the process to be interrupted is moderately stupid. What we'd really need to do is to start a slightly leaner version of CPUWatcher, i.e., instead of blindly interrupting whatever process is active, start sampling the running processes and after a short while (100-500 ms) decide which process to kick[*]. Plus, after that ensure that the UI is actually responsive so that the user can interact with the system and if not, keep kicking processes unless the system becomes interactive again. Alas, not a trivial task to be solved.
[*] A more radical version would suspend *all* user processes and let the user decide which of the suspended processes to inspect. This might have some interesting side effects though...
I think I found the underlying cause of all this grief, which in fact has nothing to do with the user interrupt handler. The problem is that the weak finalization process is very busy due to thrashing between the VM and the image. The VM notifies the image when weak references need to be cleaned up, and the weak finalization process responds by creating new weak references for the VM to clean up, etc etc etc ...
A fix is posted to the inbox in Collections-dtl.466
As Andreas observes, creating a smarter user interrupt handler is not at all trivial. But creating a smarter weak finalization process is really easy :) The solution was to move the check for VM support of new finalization out of the finalization process, and perform the check once at image startUp time.
With that change in place, the following may all be interrupted in the expected way:
"[true] whileTrue" "[[true] whileTrue] forkAt: Processor userSchedulingPriority + 1" "Smalltalk createStackOverflow" "[Smalltalk createStackOverflow] forkAt: Processor userSchedulingPriority + 1"
Just for the record, this problem was a whole lot harder to figure out than it was to explain ;-)
Dave