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

Reply via email to