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... |
Free forum by Nabble | Edit this page |