Thanks I will integrate that later.
(argh I should not read mails and finish that crap of file to be filled
up)
Stef
On Dec 24, 2009, at 4:50 PM, Nicolas Cellier wrote:
> 2009/12/24 Stéphane Ducasse <[email protected]>:
>> do you have a slice for pharo?
>
> http://code.google.com/p/pharo/issues/detail?id=1675
> http://code.google.com/p/pharo/issues/detail?id=1676
> http://code.google.com/p/pharo/issues/detail?id=1677
>
> And I can offer you a soda... If I ever go to Lille, prepare the beers.
>
> Nicolas
>
>> Adrian is on holidays deep in the swiss moutain with no internet
>> connection....
>> But who knows :)
>>
>> Stef
>> On Dec 24, 2009, at 11:53 AM, Nicolas Cellier wrote:
>>
>>> For Trait experts only.
>>>
>>>
>>> ---------- Forwarded message ----------
>>> From: <[email protected]>
>>> Date: 2009/12/24
>>> Subject: [squeak-dev] The Trunk: Traits-nice.248.mcz
>>> To: [email protected],
>>> [email protected]
>>>
>>>
>>> Nicolas Cellier uploaded a new version of Traits to project The Trunk:
>>> http://source.squeak.org/trunk/Traits-nice.248.mcz
>>>
>>> ==================== Summary ====================
>>>
>>> Name: Traits-nice.248
>>> Author: nice
>>> Time: 24 December 2009, 11:49:10 am
>>> UUID: 557593d7-1db7-2347-bf40-2d40e3b91f55
>>> Ancestors: Traits-nice.247
>>>
>>> Move FixedIdentitySet off the Array hierarchy.
>>> Provide a fast implementation using MethodDictionary tricks
>>> - handles collisions (instead of blindly ignoring the entry)
>>> - eventually grow.
>>>
>>> I did not understand previous design decision...
>>> The conflict just did happen (I put a halt: and caught one in Object...)
>>> According to my own scale, make it work > make it fast.
>>>
>>> Rationale about the new design:
>>> #grow costs, but I think it is user responsibility to fix a
>>> reasonnable capacity.
>>> collisions handling should not cost much (except above 4096 entries)
>>>
>>> If any expert knowing the reasons for this class and knowing how to
>>> fire the profiling tests could have a look, thanks...
>>>
>>> =============== Diff against Traits-nice.247 ===============
>>>
>>> Item was changed:
>>> + Collection variableSubclass: #FixedIdentitySet
>>> + instanceVariableNames: 'tally capacity hashShift'
>>> - Array variableSubclass: #FixedIdentitySet
>>> - instanceVariableNames: 'tally capacity'
>>> classVariableNames: ''
>>> poolDictionaries: ''
>>> category: 'Traits-Requires'!
>>>
>>> + !FixedIdentitySet commentStamp: 'nice 12/24/2009 11:46' prior: 0!
>>> + This is a fast implementation of fixed size identity sets.
>>> + Same algorithm as MethodDictionary are used, and thus
>>> FixedIdentitySet is to IdentitySet what MethodDictionary is to
>>> IdentityDictionary.
>>> + The main features are:
>>> + 1) do not use an array instance variable so as to fast-up creation
>>> and every access
>>> + 2) due to the fixed allocated size, growing costs an expensive
>>> #become: operation. Preallocate me with care.
>>> + 3) my size is a power of two so the the hashing algorithm be most
>>> efficient.
>>> + 4) for maximum random access efficiency, at least half the storage
>>> area is always kept empty
>>> - !FixedIdentitySet commentStamp: 'NS 5/26/2005 13:00' prior: 0!
>>> - This is a fast but lazy implementation of fixed size identity sets.
>>> The two main difference to regular identity sets are:
>>> -
>>> - 1) These identity sets have a fixed size. If they are full, adding
>>> another element doesn't have any effect.
>>> - 2) No rehashing. If two elements were to be stored on the same
>>> position in the underlying array, one of them is simply discarded.
>>>
>>> + Unlike MethodDictionary, this class will scale a bit better over the
>>> 4096 basicSize limit inherent to identityHash, thanks to a proper
>>> bitShift.!
>>> - As a consequence of (1) and (2), these identity sets are very fast!!
>>> Note that this class inherits form Array. This is not clean but
>>> reduces memory overhead when instances are created.!
>>>
>>> Item was added:
>>> + ----- Method: FixedIdentitySet>>removeAll (in category 'removing') -----
>>> + removeAll
>>> + tally = 0 ifTrue: [^self].
>>> + 1 to: self basicSize do: [:i | self basicAt: i put: nil].
>>> + tally := 0!
>>>
>>> Item was changed:
>>> + ----- Method: FixedIdentitySet>>add: (in category 'adding') -----
>>> - ----- Method: FixedIdentitySet>>add: (in category 'accessing') -----
>>> add: anObject
>>> + | index |
>>> + index := self scanFor: anObject.
>>> + (self basicAt: index)
>>> + ifNil: [
>>> + self basicAt: index put: anObject.
>>> + tally := tally + 1.
>>> + self isFull ifTrue: [ self grow ]]
>>> + "ifNotNil: [] already inside".
>>> + ^anObject!
>>> - | index old |
>>> - self isFull ifTrue: [^ false].
>>> - index := self indexOf: anObject.
>>> - old := self basicAt: index.
>>> - old == anObject ifTrue: [^ true].
>>> - old ifNotNil: [^ false].
>>> - self basicAt: index put: anObject.
>>> - tally := tally + 1.
>>> - ^ true!
>>>
>>> Item was changed:
>>> + ----- Method: FixedIdentitySet>>addAll:notIn: (in category 'adding') -----
>>> - ----- Method: FixedIdentitySet>>addAll:notIn: (in category 'accessing')
>>> -----
>>> addAll: aCollection notIn: notCollection
>>> aCollection do: [:each |
>>> - self isFull ifTrue: [^ self].
>>> (notCollection includes: each) ifFalse: [self add: each].
>>> ].!
>>>
>>> Item was changed:
>>> ----- Method: FixedIdentitySet class>>with:with:with:with:with: (in
>>> category 'instance creation') -----
>>> with: firstObject with: secondObject with: thirdObject with:
>>> fourthObject with: fifthObject
>>> "Answer an instance of me, containing the five arguments as the
>>> elements."
>>>
>>> + ^ (self new: 5)
>>> - ^ self new
>>> add: firstObject;
>>> add: secondObject;
>>> add: thirdObject;
>>> add: fourthObject;
>>> add: fifthObject;
>>> yourself!
>>>
>>> Item was changed:
>>> ----- Method: FixedIdentitySet class>>with:with:with:with:with:with:
>>> (in category 'instance creation') -----
>>> with: firstObject with: secondObject with: thirdObject with:
>>> fourthObject with: fifthObject with: sixthObject
>>> "Answer an instance of me, containing the six arguments as the
>>> elements."
>>>
>>> + ^ (self new: 6)
>>> - ^ self new
>>> add: firstObject;
>>> add: secondObject;
>>> add: thirdObject;
>>> add: fourthObject;
>>> add: fifthObject;
>>> add: sixthObject;
>>> yourself!
>>>
>>> Item was changed:
>>> + ----- Method: FixedIdentitySet class>>new (in category 'instance
>>> creation') -----
>>> - ----- Method: FixedIdentitySet class>>new (in category 'constants') -----
>>> new
>>> ^ self new: self defaultSize!
>>>
>>> Item was added:
>>> + ----- Method: FixedIdentitySet>>grow (in category 'private') -----
>>> + grow
>>> + | newSelf |
>>> + newSelf := self species new: capacity * 2. "This will double
>>> the capacity"
>>> + self do: [ :anObject | newSelf add: anObject ].
>>> + self become: newSelf!
>>>
>>> Item was changed:
>>> + ----- Method: FixedIdentitySet>>includes: (in category 'testing') -----
>>> + includes: aSymbol
>>> + "This override assumes that pointsTo is a fast primitive"
>>> +
>>> + aSymbol ifNil: [^ false].
>>> + ^ self pointsTo: aSymbol!
>>> - ----- Method: FixedIdentitySet>>includes: (in category 'accessing') -----
>>> - includes: anObject
>>> - ^ (self basicAt: (self indexOf: anObject)) == anObject!
>>>
>>> Item was added:
>>> + ----- Method: FixedIdentitySet>>fixCollisionsFrom: (in category
>>> 'private') -----
>>> + fixCollisionsFrom: start
>>> + "The element at start has been removed and replaced by nil.
>>> + This method moves forward from there, relocating any entries
>>> + that had been placed below due to collisions with this one."
>>> +
>>> + | key index mask |
>>> + index := start.
>>> + mask := self basicSize - 1.
>>> + [ (key := self basicAt: (index := (index bitAnd: mask) + 1))
>>> == nil ] whileFalse: [
>>> + | newIndex |
>>> + (newIndex := self scanFor: key) = index ifFalse: [
>>> + | element |
>>> + element := self basicAt: index.
>>> + self basicAt: index put: (self basicAt: newIndex).
>>> + self basicAt: newIndex put: element.] ]!
>>>
>>> Item was changed:
>>> + ----- Method: FixedIdentitySet class>>new: (in category 'instance
>>> creation') -----
>>> - ----- Method: FixedIdentitySet class>>new: (in category 'constants') -----
>>> new: anInteger
>>> + ^ (self basicNew: (self arraySizeForCapacity: anInteger))
>>> initializeCapacity: anInteger!
>>> - ^ (super new: (self arraySizeForCapacity: anInteger))
>>> initializeCapacity: anInteger!
>>>
>>> Item was changed:
>>> + ----- Method: FixedIdentitySet>>remove:ifAbsent: (in category
>>> 'removing') -----
>>> - ----- Method: FixedIdentitySet>>remove:ifAbsent: (in category
>>> 'accessing') -----
>>> remove: anObject ifAbsent: aBlock
>>> + | index element |
>>> + index := self scanFor: anObject.
>>> + (element := self basicAt: index) ifNil: [ ^aBlock value ].
>>> + self basicAt: index put: nil.
>>> + tally := tally - 1.
>>> + self fixCollisionsFrom: index.
>>> + ^element!
>>> - | index |
>>> - index := self indexOf: anObject.
>>> - ^ (self basicAt: index) == anObject
>>> - ifTrue: [self basicAt: index put: nil. tally := tally
>>> - 1. anObject]
>>> - ifFalse: [aBlock value].!
>>>
>>> Item was added:
>>> + ----- Method: FixedIdentitySet>>rehash (in category 'private') -----
>>> + rehash
>>> + | newSelf |
>>> + newSelf := self species new: self size.
>>> + self do: [ :anObject | newSelf add: anObject ].
>>> + ^newSelf!
>>>
>>> Item was changed:
>>> ----- Method: FixedIdentitySet>>initializeCapacity: (in category
>>> 'initialize-release') -----
>>> initializeCapacity: anInteger
>>> tally := 0.
>>> + capacity := anInteger.
>>> + hashShift := self basicSize highBit - 4096 highBit max: 0!
>>> - capacity := anInteger.!
>>>
>>> Item was changed:
>>> + ----- Method: FixedIdentitySet class>>arraySizeForCapacity: (in
>>> category 'private') -----
>>> - ----- Method: FixedIdentitySet class>>arraySizeForCapacity: (in
>>> category 'constants') -----
>>> arraySizeForCapacity: anInteger
>>> "Because of the hash performance, the array size is always a power
>>> of 2
>>> and at least twice as big as the capacity anInteger"
>>>
>>> ^ anInteger <= 0
>>> ifTrue: [0]
>>> ifFalse: [1 << (anInteger << 1 - 1) highBit].!
>>>
>>> Item was added:
>>> + ----- Method: FixedIdentitySet>>scanFor: (in category 'private') -----
>>> + scanFor: anObject
>>> + "Scan the key array for the first slot containing either a nil
>>> (indicating an empty slot) or an element that matches anObject. Answer
>>> the index of that slot or raise an error if no slot is found. This
>>> method will be overridden in various subclasses that have different
>>> interpretations for matching elements."
>>> +
>>> + | index start mask |
>>> + anObject ifNil: [self error: 'This class collection cannot
>>> handle nil as an element'].
>>> + mask := self basicSize - 1.
>>> + index := start := ((anObject identityHash bitShift: hashShift)
>>> bitAnd: mask) + 1.
>>> + [
>>> + | element |
>>> + ((element := self basicAt: index) == nil or: [ element
>>> == anObject ])
>>> + ifTrue: [ ^index ].
>>> + (index := (index bitAnd: mask) + 1) = start ] whileFalse.
>>> + self errorNoFreeSpace!
>>>
>>> Item was removed:
>>> - ----- Method: FixedIdentitySet>>destructiveAdd: (in category
>>> 'accessing') -----
>>> - destructiveAdd: anObject
>>> - | index old |
>>> - self isFull ifTrue: [^ false].
>>> - index := self indexOf: anObject.
>>> - old := self basicAt: index.
>>> - self basicAt: index put: anObject.
>>> - old ifNil: [tally := tally + 1].
>>> - ^ true!
>>>
>>> Item was removed:
>>> - ----- Method: FixedIdentitySet>>notFull (in category 'testing') -----
>>> - notFull
>>> - ^ tally < capacity!
>>>
>>> Item was removed:
>>> - ----- Method: FixedIdentitySet>>addAll: (in category 'accessing') -----
>>> - addAll: aCollection
>>> - aCollection do: [:each |
>>> - self isFull ifTrue: [^ self].
>>> - self add: each.
>>> - ].!
>>>
>>> Item was removed:
>>> - ----- Method: FixedIdentitySet>>indexOf: (in category 'private') -----
>>> - indexOf: anObject
>>> - anObject isNil ifTrue: [self error: 'This class collection
>>> cannot handle nil as an element'].
>>> - ^ (anObject identityHash bitAnd: self basicSize - 1) + 1!
>>>
>>> _______________________________________________
>>> Pharo-project mailing list
>>> [email protected]
>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>
>>
>> _______________________________________________
>> Pharo-project mailing list
>> [email protected]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>
>
> _______________________________________________
> Pharo-project mailing list
> [email protected]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project