Recompile slows down the compiler
Klaus D. Witzel
klaus.witzel at cobss.com
Sat Oct 21 10:06:06 UTC 2006
A strange performance problem happens when methods which refer to "global"
variables (classVars, for example) are recompiled *after* the variable in
question is initialized to a *large* collection.
The sequence of message sends is
1) Parser>>variable
2) Encoder>>encodeVariable:sourceRange:ifUnknown:
3) Encoder>>global:name:
and a full trace is below. This example results in a #hash (1 to: 917632
do: ... hashMultiply) of a SparseLargeTable(SequenceableCollection) for
every occurence of the class variable in the source text.
The reason for this particular slowdown is the use of Association>>#hash
which hashes its key xOr its value (and the latter is the *very* *large*
collection).
Any suggestions? Wouldn't it be sufficient to use the name of the class
var, instead of the literal variable (the association).
/Klaus
P.S. reproducible, for example by filing out a method of Unicode class
which accesses the GeneralCategory variable, then opening a code browser
on that file (I'm using the tools and settings of the current
squeak-dev-41.image).
--------------------------
VM: Win32 - a SmalltalkImage
Image: Squeak3.9gamma [latest update: #7065]
SecurityManager state:
Restricted: false
FileAccess: true
SocketAccess: true
Working Dir ...\kWitzel\My Documents\SqueakDev
Trusted Dir ...\kWitzel\My Documents\SqueakDev\kWitzel
Untrusted Dir ...\My Squeak\kWitzel
SmallInteger>>hashMultiply
Receiver: 37545126
Arguments and temporary variables:
low: nil
Receiver's instance variables:
37545126
SparseLargeTable(SequenceableCollection)>>hash
Receiver: a SparseLargeTable(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 29 21 2...etc...
Arguments and temporary variables:
hash: 37545126
i: 670022
iLimiT: 917632
Receiver's instance variables:
base: 1
size: 917632
chunkSize: 1024
defaultValue: 0
Association>>hash
Receiver: #GeneralCategory->a SparseLargeTable(1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1...etc...
Arguments and temporary variables:
Receiver's instance variables:
key: #GeneralCategory
value: a SparseLargeTable(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1...etc...
Dictionary>>scanFor:
Receiver: a Dictionary()
Arguments and temporary variables:
anObject: #GeneralCategory->a SparseLargeTable(1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 ...etc...
element: nil
start: nil
finish: 22
index: nil
indexLimiT: nil
Receiver's instance variables:
tally: 0
array: #(nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil ni...etc...
--- The full stack ---
SmallInteger>>hashMultiply
SparseLargeTable(SequenceableCollection)>>hash
Association>>hash
Dictionary>>scanFor:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dictionary(Set)>>findElementOrNil:
Dictionary>>at:ifAbsent:
Encoder>>name:key:class:type:set:
Encoder>>global:name:
[] in Encoder>>encodeVariable:sourceRange:ifUnknown: {[:assoc | varNode :=
self global: assoc name: name]}
[] in Encoder>>lookupInPools:ifFound: {[:assoc | assocBlock value:
assoc. ^ true]}
Association(Object)>>ifNotNilDo:
[] in Encoder>>lookupInPools:ifFound: {[:sym | (class bindingOf: sym)
ifNotNilDo: [:assoc | assocBlock value...]}
Symbol class>>hasInterned:ifTrue:
Encoder>>lookupInPools:ifFound:
[] in Encoder>>encodeVariable:sourceRange:ifUnknown: {[(self
lookupInPools: name ifFound: [:assoc | varNode := self global: ...]}
Dictionary>>at:ifAbsent:
Encoder>>encodeVariable:sourceRange:ifUnknown:
Parser>>variable
Parser>>primaryExpression
Parser>>expression
Parser>>primaryExpression
Parser>>messagePart:repeat:
Parser>>expression
Parser>>statements:innerBlock:
Parser>>method:context:encoder:
[] in Parser>>parse:class:noPattern:context:notifying:ifFail: {[methNode
:= self method: noPattern context: ctxt encoder: (Enco...]}
BlockContext>>on:do:
Parser>>parse:class:noPattern:context:notifying:ifFail:
Compiler>>format:noPattern:ifFail:
Compiler>>format:in:notifying:decorated:
Compiler class>>format:in:notifying:decorated:
[] in PrettyTextDiffBuilder>>split: {[sourceClass prettyPrinterClass
format: trimmed in: sourceClass notify...]}
BlockContext>>on:do:
PrettyTextDiffBuilder>>split:
PrettyTextDiffBuilder(TextDiffBuilder)>>sourceString:
PrettyTextDiffBuilder(TextDiffBuilder)>>from:to:
PrettyTextDiffBuilder class>>from:to:inClass:
TextDiffBuilder class>>buildDisplayPatchFrom:to:inClass:prettyDiffs:
[] in FileContentsBrowser>>methodDiffFor:class:selector:meta:
{[TextDiffBuilder buildDisplayPatchFrom: source to: aString inClass:
th...]}
BlockContext>>ensure:
CursorWithMask(Cursor)>>showWhile:
FileContentsBrowser>>methodDiffFor:class:selector:meta:
FileContentsBrowser>>extraInfo
FileContentsBrowser>>infoViewContents
PluggableTextMorph>>getText
PluggableTextMorph>>update:
[] in FileContentsBrowser(Object)>>changed: {[:aDependent | aDependent
update: aParameter]}
DependentsArray>>do:
FileContentsBrowser(Object)>>changed:
FileContentsBrowser>>updateInfoView
FileContentsBrowser>>contents
PluggableShoutMorph(PluggableTextMorph)>>getText
PluggableShoutMorph(PluggableTextMorph)>>update:
[] in FileContentsBrowser(Object)>>changed: {[:aDependent | aDependent
update: aParameter]}
DependentsArray>>do:
FileContentsBrowser(Object)>>changed:
FileContentsBrowser(Object)>>contentsChanged
FileContentsBrowser(CodeHolder)>>contentsChanged
...etc...
More information about the Squeak-dev
mailing list
|