The Trunk: Morphic-eem.994.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Morphic-eem.994.mcz

commits-2
Eliot Miranda uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-eem.994.mcz

==================== Summary ====================

Name: Morphic-eem.994
Author: eem
Time: 18 July 2015, 10:22:51.401 am
UUID: bd1bf232-933d-4017-95d5-974200758bb6
Ancestors: Morphic-cmm.993

Fix a serious bug with interCyclePause:.  On the first invocation, lastCycleTime may be far in the future (since it will be whatever it was when the image is saved), hence Time millisecondsSince: lastCycleTime can be large and negative, hence milliSecs - (Time millisecondsSince: lastCycleTime) can be large and positive, which can result in a delay of many minutes in the first invocation.  This was causing the unresponsivness of the 64-bit Spur image on start-up.  The fix is simple; if lastCycleTime iks in the future it should be reset.

Change HandMorph>>handleEvent: to only update EventStats if it is non-nil, and change the package prologue to nil it.  Nothing reads EventStats, so it is taking cycles for no purpose.  This isn;t an issue until the count of mouse move events rolls over into large positive integers, at which point there's real overhead.  There's a comment in the method to allow one to "install" EventStats if and when one does want to collect such stats.  But IMO this shouldn't be enabled by default.  Waste not, want not.

=============== Diff against Morphic-cmm.993 ===============

Item was changed:
  ----- Method: HandMorph>>handleEvent: (in category 'events-processing') -----
  handleEvent: anEvent
  | evt ofs |
  owner ifNil:[^self].
  evt := anEvent.
 
+ "EventStats ifNil:[EventStats := IdentityDictionary new] ifNotNil: [EventStats := nil]."
+ EventStats ifNotNil:
+ [EventStats
+ at: #TypicalStack ifAbsentPut: [thisContext copyStack];
+ at: #count put: (EventStats at: #count ifAbsent:[0]) + 1;
+ at: evt type put: (EventStats at: evt type ifAbsent:[0]) + 1].
- EventStats ifNil:[EventStats := IdentityDictionary new].
- EventStats at: #count put: (EventStats at: #count ifAbsent:[0]) + 1.
- EventStats at: evt type put: (EventStats at: evt type ifAbsent:[0]) + 1.
 
  evt isMouseOver ifTrue:[^self sendMouseEvent: evt].
 
  ShowEvents == true ifTrue:[
  Display fill: (0@0 extent: 250@120) rule: Form over fillColor: Color white.
  ofs := (owner hands indexOf: self) - 1 * 60.
  evt printString displayAt: (0@ofs) + (evt isKeyboard ifTrue:[0@30] ifFalse:[0@0]).
  self keyboardFocus printString displayAt: (0@ofs)+(0@45).
  ].
  "Notify listeners"
  self sendListenEvent: evt to: self eventListeners.
 
  evt isWindowEvent ifTrue: [
  self sendEvent: evt focus: nil.
  ^self mouseOverHandler processMouseOver: lastMouseEvent].
 
  evt isKeyboard ifTrue:[
  self sendListenEvent: evt to: self keyboardListeners.
  self sendKeyboardEvent: evt.
  ^self mouseOverHandler processMouseOver: lastMouseEvent].
 
  evt isDropEvent ifTrue:[
  self sendEvent: evt focus: nil.
  ^self mouseOverHandler processMouseOver: lastMouseEvent].
 
  evt isMouse ifTrue:[
  self sendListenEvent: evt to: self mouseListeners.
  lastMouseEvent := evt].
 
  "Check for pending drag or double click operations."
  mouseClickState ifNotNil:[
  (mouseClickState handleEvent: evt from: self) ifFalse:[
  "Possibly dispatched #click: or something and will not re-establish otherwise"
  ^self mouseOverHandler processMouseOver: lastMouseEvent]].
 
  evt isMove ifTrue:[
  self position: evt position.
  self sendMouseEvent: evt.
  ] ifFalse:[
  "Issue a synthetic move event if we're not at the position of the event"
  (evt position = self position) ifFalse:[self moveToEvent: evt].
  "Drop submorphs on button events"
  (self hasSubmorphs)
  ifTrue:[self dropMorphs: evt]
  ifFalse:[self sendMouseEvent: evt].
  ].
  ShowEvents == true ifTrue:[self mouseFocus printString displayAt: (0@ofs) + (0@15)].
  self mouseOverHandler processMouseOver: lastMouseEvent.
  "self handleDragOutside: anEvent."
  !

Item was changed:
  ----- Method: WorldState>>interCyclePause: (in category 'update cycle') -----
  interCyclePause: milliSecs
+ "Delay enough that the previous cycle plus the amount of delay will equal milliSecs.  If the cycle is
+ already expensive, then no delay occurs.  However, if the system is idly waiting for interaction from
+ the user, the method will delay for a proportionally long time and cause the overall CPU usage of
+ Squeak to be low. If the preference #serverMode is enabled, always do a complete delay of 50ms,
+ independant of my argument. This prevents the freezing problem described in Mantis #6581"
- "delay enough that the previous cycle plus the amount of delay will equal milliSecs.  If the cycle is already expensive, then no delay occurs.  However, if the system is idly waiting for interaction from the user, the method will delay for a proportionally long time and cause the overall CPU usage of Squeak to be low.
- If the preference #serverMode is enabled, always do a complete delay of 50ms, independant of my argument. This prevents the freezing problem described in Mantis #6581"
 
+ | now millisecondsToWait |
+ now := Time millisecondClockValue.
+ "Be careful not to be misled by the first invocation after start-up.
+ lastCycleTime may be a left-over.  On clock wraparound, this will
+ result in a delya-less cycle, which should not be a problem."
+ (lastCycleTime notNil and: [lastCycleTime > now]) ifTrue:
+ [lastCycleTime := nil].
- | millisecondsToWait |
  millisecondsToWait := Preferences serverMode
  ifTrue: [ 50 ]
+ ifFalse: "e.g. CanSurrenderToOS is falsified by mouse move events in the SketchEditor for maximal responsiveness."
+ [ (lastCycleTime isNil or: [ CanSurrenderToOS == false ])
- ifFalse: [
- (lastCycleTime isNil or: [ CanSurrenderToOS == false ])
  ifTrue: [ 0 ]
+ ifFalse: [ milliSecs - (now - lastCycleTime) ] ].
+ millisecondsToWait > 0 ifTrue:
+ [ (interCycleDelay isNil or: [ interCycleDelay beingWaitedOn ])
- ifFalse: [ milliSecs - (Time millisecondsSince: lastCycleTime) ] ].
- millisecondsToWait > 0 ifTrue: [
- (interCycleDelay isNil or: [ interCycleDelay beingWaitedOn ])
  ifTrue: [ interCycleDelay := Delay forMilliseconds: millisecondsToWait ]
  ifFalse: [ interCycleDelay delayDuration: millisecondsToWait ].
  interCycleDelay wait ].
+ lastCycleTime := now.
+ CanSurrenderToOS := true!
- lastCycleTime := Time millisecondClockValue.
- CanSurrenderToOS := true.!

Item was changed:
  (PackageInfo named: 'Morphic') postscript: '"Initialize the key bindings and menus"
  Editor initialize.
 
  "apply the new icons"
  MenuIcons initializeIcons.
  TheWorldMainDockingBar updateInstances.
 
  "Fix missing inset of old-style windows."
  SystemWindow allSubInstancesDo: [:ea |
  (ea paneMorphs detect: [:m | m layoutFrame leftFraction = 0] ifNone: [])
  ifNotNil: [:m | m layoutFrame leftOffset > 0
      ifTrue: [ea layoutInset: 0]]].
 
  "Remove non-functional tools from world menu."
  LanguageEditor unload.
  UUniverseBrowser unload.
+ UUniverseEditor unload.
+
+ "Nuke the dubious EventStats dictionary"
+ HandMorph classPool at: #EventStats put: nil.'!
- UUniverseEditor unload.'!


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Morphic-eem.994.mcz

Chris Muller-3
Does this only affect the 64-bit image?  If so, we should move this to
Inbox until we finish the release.

On Sat, Jul 18, 2015 at 12:24 PM,  <[hidden email]> wrote:

> Eliot Miranda uploaded a new version of Morphic to project The Trunk:
> http://source.squeak.org/trunk/Morphic-eem.994.mcz
>
> ==================== Summary ====================
>
> Name: Morphic-eem.994
> Author: eem
> Time: 18 July 2015, 10:22:51.401 am
> UUID: bd1bf232-933d-4017-95d5-974200758bb6
> Ancestors: Morphic-cmm.993
>
> Fix a serious bug with interCyclePause:.  On the first invocation, lastCycleTime may be far in the future (since it will be whatever it was when the image is saved), hence Time millisecondsSince: lastCycleTime can be large and negative, hence milliSecs - (Time millisecondsSince: lastCycleTime) can be large and positive, which can result in a delay of many minutes in the first invocation.  This was causing the unresponsivness of the 64-bit Spur image on start-up.  The fix is simple; if lastCycleTime iks in the future it should be reset.
>
> Change HandMorph>>handleEvent: to only update EventStats if it is non-nil, and change the package prologue to nil it.  Nothing reads EventStats, so it is taking cycles for no purpose.  This isn;t an issue until the count of mouse move events rolls over into large positive integers, at which point there's real overhead.  There's a comment in the method to allow one to "install" EventStats if and when one does want to collect such stats.  But IMO this shouldn't be enabled by default.  Waste not, want not.
>
> =============== Diff against Morphic-cmm.993 ===============
>
> Item was changed:
>   ----- Method: HandMorph>>handleEvent: (in category 'events-processing') -----
>   handleEvent: anEvent
>         | evt ofs |
>         owner ifNil:[^self].
>         evt := anEvent.
>
> +       "EventStats ifNil:[EventStats := IdentityDictionary new] ifNotNil: [EventStats := nil]."
> +       EventStats ifNotNil:
> +               [EventStats
> +                       at: #TypicalStack ifAbsentPut: [thisContext copyStack];
> +                       at: #count put: (EventStats at: #count ifAbsent:[0]) + 1;
> +                       at: evt type put: (EventStats at: evt type ifAbsent:[0]) + 1].
> -       EventStats ifNil:[EventStats := IdentityDictionary new].
> -       EventStats at: #count put: (EventStats at: #count ifAbsent:[0]) + 1.
> -       EventStats at: evt type put: (EventStats at: evt type ifAbsent:[0]) + 1.
>
>         evt isMouseOver ifTrue:[^self sendMouseEvent: evt].
>
>   ShowEvents == true ifTrue:[
>         Display fill: (0@0 extent: 250@120) rule: Form over fillColor: Color white.
>         ofs := (owner hands indexOf: self) - 1 * 60.
>         evt printString displayAt: (0@ofs) + (evt isKeyboard ifTrue:[0@30] ifFalse:[0@0]).
>         self keyboardFocus printString displayAt: (0@ofs)+(0@45).
>   ].
>         "Notify listeners"
>         self sendListenEvent: evt to: self eventListeners.
>
>         evt isWindowEvent ifTrue: [
>                 self sendEvent: evt focus: nil.
>                 ^self mouseOverHandler processMouseOver: lastMouseEvent].
>
>         evt isKeyboard ifTrue:[
>                 self sendListenEvent: evt to: self keyboardListeners.
>                 self sendKeyboardEvent: evt.
>                 ^self mouseOverHandler processMouseOver: lastMouseEvent].
>
>         evt isDropEvent ifTrue:[
>                 self sendEvent: evt focus: nil.
>                 ^self mouseOverHandler processMouseOver: lastMouseEvent].
>
>         evt isMouse ifTrue:[
>                 self sendListenEvent: evt to: self mouseListeners.
>                 lastMouseEvent := evt].
>
>         "Check for pending drag or double click operations."
>         mouseClickState ifNotNil:[
>                 (mouseClickState handleEvent: evt from: self) ifFalse:[
>                         "Possibly dispatched #click: or something and will not re-establish otherwise"
>                         ^self mouseOverHandler processMouseOver: lastMouseEvent]].
>
>         evt isMove ifTrue:[
>                 self position: evt position.
>                 self sendMouseEvent: evt.
>         ] ifFalse:[
>                 "Issue a synthetic move event if we're not at the position of the event"
>                 (evt position = self position) ifFalse:[self moveToEvent: evt].
>                 "Drop submorphs on button events"
>                 (self hasSubmorphs)
>                         ifTrue:[self dropMorphs: evt]
>                         ifFalse:[self sendMouseEvent: evt].
>         ].
>         ShowEvents == true ifTrue:[self mouseFocus printString displayAt: (0@ofs) + (0@15)].
>         self mouseOverHandler processMouseOver: lastMouseEvent.
>         "self handleDragOutside: anEvent."
>   !
>
> Item was changed:
>   ----- Method: WorldState>>interCyclePause: (in category 'update cycle') -----
>   interCyclePause: milliSecs
> +       "Delay enough that the previous cycle plus the amount of delay will equal milliSecs.  If the cycle is
> +        already expensive, then no delay occurs.  However, if the system is idly waiting for interaction from
> +        the user, the method will delay for a proportionally long time and cause the overall CPU usage of
> +        Squeak to be low. If the preference #serverMode is enabled, always do a complete delay of 50ms,
> +        independant of my argument. This prevents the freezing problem described in Mantis #6581"
> -       "delay enough that the previous cycle plus the amount of delay will equal milliSecs.  If the cycle is already expensive, then no delay occurs.  However, if the system is idly waiting for interaction from the user, the method will delay for a proportionally long time and cause the overall CPU usage of Squeak to be low.
> -       If the preference #serverMode is enabled, always do a complete delay of 50ms, independant of my argument. This prevents the freezing problem described in Mantis #6581"
>
> +       | now millisecondsToWait |
> +       now := Time millisecondClockValue.
> +       "Be careful not to be misled by the first invocation after start-up.
> +        lastCycleTime may be a left-over.  On clock wraparound, this will
> +        result in a delya-less cycle, which should not be a problem."
> +       (lastCycleTime notNil and: [lastCycleTime > now]) ifTrue:
> +               [lastCycleTime := nil].
> -       | millisecondsToWait |
>         millisecondsToWait := Preferences serverMode
>                 ifTrue: [ 50 ]
> +               ifFalse: "e.g. CanSurrenderToOS is falsified by mouse move events in the SketchEditor for maximal responsiveness."
> +                       [ (lastCycleTime isNil or: [ CanSurrenderToOS == false ])
> -               ifFalse: [
> -                       (lastCycleTime isNil or: [ CanSurrenderToOS == false ])
>                                 ifTrue: [ 0 ]
> +                               ifFalse: [ milliSecs - (now - lastCycleTime) ] ].
> +       millisecondsToWait > 0 ifTrue:
> +               [ (interCycleDelay isNil or: [ interCycleDelay beingWaitedOn ])
> -                               ifFalse: [ milliSecs - (Time millisecondsSince: lastCycleTime) ] ].
> -       millisecondsToWait > 0 ifTrue: [
> -               (interCycleDelay isNil or: [ interCycleDelay beingWaitedOn ])
>                         ifTrue: [ interCycleDelay := Delay forMilliseconds: millisecondsToWait ]
>                         ifFalse: [ interCycleDelay delayDuration: millisecondsToWait ].
>                 interCycleDelay wait ].
> +       lastCycleTime := now.
> +       CanSurrenderToOS := true!
> -       lastCycleTime := Time millisecondClockValue.
> -       CanSurrenderToOS := true.!
>
> Item was changed:
>   (PackageInfo named: 'Morphic') postscript: '"Initialize the key bindings and menus"
>   Editor initialize.
>
>   "apply the new icons"
>   MenuIcons initializeIcons.
>   TheWorldMainDockingBar updateInstances.
>
>   "Fix missing inset of old-style windows."
>   SystemWindow allSubInstancesDo: [:ea |
>         (ea paneMorphs detect: [:m | m layoutFrame leftFraction = 0] ifNone: [])
>                 ifNotNil: [:m | m layoutFrame leftOffset > 0
>                         ifTrue: [ea layoutInset: 0]]].
>
>   "Remove non-functional tools from world menu."
>   LanguageEditor unload.
>   UUniverseBrowser unload.
> + UUniverseEditor unload.
> +
> + "Nuke the dubious EventStats dictionary"
> + HandMorph classPool at: #EventStats put: nil.'!
> - UUniverseEditor unload.'!
>
>

Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Morphic-eem.994.mcz

Eliot Miranda-2
Hi Chris,

On Sat, Jul 18, 2015 at 10:31 AM, Chris Muller <[hidden email]> wrote:
Does this only affect the 64-bit image?  If so, we should move this to
Inbox until we finish the release.

OK.  Go ahead.  In fact, I may just have mis-diagnosed the bug.  I'll take another look.  But feel free to move it to inbox.

 

On Sat, Jul 18, 2015 at 12:24 PM,  <[hidden email]> wrote:
> Eliot Miranda uploaded a new version of Morphic to project The Trunk:
> http://source.squeak.org/trunk/Morphic-eem.994.mcz
>
> ==================== Summary ====================
>
> Name: Morphic-eem.994
> Author: eem
> Time: 18 July 2015, 10:22:51.401 am
> UUID: bd1bf232-933d-4017-95d5-974200758bb6
> Ancestors: Morphic-cmm.993
>
> Fix a serious bug with interCyclePause:.  On the first invocation, lastCycleTime may be far in the future (since it will be whatever it was when the image is saved), hence Time millisecondsSince: lastCycleTime can be large and negative, hence milliSecs - (Time millisecondsSince: lastCycleTime) can be large and positive, which can result in a delay of many minutes in the first invocation.  This was causing the unresponsivness of the 64-bit Spur image on start-up.  The fix is simple; if lastCycleTime iks in the future it should be reset.
>
> Change HandMorph>>handleEvent: to only update EventStats if it is non-nil, and change the package prologue to nil it.  Nothing reads EventStats, so it is taking cycles for no purpose.  This isn;t an issue until the count of mouse move events rolls over into large positive integers, at which point there's real overhead.  There's a comment in the method to allow one to "install" EventStats if and when one does want to collect such stats.  But IMO this shouldn't be enabled by default.  Waste not, want not.
>
> =============== Diff against Morphic-cmm.993 ===============
>
> Item was changed:
>   ----- Method: HandMorph>>handleEvent: (in category 'events-processing') -----
>   handleEvent: anEvent
>         | evt ofs |
>         owner ifNil:[^self].
>         evt := anEvent.
>
> +       "EventStats ifNil:[EventStats := IdentityDictionary new] ifNotNil: [EventStats := nil]."
> +       EventStats ifNotNil:
> +               [EventStats
> +                       at: #TypicalStack ifAbsentPut: [thisContext copyStack];
> +                       at: #count put: (EventStats at: #count ifAbsent:[0]) + 1;
> +                       at: evt type put: (EventStats at: evt type ifAbsent:[0]) + 1].
> -       EventStats ifNil:[EventStats := IdentityDictionary new].
> -       EventStats at: #count put: (EventStats at: #count ifAbsent:[0]) + 1.
> -       EventStats at: evt type put: (EventStats at: evt type ifAbsent:[0]) + 1.
>
>         evt isMouseOver ifTrue:[^self sendMouseEvent: evt].
>
>   ShowEvents == true ifTrue:[
>         Display fill: (0@0 extent: 250@120) rule: Form over fillColor: Color white.
>         ofs := (owner hands indexOf: self) - 1 * 60.
>         evt printString displayAt: (0@ofs) + (evt isKeyboard ifTrue:[0@30] ifFalse:[0@0]).
>         self keyboardFocus printString displayAt: (0@ofs)+(0@45).
>   ].
>         "Notify listeners"
>         self sendListenEvent: evt to: self eventListeners.
>
>         evt isWindowEvent ifTrue: [
>                 self sendEvent: evt focus: nil.
>                 ^self mouseOverHandler processMouseOver: lastMouseEvent].
>
>         evt isKeyboard ifTrue:[
>                 self sendListenEvent: evt to: self keyboardListeners.
>                 self sendKeyboardEvent: evt.
>                 ^self mouseOverHandler processMouseOver: lastMouseEvent].
>
>         evt isDropEvent ifTrue:[
>                 self sendEvent: evt focus: nil.
>                 ^self mouseOverHandler processMouseOver: lastMouseEvent].
>
>         evt isMouse ifTrue:[
>                 self sendListenEvent: evt to: self mouseListeners.
>                 lastMouseEvent := evt].
>
>         "Check for pending drag or double click operations."
>         mouseClickState ifNotNil:[
>                 (mouseClickState handleEvent: evt from: self) ifFalse:[
>                         "Possibly dispatched #click: or something and will not re-establish otherwise"
>                         ^self mouseOverHandler processMouseOver: lastMouseEvent]].
>
>         evt isMove ifTrue:[
>                 self position: evt position.
>                 self sendMouseEvent: evt.
>         ] ifFalse:[
>                 "Issue a synthetic move event if we're not at the position of the event"
>                 (evt position = self position) ifFalse:[self moveToEvent: evt].
>                 "Drop submorphs on button events"
>                 (self hasSubmorphs)
>                         ifTrue:[self dropMorphs: evt]
>                         ifFalse:[self sendMouseEvent: evt].
>         ].
>         ShowEvents == true ifTrue:[self mouseFocus printString displayAt: (0@ofs) + (0@15)].
>         self mouseOverHandler processMouseOver: lastMouseEvent.
>         "self handleDragOutside: anEvent."
>   !
>
> Item was changed:
>   ----- Method: WorldState>>interCyclePause: (in category 'update cycle') -----
>   interCyclePause: milliSecs
> +       "Delay enough that the previous cycle plus the amount of delay will equal milliSecs.  If the cycle is
> +        already expensive, then no delay occurs.  However, if the system is idly waiting for interaction from
> +        the user, the method will delay for a proportionally long time and cause the overall CPU usage of
> +        Squeak to be low. If the preference #serverMode is enabled, always do a complete delay of 50ms,
> +        independant of my argument. This prevents the freezing problem described in Mantis #6581"
> -       "delay enough that the previous cycle plus the amount of delay will equal milliSecs.  If the cycle is already expensive, then no delay occurs.  However, if the system is idly waiting for interaction from the user, the method will delay for a proportionally long time and cause the overall CPU usage of Squeak to be low.
> -       If the preference #serverMode is enabled, always do a complete delay of 50ms, independant of my argument. This prevents the freezing problem described in Mantis #6581"
>
> +       | now millisecondsToWait |
> +       now := Time millisecondClockValue.
> +       "Be careful not to be misled by the first invocation after start-up.
> +        lastCycleTime may be a left-over.  On clock wraparound, this will
> +        result in a delya-less cycle, which should not be a problem."
> +       (lastCycleTime notNil and: [lastCycleTime > now]) ifTrue:
> +               [lastCycleTime := nil].
> -       | millisecondsToWait |
>         millisecondsToWait := Preferences serverMode
>                 ifTrue: [ 50 ]
> +               ifFalse: "e.g. CanSurrenderToOS is falsified by mouse move events in the SketchEditor for maximal responsiveness."
> +                       [ (lastCycleTime isNil or: [ CanSurrenderToOS == false ])
> -               ifFalse: [
> -                       (lastCycleTime isNil or: [ CanSurrenderToOS == false ])
>                                 ifTrue: [ 0 ]
> +                               ifFalse: [ milliSecs - (now - lastCycleTime) ] ].
> +       millisecondsToWait > 0 ifTrue:
> +               [ (interCycleDelay isNil or: [ interCycleDelay beingWaitedOn ])
> -                               ifFalse: [ milliSecs - (Time millisecondsSince: lastCycleTime) ] ].
> -       millisecondsToWait > 0 ifTrue: [
> -               (interCycleDelay isNil or: [ interCycleDelay beingWaitedOn ])
>                         ifTrue: [ interCycleDelay := Delay forMilliseconds: millisecondsToWait ]
>                         ifFalse: [ interCycleDelay delayDuration: millisecondsToWait ].
>                 interCycleDelay wait ].
> +       lastCycleTime := now.
> +       CanSurrenderToOS := true!
> -       lastCycleTime := Time millisecondClockValue.
> -       CanSurrenderToOS := true.!
>
> Item was changed:
>   (PackageInfo named: 'Morphic') postscript: '"Initialize the key bindings and menus"
>   Editor initialize.
>
>   "apply the new icons"
>   MenuIcons initializeIcons.
>   TheWorldMainDockingBar updateInstances.
>
>   "Fix missing inset of old-style windows."
>   SystemWindow allSubInstancesDo: [:ea |
>         (ea paneMorphs detect: [:m | m layoutFrame leftFraction = 0] ifNone: [])
>                 ifNotNil: [:m | m layoutFrame leftOffset > 0
>                         ifTrue: [ea layoutInset: 0]]].
>
>   "Remove non-functional tools from world menu."
>   LanguageEditor unload.
>   UUniverseBrowser unload.
> + UUniverseEditor unload.
> +
> + "Nuke the dubious EventStats dictionary"
> + HandMorph classPool at: #EventStats put: nil.'!
> - UUniverseEditor unload.'!
>
>



--
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Morphic-eem.994.mcz

Eliot Miranda-2
In reply to this post by Chris Muller-3
Hi Chris,

    thank you.  You've stopped me driving a baaaad bug underground.  In fact it looks like a bootstrap bug.  In normal images

(Time classPool at: #MillisecondClockMask) = 16r1FFFFFFF

but in the 64-bit Spur image

(Time classPool at: #MillisecondClockMask) = -1

Eek :-).  So please disregard Morphic-eem.994.  There is /some/ goodness in that version, but at least the method commentary is wrong.

On Sat, Jul 18, 2015 at 10:31 AM, Chris Muller <[hidden email]> wrote:
Does this only affect the 64-bit image?  If so, we should move this to
Inbox until we finish the release.

On Sat, Jul 18, 2015 at 12:24 PM,  <[hidden email]> wrote:
> Eliot Miranda uploaded a new version of Morphic to project The Trunk:
> http://source.squeak.org/trunk/Morphic-eem.994.mcz
>
> ==================== Summary ====================
>
> Name: Morphic-eem.994
> Author: eem
> Time: 18 July 2015, 10:22:51.401 am
> UUID: bd1bf232-933d-4017-95d5-974200758bb6
> Ancestors: Morphic-cmm.993
>
> Fix a serious bug with interCyclePause:.  On the first invocation, lastCycleTime may be far in the future (since it will be whatever it was when the image is saved), hence Time millisecondsSince: lastCycleTime can be large and negative, hence milliSecs - (Time millisecondsSince: lastCycleTime) can be large and positive, which can result in a delay of many minutes in the first invocation.  This was causing the unresponsivness of the 64-bit Spur image on start-up.  The fix is simple; if lastCycleTime iks in the future it should be reset.
>
> Change HandMorph>>handleEvent: to only update EventStats if it is non-nil, and change the package prologue to nil it.  Nothing reads EventStats, so it is taking cycles for no purpose.  This isn;t an issue until the count of mouse move events rolls over into large positive integers, at which point there's real overhead.  There's a comment in the method to allow one to "install" EventStats if and when one does want to collect such stats.  But IMO this shouldn't be enabled by default.  Waste not, want not.
>
> =============== Diff against Morphic-cmm.993 ===============
>
> Item was changed:
>   ----- Method: HandMorph>>handleEvent: (in category 'events-processing') -----
>   handleEvent: anEvent
>         | evt ofs |
>         owner ifNil:[^self].
>         evt := anEvent.
>
> +       "EventStats ifNil:[EventStats := IdentityDictionary new] ifNotNil: [EventStats := nil]."
> +       EventStats ifNotNil:
> +               [EventStats
> +                       at: #TypicalStack ifAbsentPut: [thisContext copyStack];
> +                       at: #count put: (EventStats at: #count ifAbsent:[0]) + 1;
> +                       at: evt type put: (EventStats at: evt type ifAbsent:[0]) + 1].
> -       EventStats ifNil:[EventStats := IdentityDictionary new].
> -       EventStats at: #count put: (EventStats at: #count ifAbsent:[0]) + 1.
> -       EventStats at: evt type put: (EventStats at: evt type ifAbsent:[0]) + 1.
>
>         evt isMouseOver ifTrue:[^self sendMouseEvent: evt].
>
>   ShowEvents == true ifTrue:[
>         Display fill: (0@0 extent: 250@120) rule: Form over fillColor: Color white.
>         ofs := (owner hands indexOf: self) - 1 * 60.
>         evt printString displayAt: (0@ofs) + (evt isKeyboard ifTrue:[0@30] ifFalse:[0@0]).
>         self keyboardFocus printString displayAt: (0@ofs)+(0@45).
>   ].
>         "Notify listeners"
>         self sendListenEvent: evt to: self eventListeners.
>
>         evt isWindowEvent ifTrue: [
>                 self sendEvent: evt focus: nil.
>                 ^self mouseOverHandler processMouseOver: lastMouseEvent].
>
>         evt isKeyboard ifTrue:[
>                 self sendListenEvent: evt to: self keyboardListeners.
>                 self sendKeyboardEvent: evt.
>                 ^self mouseOverHandler processMouseOver: lastMouseEvent].
>
>         evt isDropEvent ifTrue:[
>                 self sendEvent: evt focus: nil.
>                 ^self mouseOverHandler processMouseOver: lastMouseEvent].
>
>         evt isMouse ifTrue:[
>                 self sendListenEvent: evt to: self mouseListeners.
>                 lastMouseEvent := evt].
>
>         "Check for pending drag or double click operations."
>         mouseClickState ifNotNil:[
>                 (mouseClickState handleEvent: evt from: self) ifFalse:[
>                         "Possibly dispatched #click: or something and will not re-establish otherwise"
>                         ^self mouseOverHandler processMouseOver: lastMouseEvent]].
>
>         evt isMove ifTrue:[
>                 self position: evt position.
>                 self sendMouseEvent: evt.
>         ] ifFalse:[
>                 "Issue a synthetic move event if we're not at the position of the event"
>                 (evt position = self position) ifFalse:[self moveToEvent: evt].
>                 "Drop submorphs on button events"
>                 (self hasSubmorphs)
>                         ifTrue:[self dropMorphs: evt]
>                         ifFalse:[self sendMouseEvent: evt].
>         ].
>         ShowEvents == true ifTrue:[self mouseFocus printString displayAt: (0@ofs) + (0@15)].
>         self mouseOverHandler processMouseOver: lastMouseEvent.
>         "self handleDragOutside: anEvent."
>   !
>
> Item was changed:
>   ----- Method: WorldState>>interCyclePause: (in category 'update cycle') -----
>   interCyclePause: milliSecs
> +       "Delay enough that the previous cycle plus the amount of delay will equal milliSecs.  If the cycle is
> +        already expensive, then no delay occurs.  However, if the system is idly waiting for interaction from
> +        the user, the method will delay for a proportionally long time and cause the overall CPU usage of
> +        Squeak to be low. If the preference #serverMode is enabled, always do a complete delay of 50ms,
> +        independant of my argument. This prevents the freezing problem described in Mantis #6581"
> -       "delay enough that the previous cycle plus the amount of delay will equal milliSecs.  If the cycle is already expensive, then no delay occurs.  However, if the system is idly waiting for interaction from the user, the method will delay for a proportionally long time and cause the overall CPU usage of Squeak to be low.
> -       If the preference #serverMode is enabled, always do a complete delay of 50ms, independant of my argument. This prevents the freezing problem described in Mantis #6581"
>
> +       | now millisecondsToWait |
> +       now := Time millisecondClockValue.
> +       "Be careful not to be misled by the first invocation after start-up.
> +        lastCycleTime may be a left-over.  On clock wraparound, this will
> +        result in a delya-less cycle, which should not be a problem."
> +       (lastCycleTime notNil and: [lastCycleTime > now]) ifTrue:
> +               [lastCycleTime := nil].
> -       | millisecondsToWait |
>         millisecondsToWait := Preferences serverMode
>                 ifTrue: [ 50 ]
> +               ifFalse: "e.g. CanSurrenderToOS is falsified by mouse move events in the SketchEditor for maximal responsiveness."
> +                       [ (lastCycleTime isNil or: [ CanSurrenderToOS == false ])
> -               ifFalse: [
> -                       (lastCycleTime isNil or: [ CanSurrenderToOS == false ])
>                                 ifTrue: [ 0 ]
> +                               ifFalse: [ milliSecs - (now - lastCycleTime) ] ].
> +       millisecondsToWait > 0 ifTrue:
> +               [ (interCycleDelay isNil or: [ interCycleDelay beingWaitedOn ])
> -                               ifFalse: [ milliSecs - (Time millisecondsSince: lastCycleTime) ] ].
> -       millisecondsToWait > 0 ifTrue: [
> -               (interCycleDelay isNil or: [ interCycleDelay beingWaitedOn ])
>                         ifTrue: [ interCycleDelay := Delay forMilliseconds: millisecondsToWait ]
>                         ifFalse: [ interCycleDelay delayDuration: millisecondsToWait ].
>                 interCycleDelay wait ].
> +       lastCycleTime := now.
> +       CanSurrenderToOS := true!
> -       lastCycleTime := Time millisecondClockValue.
> -       CanSurrenderToOS := true.!
>
> Item was changed:
>   (PackageInfo named: 'Morphic') postscript: '"Initialize the key bindings and menus"
>   Editor initialize.
>
>   "apply the new icons"
>   MenuIcons initializeIcons.
>   TheWorldMainDockingBar updateInstances.
>
>   "Fix missing inset of old-style windows."
>   SystemWindow allSubInstancesDo: [:ea |
>         (ea paneMorphs detect: [:m | m layoutFrame leftFraction = 0] ifNone: [])
>                 ifNotNil: [:m | m layoutFrame leftOffset > 0
>                         ifTrue: [ea layoutInset: 0]]].
>
>   "Remove non-functional tools from world menu."
>   LanguageEditor unload.
>   UUniverseBrowser unload.
> + UUniverseEditor unload.
> +
> + "Nuke the dubious EventStats dictionary"
> + HandMorph classPool at: #EventStats put: nil.'!
> - UUniverseEditor unload.'!
>
>



--
_,,,^..^,,,_
best, Eliot