Hi all!<br>
<br>
while playing around with code simulation recently, I found out that the following dictionary lookup consumes extremely many bytecodes:<br>
<br>
    <font color="#000000">UserInterfaceTheme </font><font color="#000080">current</font><font color="#000000"> </font><font color="#000080">get:</font><font color="#000000"> </font><font color="#000080">#return</font><font color="#000000"> </font><font color="#000080">for:</font><font color="#000000"> SHTextStylerST80.</font><br>
<br>
<font color="#000000">Dictionary </font><font color="#000080">>></font><font color="#000000"> </font><font color="#000080">#scanFor:</font> takes 59 (sic!) attempts to find the right item in the dictionary. In other words, almost 20% of the property table is traversed, which does not conform my idea of a hashtable.<br>
<br>
The reason for this can be found in <font color="#000000">Association </font><font color="#000080">>></font><font color="#000000"> </font><font color="#000080">#hash</font>: Since Collections-ar.304, it does not take the value of an association into consideration for the hash any longer. As <font color="#606060">UserInterfaceTheme</font> uses <font color="#606060">Association</font>s as keys in the <font color="#000000">Dictionary</font>, we have a lot of "hash misses". Even though you might not notice this in practice, I noticed this indeed during debugging und simulating, I can tell you. :-)<br>
<br>
On the other hand, reverting <font color="#000000">Association </font><font color="#000080">>></font><font color="#000000"> </font><font color="#000080">#hash</font> to honor the value slows down <font color="#000000">Unicode </font><font color="#000080">class</font><font color="#000000"> </font><font color="#000080">compileAll</font> indeed (significantly: 60 ms vs. 2100 ms), as noted in Andreas' original comment:<br>
<br>
    <i>Name: Collections-ar.304<br>
    Author: ar<br>
    Time: 11 February 2010, 11:52:58.959 pm<br>
    UUID: 9e97b360-adf1-f745-8f8c-562aa08d566e<br>
    Ancestors: Collections-ar.303<br>
    <br>
    Fix an age-old bug in Association>>hash which causes extreme slowdowns in compiling Unicode methods. Association>>hash does not need to hash the value; it's slow and useless.</i><br>
<br>
So my question is: What would be the right fix for this situation? Is it<br>
a) Do <u>not</u> use <font color="#000000">Association</font>s in <font color="#000000">Dictionary</font>s when its value matters for the lookup; or<br>
b) Do <u>only</u> use <font color="#000000">Association</font>s in <font color="#000000">Dictionary</font>s when its value maters for the lookup?<br>
For a), the dictionary layout of <font color="#000000">UserInterfaceTheme</font> needs to be changed, for which I am attaching a changeset that replaces <font color="#000000">Association</font>s by <font color="#000000">Array</font>s there.* For b), the layout of litIndSet in <font color="#000000">Encoder</font> needs to be changed, for instance by using <font color="#000000">Binding</font>s instead of <font color="#000000">Association</font>s for classPool entries. However, I'm not familiar enough with <font color="#000000">Encoder</font> etc. to answer this question.<br>
<br>
<font color="#808080">*The changeset will automatically update all UserInterfaceTheme instances. Benchmark:<br>
<br>
    </font><font color="#817F7F">theme</font><font color="#808080"> </font><b>:=</b><font color="#808080"> </font><font color="#606060">UserInterfaceTheme</font><font color="#808080"> </font><font color="#787880">current</font><font color="#787878">.</font><font color="#808080"><br>
    </font><font color="#817F7F">random</font><font color="#808080"> </font><b>:=</b><font color="#808080"> </font><font color="#606060">Random</font><font color="#808080"> </font><font color="#7E7E80">seed:</font><font color="#808080"> </font><font color="#807070">20220526</font><font color="#787878">.</font><font color="#808080"><br>
    </font><font color="#817F7F">properties</font><font color="#808080"> </font><b>:=</b><font color="#808080"> </font><font color="#404040">(</font><font color="#807070">1</font><font color="#808080"> </font><font color="#7E7E80">to:</font><font color="#808080"> </font><font color="#807070">10000</font><font color="#404040">)</font><font color="#808080"> </font><font color="#7E7E80">collect:</font><font color="#808080"> </font><font color="#606060">[:</font><font color="#606080">i</font><font color="#808080"> | </font><font color="#817F7F">theme</font><font color="#808080"> </font><font color="#787880">properties</font><font color="#808080"> </font><font color="#787880">keys</font><font color="#808080"> </font><font color="#7E7E80">atRandom:</font><font color="#808080"> </font><font color="#817F7F">random</font><font color="#606060">]</font><font color="#787878">.</font><font color="#808080"><br>
    </font><font color="#606060">[</font><font color="#817F7F">properties</font><font color="#808080"> </font><font color="#7E7E80">collect:</font><font color="#808080"> </font><font color="#408040">[</font><font color="#606060">:</font><font color="#606080">ea</font><font color="#808080"> | </font><font color="#817F7F">theme</font><font color="#808080"> </font><font color="#7E7E80">get:</font><font color="#808080"> </font><font color="#404080">ea</font><font color="#408040">]</font><font color="#606060">]</font><font color="#808080"> </font><font color="#787880">bench</font><font color="#787878">.</font><font color="#808080"><br>
<br>
Old: 45 ms | New: 10 ms<br>
</font><br>
Looking forward to your opinion: <b>How should we treat Associations in Dictionarys?</b> Of course, this is not release-critical. :-)<br>
<br>
Best,<br>
Christoph<br>
<br>
<b>=============== Postscript (accelerateUserInterfaceTheme.2.cs) ===============</b><br>
<br>
<font color="#008080">"Postscript: Update UserInterfaceTheme instances"</font><font color="#000000"><br>
<br>
</font><font color="#000000">UserInterfaceTheme</font><font color="#000000"> </font><font color="#000080">allSubInstancesDo:</font><font color="#000000"> </font><font color="#000000">[</font><font color="#000000">:</font><font color="#000080">theme</font><font color="#000000"> </font><font color="#808080">|</font><font color="#000000"><br>
    </font><font color="#808080">|</font><font color="#000000"> </font><font color="#808080">newProperties</font><font color="#000000"> </font><font color="#808080">|</font><font color="#000000"><br>
    </font><font color="#808080">newProperties</font><font color="#000000"> </font><b>:=</b><font color="#000000"> </font><font color="#000080">theme</font><font color="#000000"> </font><font color="#000080">properties</font><font color="#000000"> </font><font color="#000080">copyEmpty</font><font color="#000000">.</font><font color="#000000"><br>
    </font><font color="#000080">theme</font><font color="#000000"> </font><font color="#000080">properties</font><font color="#000000"> </font><font color="#000080">keysAndValuesDo:</font><font color="#000000"> </font><font color="#008000">[</font><font color="#000000">:</font><font color="#000080">key</font><font color="#000000"> </font><font color="#000000">:</font><font color="#000080">value</font><font color="#000000"> </font><font color="#808080">|</font><font color="#000000"><br>
        </font><font color="#808080">newProperties</font><font color="#000000"><br>
            </font><font color="#000080">at:</font><font color="#000000"> </font><font color="#800080">(</font><font color="#800000">(</font><font color="#000080">key</font><font color="#000000"> </font><font color="#000080">isKindOf:</font><font color="#000000"> </font><font color="#000000">Association</font><font color="#800000">)</font><font color="#000000"><br>
                </font><font color="#000080">ifTrue:</font><font color="#000000"> </font><font color="#800000">[</font><font color="#000000">{</font><font color="#000080">key</font><font color="#000000"> </font><font color="#000080">key</font><font color="#000000">.</font><font color="#000000"> </font><font color="#000080">key</font><font color="#000000"> </font><font color="#000080">value</font><font color="#000000">}</font><font color="#800000">]</font><font color="#000000"><br>
                </font><font color="#000080">ifFalse:</font><font color="#000000"> </font><font color="#800000">[</font><font color="#000080">key</font><font color="#800000">]</font><font color="#800080">)</font><font color="#000000"><br>
            </font><font color="#000080">put:</font><font color="#000000"> </font><font color="#000080">value</font><font color="#008000">]</font><font color="#000000">.</font><font color="#000000"><br>
    </font><font color="#000080">theme</font><font color="#000000"> </font><font color="#000080">instVarNamed:</font><font color="#000000"> </font><font color="#800080">'properties'</font><font color="#000000"> </font><font color="#000080">put:</font><font color="#000000"> </font><font color="#808080">newProperties</font><font color="#000000">]</font><font color="#000000">.</font><br>
<br>
<b>=============== Diff ===============</b><br>
<br>
<b>UserInterfaceTheme>>get: {private} · ct 5/26/2022 21:15 (changed)</b><br>
get: keyObject <br>
    "keyObject is intended to be an Association. We have two lookup strategies: 1) along the superclass chain *of the client*, 2) via a linked theme. Evaluate the result because there can be message sends stored or blocks."<br>
    <br>
    | k |<br>
    properties<br>
        at: keyObject<br>
        ifPresent: [:prop | ^ prop value].<br>
    <br>
<s><font color="#0000FF">-     keyObject isVariableBinding "simple key objects"<br>
</font></s><font color="#FF0000">+     keyObject isArray "simple key objects"<br>
</font>        ifFalse: [^ self getViaLink: keyObject].<br>
    <br>
<s><font color="#0000FF">-     k := keyObject key.<br>
</font></s><font color="#FF0000">+     k := keyObject at: 1.<br>
</font>    (self getViaSuperclasses: keyObject)<br>
        ifNotNil: [:prop | ^ prop].<br>
        <br>
<s><font color="#0000FF">-     keyObject key: k. "restore"<br>
</font></s><font color="#FF0000">+     keyObject at: 1 put: k. "restore"<br>
</font>    ^ self getViaLink: keyObject<br>
<br>
<b>UserInterfaceTheme>>get:for: {private} · ct 5/26/2022 21:02 (changed)</b><br>
get: propertySymbol for: scope<br>
    "For convenience. Does support access to non-class keys."<br>
    <br>
    | aClass |<br>
    aClass := (scope isNil or: [scope isBehavior])<br>
        ifTrue: [scope]<br>
        ifFalse: [Smalltalk classNamed: scope].<br>
<br>
<s><font color="#0000FF">-     aClass ifNotNil: [^ self get: aClass -> propertySymbol].<br>
</font></s><font color="#FF0000">+     aClass ifNotNil: [^ self get: {aClass. propertySymbol}].<br>
</font>        <br>
    properties<br>
<s><font color="#0000FF">-         at: scope -> propertySymbol<br>
</font></s><font color="#FF0000">+         at: {scope. propertySymbol}<br>
</font>        ifPresent: [:prop | ^ prop value].<br>
        <br>
<s><font color="#0000FF">-     ^ self getViaLink: scope -> propertySymbol<br>
</font></s><font color="#FF0000">+     ^ self getViaLink: {scope. propertySymbol}</font><br>
<br>
<b>UserInterfaceTheme>>getViaSuperclasses: {private} · ct 5/26/2022 21:15 (changed)</b><br>
getViaSuperclasses: keyObject <br>
    "keyObject is intended to be an Association.<br>
    Find the superclass of the key of the keyObject (which will initially be the client's class) and make a new keyObject using that and the original message name, then try searching for that."<br>
        <br>
    "We know we're the only referencer of keyObject.  Update it rather than create new ones, for performance reasons."<br>
<s><font color="#0000FF">-     keyObject key: keyObject key superclass.<br>
</font></s><font color="#FF0000">+     keyObject at: 1 put: (keyObject at: 1) superclass.<br>
</font><br>
<s><font color="#0000FF">-     keyObject key ifNil: [^ nil].<br>
</font></s><font color="#FF0000">+     (keyObject at: 1) ifNil: [^ nil].<br>
</font>    <br>
    properties<br>
        at: keyObject<br>
        ifPresent: [:prop | ^ prop value].<br>
    <br>
    ^ self getViaSuperclasses: keyObject<br>
<br>
<b>UserInterfaceTheme>>set:for:to: {building} · ct 5/26/2022 21:03 (changed)</b><br>
set: propertySymbol for: aClassOrSymbol to: valueObject<br>
    "Where aClass asks its userInterfaceTheme for propertySymbol, provide valueObject."<br>
    <br>
    | aClass |<br>
    aClass := aClassOrSymbol isBehavior ifTrue: [aClassOrSymbol] ifFalse: [Smalltalk classNamed: aClassOrSymbol].<br>
    aClass ifNil: [^ self].<br>
    ^ self atomicUpdate:<br>
        [ : props | | key |<br>
<s><font color="#0000FF">-         key := aClass -> propertySymbol.<br>
</font></s><font color="#FF0000">+         key := {aClass. propertySymbol}.<br>
</font>        valueObject<br>
            ifNil:<br>
                [ props<br>
                    removeKey: key<br>
                    ifAbsent: [ "already cleared, don't error" ] ]<br>
            ifNotNil:<br>
                [ props<br>
                    at: key<br>
                    put: valueObject ] ]<br>
<br>
<b>UserInterfaceThemeRequest>>doesNotUnderstand: {lookup} · ct 5/26/2022 21:02 (changed)</b><br>
doesNotUnderstand: aMessage <br>
    "Look up the visual attribute specified by aMessage's #selector in the current theme for the current target object."<br>
<br>
    aMessage numArgs = 0 ifTrue: [<br>
<s><font color="#0000FF">-         ^ (self theme get: self target class -> aMessage selector)<br>
</font></s><font color="#FF0000">+         ^ (self theme get: {self target class. aMessage selector})<br>
</font>            ifNil: [(self theme respondsTo: aMessage selector)<br>
                ifTrue: [self theme perform: aMessage selector]<br>
                ifFalse: [nil "unset property"]]].<br>
    <br>
    aMessage numArgs = 1 ifTrue: [<br>
        ^ self theme<br>
<s><font color="#0000FF">-             set: self target class -> aMessage selector asSimpleGetter<br>
</font></s><font color="#FF0000">+             set: {self target class. aMessage selector asSimpleGetter}<br>
</font>            to: aMessage arguments first].<br>
        <br>
    ^ self theme<br>
        perform: aMessage selector<br>
        withArguments: aMessage arguments.<br>
<br>
<font color="#808080">---<br>
</font><font color="#808080"><i>Sent from </i></font><font color="#808080"><i><a href="https://github.com/hpi-swa-lab/squeak-inbox-talk"><u><font color="#808080">Squeak Inbox Talk</font></u></a></i></font><br>
["accelerateUserInterfaceTheme.2.cs"]