Hi Holger,
The Morphic main loop empties the event queue (mouse & keyboard) in each cycle. It also checks for drawing requests and stepping. If that processing goes too fast, it tries to free CPU time via a delay (so that the idle process can run if no other).
No, it does not make sense to get rid of that pause/delay/tick. ;-) The system is NOT event-based at that lower level. It is just polling/looping. A single UI process, which sleeps occasionally. By design.
Note that if you want to run that in the cloud, just avoid busy morphs and Morphic should use very little CPU resources.
Best,
Marcel
Am 29.08.2017 23:29:21 schrieb Holger Freyther <holger(a)freyther.de>:
Hi,
I have done some early prototype for the Unix VM end of 2015(?) and I have improved and repeated these for MacOS now and the thread based heartbeat (now that it is the universal default). I won't make it to ESUG this year but this might be something to play with?
The motivations is simple: Polling increases the CPU usage which will reduce your battery life, takes away resources from other processes (e.g. more Pharo images) or these days increases your cloud computing bill. On top of that it might increase network latency (time from socket becoming readable to the time the semaphore is signaled).
To complete the work we have work inside the Image and the VM and some of it is on the way and others might need more discussion.
The idle process:
ProcessorScheduler>># idleProcess
"A default background process which is invisible."
[true] whileTrue:
[self relinquishProcessorForMicroseconds: 1000]
Let's please yield the CPU for more than a 1ms. Unless I am missing something an expired Delay or network IO would make us wake up earlier anyway?
The delay scheduler:
The VM supports that when the next wake-up time is set to 0, the VM can sleep indefinitely. There is a pending patch to sleep "0" in our Delay scheduler. Currently we force a wake-up earlier than that. I think we should trust the VM to do wake us up even if it is a second away.
Morphic UI:
I don't understand the WorldState>>#interCyclePause but then I never looked at Morphic. Do we really need to poll like that? Under which circumstances does the world update? We get an event (where we have the event semaphore), we get some I/O (where we have a semaphore) or we have a timeout (where we sleep on a semaphore). Did anyone ever look at removing the tick?
VM I/O:
Currently we receive a SIGIO but from what I can see (and I still need to write a benchmark) the processing might be delayed 20ms? My hack removes the usage of nextPollUsecs and instead checks a variable that is set by the SIGIO handler. Besides missing memory barriers this should work(tm).
The biggest issue seems that for macos/ios the input is driven by polling. E.g. some wheel events seem to require to pump the event queue. Is this something we could trigger from the image in the future? I had hoped to get a fd to a machport we could get SIGIO for.. but that doesn't seem to exist. I have hacked out the honoring of the relinquish delay, added the polling into a iOS specific routine and thanks to the Morphic Delay we bump the event loop frequently enough.
VM heartbeat thread:
The process keeps ticking even if the VM doesn't run. E.g. sleeps and waits for an event. There is a cost in deciding when to halt the thread so there must be a cut-off for which delays we bother to disable the heartbeat thread. I think the current code would allow the hearbeat to drift so the new code might just make it a bit worse.
Where are we now?
I have pushed my changes to https://github.com/zecke/opensmalltalk-vm/tree/mac-use-less-cpu and would be happy to have people look at it, look at the memory synchronization, maybe run to see if they notice extra delays or such?
I started the same image with the plain-vm and my hacked one and let it run for about 20min. The output is coming from top.
COMMAND %CPU TIME
Pharo 4.3 00:48.49
Pharo 0.8 00:10.20
Looking for comments and feedback.
regards
holger
Chris Muller uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-cmm.1113.mcz
==================== Summary ====================
Name: Kernel-cmm.1113
Author: cmm
Time: 31 August 2017, 1:55:06.158647 pm
UUID: 05c89229-0279-4842-b0d0-dacb2713a4b6
Ancestors: Kernel-tbn.1112
Provide #pinned: so clients don't have to write duplicate code (e.g., "myCondition ifTrue: [myObject pin] ifFalse: [myObject unpin]") while allowing frameworks to hook #pinned: if necessary (without overriding a primitive).
=============== Diff against Kernel-tbn.1112 ===============
Item was changed:
----- Method: Object>>pin (in category 'pinning') -----
pin
+ "Ensure the receiver is pinned and answer whether it was pinned."
+ ^ self pinned: true!
- "The VM's garbage collector routinely moves objects as it reclaims and compacts
- memory. But it can also pin an object so that it will not be moved, which can make
- it easier to pass objects out through the FFI. Objects are unpinnned when created.
- This method ensures an object is pinned, and answers whether it was already pinned."
- ^self setPinned: true!
Item was added:
+ ----- Method: Object>>pinned: (in category 'pinning') -----
+ pinned: aBoolean
+ "The VM's garbage collector routinely moves objects as it reclaims and compacts memory. But it can also pin an object so that it will not be moved, which can make it easier to pass objects out through the FFI. Objects are unpinnned when created.
+ Answer whether the receiver was pinned."
+ ^ self setPinned: aBoolean!
Item was changed:
----- Method: Object>>setPinned: (in category 'private') -----
setPinned: aBoolean
+ "Primitive which pins or unpins the receiver and answers whether it was already pinned."
- "The VM's garbage collector routinely moves objects as it reclaims and compacts
- memory. But it can also pin an object so that it will not be moved, which can make
- it easier to pass objects out through the FFI. Objects are unpinnned when created.
- This primitive either pins or unpins an object, and answers if it was already pinned."
<primitive: 184 error: ec>
^self primitiveFailed!
Item was changed:
----- Method: Object>>unpin (in category 'pinning') -----
unpin
+ "Ensure the receiver is unpinned and answer whether it was pinned."
+ ^ self pinned: false!
- "The VM's garbage collector routinely moves objects as it reclaims and compacts
- memory. But it can also pin an object so that it will not be moved, which can make
- it easier to pass objects out through the FFI. Objects are unpinnned when created.
- This method ensures an object is unpinned, and answers whether it was pinned."
- ^self setPinned: false!
Chris Muller uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-cmm.1114.mcz
==================== Summary ====================
Name: Kernel-cmm.1114
Author: cmm
Time: 1 September 2017, 12:24:33.854299 pm
UUID: 0bc56c90-144a-401c-915c-c68060661f03
Ancestors: Kernel-cmm.1113
Revert cmm.1113 due to objections.
=============== Diff against Kernel-cmm.1113 ===============
Item was changed:
----- Method: Object>>pin (in category 'pinning') -----
pin
+ "The VM's garbage collector routinely moves objects as it reclaims and compacts
+ memory. But it can also pin an object so that it will not be moved, which can make
+ it easier to pass objects out through the FFI. Objects are unpinnned when created.
+ This method ensures an object is pinned, and answers whether it was already pinned."
+ ^self setPinned: true!
- "Ensure the receiver is pinned and answer whether it was pinned."
- ^ self pinned: true!
Item was removed:
- ----- Method: Object>>pinned: (in category 'pinning') -----
- pinned: aBoolean
- "The VM's garbage collector routinely moves objects as it reclaims and compacts memory. But it can also pin an object so that it will not be moved, which can make it easier to pass objects out through the FFI. Objects are unpinnned when created.
- Answer whether the receiver was pinned."
- ^ self setPinned: aBoolean!
Item was changed:
----- Method: Object>>setPinned: (in category 'private') -----
setPinned: aBoolean
+ "The VM's garbage collector routinely moves objects as it reclaims and compacts
+ memory. But it can also pin an object so that it will not be moved, which can make
+ it easier to pass objects out through the FFI. Objects are unpinnned when created.
+ This primitive either pins or unpins an object, and answers if it was already pinned."
- "Primitive which pins or unpins the receiver and answers whether it was already pinned."
<primitive: 184 error: ec>
^self primitiveFailed!
Item was changed:
----- Method: Object>>unpin (in category 'pinning') -----
unpin
+ "The VM's garbage collector routinely moves objects as it reclaims and compacts
+ memory. But it can also pin an object so that it will not be moved, which can make
+ it easier to pass objects out through the FFI. Objects are unpinnned when created.
+ This method ensures an object is unpinned, and answers whether it was pinned."
+ ^self setPinned: false!
- "Ensure the receiver is unpinned and answer whether it was pinned."
- ^ self pinned: false!
Hello
I think Mantis issue
http://bugs.squeak.org/view.php?id=7838
Command "explore it" applied to Object leads to crash of VM.
may be closed as well.
bp 10-16-16 06:36 confirms that it was OK on Windows 8.1
-Hannes
Patrick Rein uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-pre.763.mcz
==================== Summary ====================
Name: Collections-pre.763
Author: pre
Time: 31 August 2017, 3:14:26.5764 pm
UUID: ffff1838-0f68-9e49-bd57-6263eaebd8d7
Ancestors: Collections-pre.762, Collections-tonyg.734
Merges Collections-tonyg.734 which fixes Mantis #4665 and deals with the difference in counting at the public interface of streams and counting the steps in the underlying buffer.
=============== Diff against Collections-pre.762 ===============
Item was changed:
----- Method: PositionableStream>>upToAll: (in category 'accessing') -----
upToAll: aCollection
"Answer a subcollection from the current access position to the occurrence (if any, but not inclusive) of aCollection. If aCollection is not in the stream, answer the entire rest of the stream."
| startPos endMatch result |
startPos := self position.
(self match: aCollection)
ifTrue: [endMatch := self position.
self position: startPos.
+ result := self upToPosition: endMatch - aCollection size.
- result := self next: endMatch - startPos - aCollection size.
self position: endMatch.
^ result]
ifFalse: [self position: startPos.
^ self upToEnd]!
Item was added:
+ ----- Method: PositionableStream>>upToPosition: (in category 'accessing') -----
+ upToPosition: anInteger
+ "Answer a subcollection containing items starting from the current position and ending including the given position. Usefully different to #next: in that in the case of MultiByteFileStream, and perhaps others, positions measure in terms of encoded items, while #next: convention is to name a number of items, independent of their encoding in the underlying buffer."
+ ^ self next: anInteger - position
+ !