WideString hash is way slower than ByteString hash.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

WideString hash is way slower than ByteString hash.

christophe.jalady
Just print this two scripts:

|s|
s := WideString with: (Character value: 16r55E4).
[100000 timesRepeat: [s hash]] timeToRun.

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value: 16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000 timesRepeat: [s hash]] timeToRun.

I've seen that "ByteString>>stringHash:initialHash" use a primitive. Could we
have such optimisation for WideString ?

Christophe.

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Levente Uzonyi-2
On Fri, 14 May 2010, [hidden email] wrote:

> Just print this two scripts:
>
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000 timesRepeat: [s hash]] timeToRun.
>
> |s|
> s := ByteString with: (Character value: 16rE4) with: (Character value: 16rE4)
> with: (Character value: 16rE4) with: (Character value: 16rE4).
> [100000 timesRepeat: [s hash]] timeToRun.
>
> I've seen that "ByteString>>stringHash:initialHash" use a primitive. Could we
> have such optimisation for WideString ?

Sure. There are (at least) four ways to do it:
1) Update the implementation of the primitive to support wordarrays. Then
build a vm with it and finally change the image side code. This would be
the best IMHO. Is there a reason why the primitive is not implemented this
way?
2) Use NativeBoost to write a primitive for this method. This is much
easier than building a vm/plugin, though you have to write the code in X86
assembly. This would be a cool demo for NativeBoost's primitive writing
capabilities. (Much better than the Fibonacci-number calculator. :))
3) Use Exupery, I think it can optimize methods like this.
4) Use the Cog VM. ;) (I wonder how fast this method is with Cog.)


Levente

>
> Christophe.
>
>

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Hannes Hirzel
On 5/14/10, Levente Uzonyi <[hidden email]> wrote:

> On Fri, 14 May 2010, [hidden email] wrote:
>
>> Just print this two scripts:
>>
>> |s|
>> s := WideString with: (Character value: 16r55E4).
>> [100000 timesRepeat: [s hash]] timeToRun.
>>
>> |s|
>> s := ByteString with: (Character value: 16rE4) with: (Character value:
>> 16rE4)
>> with: (Character value: 16rE4) with: (Character value: 16rE4).
>> [100000 timesRepeat: [s hash]] timeToRun.
>>
>> I've seen that "ByteString>>stringHash:initialHash" use a primitive. Could
>> we
>> have such optimisation for WideString ?



> Sure. There are (at least) four ways to do it:
> 1) Update the implementation of the primitive to support wordarrays. Then
> build a vm with it and finally change the image side code. This would be
> the best IMHO. Is there a reason why the primitive is not implemented this
> way?

If this is not a work you feel comfortable with then post this on the
VM developer list and/or create a Mantis entry.

> 2) Use NativeBoost to write a primitive for this method. This is much
> easier than building a vm/plugin, though you have to write the code in X86
> assembly. This would be a cool demo for NativeBoost's primitive writing
> capabilities. (Much better than the Fibonacci-number calculator. :))

Yes, this would be a very good demonstration.


> 3) Use Exupery, I think it can optimize methods like this.
> 4) Use the Cog VM. ;) (I wonder how fast this method is with Cog.)
What kind of VM are we using in 4.1? It supports closures, but
seeminly is not the Cog VM(yet)?


Hannes

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Eliot Miranda-2
In reply to this post by Levente Uzonyi-2


On Fri, May 14, 2010 at 10:28 AM, Levente Uzonyi <[hidden email]> wrote:
On Fri, 14 May 2010, [hidden email] wrote:

Just print this two scripts:

|s|
s := WideString with: (Character value: 16r55E4).
[100000 timesRepeat: [s hash]] timeToRun.

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value: 16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000 timesRepeat: [s hash]] timeToRun.

I've seen that "ByteString>>stringHash:initialHash" use a primitive. Could we
have such optimisation for WideString ?

Sure. There are (at least) four ways to do it:
1) Update the implementation of the primitive to support wordarrays. Then build a vm with it and finally change the image side code. This would be the best IMHO. Is there a reason why the primitive is not implemented this way?
2) Use NativeBoost to write a primitive for this method. This is much easier than building a vm/plugin, though you have to write the code in X86 assembly. This would be a cool demo for NativeBoost's primitive writing capabilities. (Much better than the Fibonacci-number calculator. :))
3) Use Exupery, I think it can optimize methods like this.
4) Use the Cog VM. ;) (I wonder how fast this method is with Cog.)

2.66GHz Intel Core i7 MacBook Pro (my new tool!!!!).  Current Cog, my 3.8 derived work image:

|s|
s := WideString with: (Character value: 16r55E4).
[100000 timesRepeat: [s hash]] timeToRun. 16

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value: 16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000 timesRepeat: [s hash]] timeToRun. 10

|s|
s := WideString with: (Character value: 16r55E4).
[100000000 timesRepeat: [s hash]] timeToRun. 15725

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value: 16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000000 timesRepeat: [s hash]] timeToRun. 11078


Current 4.1/Squeak 4.1.1beta2U.app:
|s|
s := WideString with: (Character value: 16r55E4).
[100000 timesRepeat: [s hash]] timeToRun. 98

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value: 16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000 timesRepeat: [s hash]] timeToRun. 31

|s|
s := WideString with: (Character value: 16r55E4).
[100000000 timesRepeat: [s hash]] timeToRun. 100660

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value: 16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000000 timesRepeat: [s hash]] timeToRun. 29476

Current 4.1/current Cog
|s|
s := WideString with: (Character value: 16r55E4).
[100000 timesRepeat: [s hash]] timeToRun. 14

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value: 16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000 timesRepeat: [s hash]] timeToRun. 10

|s|
s := WideString with: (Character value: 16r55E4).
[100000000 timesRepeat: [s hash]] timeToRun. 14946

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value: 16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000000 timesRepeat: [s hash]] timeToRun. 10171

So quite a bit faster :)

best
Eliot



Levente


Christophe.






Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Levente Uzonyi-2
On Fri, 14 May 2010, Eliot Miranda wrote:

> On Fri, May 14, 2010 at 10:28 AM, Levente Uzonyi <[hidden email]> wrote:
>
>> On Fri, 14 May 2010, [hidden email] wrote:
>>
>>  Just print this two scripts:
>>>
>>> |s|
>>> s := WideString with: (Character value: 16r55E4).
>>> [100000 timesRepeat: [s hash]] timeToRun.
>>>
>>> |s|
>>> s := ByteString with: (Character value: 16rE4) with: (Character value:
>>> 16rE4)
>>> with: (Character value: 16rE4) with: (Character value: 16rE4).
>>> [100000 timesRepeat: [s hash]] timeToRun.
>>>
>>> I've seen that "ByteString>>stringHash:initialHash" use a primitive. Could
>>> we
>>> have such optimisation for WideString ?
>>>
>>
>> Sure. There are (at least) four ways to do it:
>> 1) Update the implementation of the primitive to support wordarrays. Then
>> build a vm with it and finally change the image side code. This would be the
>> best IMHO. Is there a reason why the primitive is not implemented this way?
>> 2) Use NativeBoost to write a primitive for this method. This is much
>> easier than building a vm/plugin, though you have to write the code in X86
>> assembly. This would be a cool demo for NativeBoost's primitive writing
>> capabilities. (Much better than the Fibonacci-number calculator. :))
>> 3) Use Exupery, I think it can optimize methods like this.
>> 4) Use the Cog VM. ;) (I wonder how fast this method is with Cog.)
>>
>
> 2.66GHz Intel Core i7 MacBook Pro (my new tool!!!!).  Current Cog, my 3.8
> derived work image:
>
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000 timesRepeat: [s hash]] timeToRun. 16
>
> |s|
> s := ByteString with: (Character value: 16rE4) with: (Character value:
> 16rE4)
> with: (Character value: 16rE4) with: (Character value: 16rE4).
> [100000 timesRepeat: [s hash]] timeToRun. 10
>
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000000 timesRepeat: [s hash]] timeToRun. 15725
>
> |s|
> s := ByteString with: (Character value: 16rE4) with: (Character value:
> 16rE4)
> with: (Character value: 16rE4) with: (Character value: 16rE4).
> [100000000 timesRepeat: [s hash]] timeToRun. 11078
>
>
> Current 4.1/Squeak 4.1.1beta2U.app:
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000 timesRepeat: [s hash]] timeToRun. 98
>
> |s|
> s := ByteString with: (Character value: 16rE4) with: (Character value:
> 16rE4)
> with: (Character value: 16rE4) with: (Character value: 16rE4).
> [100000 timesRepeat: [s hash]] timeToRun. 31
>
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000000 timesRepeat: [s hash]] timeToRun. 100660
>
> |s|
> s := ByteString with: (Character value: 16rE4) with: (Character value:
> 16rE4)
> with: (Character value: 16rE4) with: (Character value: 16rE4).
> [100000000 timesRepeat: [s hash]] timeToRun. 29476
>
> Current 4.1/current Cog
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000 timesRepeat: [s hash]] timeToRun. 14
>
> |s|
> s := ByteString with: (Character value: 16rE4) with: (Character value:
> 16rE4)
> with: (Character value: 16rE4) with: (Character value: 16rE4).
> [100000 timesRepeat: [s hash]] timeToRun. 10
>
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000000 timesRepeat: [s hash]] timeToRun. 14946
>
> |s|
> s := ByteString with: (Character value: 16rE4) with: (Character value:
> 16rE4)
> with: (Character value: 16rE4) with: (Character value: 16rE4).
> [100000000 timesRepeat: [s hash]] timeToRun. 10171
>
> So quite a bit faster :)

Thanks, it looks really nice. I wonder why are the results with 4.1 better
than with your 3.8 derived image.


Levente

>
> best
> Eliot
>
>
>>
>> Levente
>>
>>
>>> Christophe.
>>>
>>>
>>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Eliot Miranda-2


On Fri, May 14, 2010 at 1:03 PM, Levente Uzonyi <[hidden email]> wrote:
On Fri, 14 May 2010, Eliot Miranda wrote:

On Fri, May 14, 2010 at 10:28 AM, Levente Uzonyi <[hidden email]> wrote:

On Fri, 14 May 2010, [hidden email] wrote:

 Just print this two scripts:

|s|
s := WideString with: (Character value: 16r55E4).
[100000 timesRepeat: [s hash]] timeToRun.

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value:
16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000 timesRepeat: [s hash]] timeToRun.

I've seen that "ByteString>>stringHash:initialHash" use a primitive. Could
we
have such optimisation for WideString ?


Sure. There are (at least) four ways to do it:
1) Update the implementation of the primitive to support wordarrays. Then
build a vm with it and finally change the image side code. This would be the
best IMHO. Is there a reason why the primitive is not implemented this way?
2) Use NativeBoost to write a primitive for this method. This is much
easier than building a vm/plugin, though you have to write the code in X86
assembly. This would be a cool demo for NativeBoost's primitive writing
capabilities. (Much better than the Fibonacci-number calculator. :))
3) Use Exupery, I think it can optimize methods like this.
4) Use the Cog VM. ;) (I wonder how fast this method is with Cog.)


2.66GHz Intel Core i7 MacBook Pro (my new tool!!!!).  Current Cog, my 3.8
derived work image:

|s|
s := WideString with: (Character value: 16r55E4).
[100000 timesRepeat: [s hash]] timeToRun. 16

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value:
16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000 timesRepeat: [s hash]] timeToRun. 10

|s|
s := WideString with: (Character value: 16r55E4).
[100000000 timesRepeat: [s hash]] timeToRun. 15725

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value:
16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000000 timesRepeat: [s hash]] timeToRun. 11078


Current 4.1/Squeak 4.1.1beta2U.app:
|s|
s := WideString with: (Character value: 16r55E4).
[100000 timesRepeat: [s hash]] timeToRun. 98

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value:
16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000 timesRepeat: [s hash]] timeToRun. 31

|s|
s := WideString with: (Character value: 16r55E4).
[100000000 timesRepeat: [s hash]] timeToRun. 100660

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value:
16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000000 timesRepeat: [s hash]] timeToRun. 29476

Current 4.1/current Cog
|s|
s := WideString with: (Character value: 16r55E4).
[100000 timesRepeat: [s hash]] timeToRun. 14

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value:
16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000 timesRepeat: [s hash]] timeToRun. 10

|s|
s := WideString with: (Character value: 16r55E4).
[100000000 timesRepeat: [s hash]] timeToRun. 14946

|s|
s := ByteString with: (Character value: 16rE4) with: (Character value:
16rE4)
with: (Character value: 16rE4) with: (Character value: 16rE4).
[100000000 timesRepeat: [s hash]] timeToRun. 10171

So quite a bit faster :)

Thanks, it looks really nice. I wonder why are the results with 4.1 better than with your 3.8 derived image.

The code looks the same and so I expect the times are close enough to be in the noise.  I didn't shut my machine down to a consistent state so other tasks could have affected things, etc.



Levente


best
Eliot



Levente


Christophe.









Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Igor Stasenko
In reply to this post by Eliot Miranda-2
I implemented WideString hash in NB.

|s|
s := WideString with: (Character value: 16r55E4).
[100000000 timesRepeat: [s hash]] timeToRun. 155718


|s|
s := WideString with: (Character value: 16r55E4).
[100000000 timesRepeat: [s nbHash]] timeToRun.  81231

Which makes me think, that we're benching the outer loop, rather then
hash function itself :)

So, here is more appropriate , i think:

|s t1 t2 |
s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
10 timesRepeat: [ s := s , s ].
self assert: (s hash = s nbHash).
t1 := [1000 timesRepeat: [s hash]] timeToRun.
t2 := [1000 timesRepeat: [s nbHash]] timeToRun.

{ t1. t2 }
 #(11479 134)

~ 85x faster :)


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Igor Stasenko
added implementation into examples package:
http://www.squeaksource.com/NativeBoost/NativeBoost-Examples-Igor.Stasenko.1.mcz

On 15 May 2010 01:14, Igor Stasenko <[hidden email]> wrote:

> I implemented WideString hash in NB.
>
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000000 timesRepeat: [s hash]] timeToRun. 155718
>
>
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000000 timesRepeat: [s nbHash]] timeToRun.  81231
>
> Which makes me think, that we're benching the outer loop, rather then
> hash function itself :)
>
> So, here is more appropriate , i think:
>
> |s t1 t2 |
> s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
> 10 timesRepeat: [ s := s , s ].
> self assert: (s hash = s nbHash).
> t1 := [1000 timesRepeat: [s hash]] timeToRun.
> t2 := [1000 timesRepeat: [s nbHash]] timeToRun.
>
> { t1. t2 }
>  #(11479 134)
>
> ~ 85x faster :)
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Igor Stasenko
Oh, yeah..
i forgot to hash the strings.. for comparison:

|ss s t1 t2 t3 |
s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
ss := (String with: $z) , 'abcdefghijklmno'.

10 timesRepeat: [ s := s , s. ss := ss , ss ].
self assert: (s hash = s nbHash).
t1 := [1000 timesRepeat: [s hash]] timeToRun.
t2 := [1000 timesRepeat: [s nbHash]] timeToRun.
t3 := [1000 timesRepeat: [ss hash]] timeToRun.
{ t1. t2. t3 }
 #(11477 134 190)

so, WideString>>nbHash outperforms ByteString>>hash a little, for same
string sizes. ;)

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Eliot Miranda-2
Hi Igor,

    is the NB implementation mapping the character codes in the wide strings into Character objects and taking the character hashes?  If so, very cool.  The NB code is very fast.  If on the other hand you're just short-circuiting the character code lookup then you're cheating :)

On Fri, May 14, 2010 at 3:31 PM, Igor Stasenko <[hidden email]> wrote:
Oh, yeah..
i forgot to hash the strings.. for comparison:

|ss s t1 t2 t3 |
s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
ss := (String with: $z) , 'abcdefghijklmno'.

10 timesRepeat: [ s := s , s. ss := ss , ss ].
self assert: (s hash = s nbHash).
t1 := [1000 timesRepeat: [s hash]] timeToRun.
t2 := [1000 timesRepeat: [s nbHash]] timeToRun.
t3 := [1000 timesRepeat: [ss hash]] timeToRun.
{ t1. t2. t3 }
 #(11477 134 190)

so, WideString>>nbHash outperforms ByteString>>hash a little, for same
string sizes. ;)

--
Best regards,
Igor Stasenko AKA sig.




Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

christophe.jalady
In reply to this post by Igor Stasenko
Should the hash function be the same between ByteString and WideString ?
I mean: if a WideString contains the same characters than a ByteString, I guess that they should have both the same hashcode no ?

Christophe


----- Mail Original -----
De: "Igor Stasenko" <[hidden email]>
À: "The general-purpose Squeak developers list" <[hidden email]>
Envoyé: Samedi 15 Mai 2010 00h26:18 GMT +01:00 Amsterdam / Berlin / Berne / Rome / Stockholm / Vienne
Objet: Re: [squeak-dev] WideString hash is way slower than ByteString hash.

added implementation into examples package:
http://www.squeaksource.com/NativeBoost/NativeBoost-Examples-Igor.Stasenko.1.mcz

On 15 May 2010 01:14, Igor Stasenko <[hidden email]> wrote:

> I implemented WideString hash in NB.
>
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000000 timesRepeat: [s hash]] timeToRun. 155718
>
>
> |s|
> s := WideString with: (Character value: 16r55E4).
> [100000000 timesRepeat: [s nbHash]] timeToRun.  81231
>
> Which makes me think, that we're benching the outer loop, rather then
> hash function itself :)
>
> So, here is more appropriate , i think:
>
> |s t1 t2 |
> s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
> 10 timesRepeat: [ s := s , s ].
> self assert: (s hash = s nbHash).
> t1 := [1000 timesRepeat: [s hash]] timeToRun.
> t2 := [1000 timesRepeat: [s nbHash]] timeToRun.
>
> { t1. t2 }
>  #(11479 134)
>
> ~ 85x faster :)
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.


Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Igor Stasenko
In reply to this post by Eliot Miranda-2
On 15 May 2010 01:38, Eliot Miranda <[hidden email]> wrote:
> Hi Igor,
>     is the NB implementation mapping the character codes in the wide strings
> into Character objects and taking the character hashes?  If so, very cool.
>  The NB code is very fast.  If on the other hand you're just
> short-circuiting the character code lookup then you're cheating :)
>
What mapping you have in mind?

WideString>>at: index
        "Answer the Character stored in the field of the receiver indexed by
the argument."
        ^ Character value: (self wordAt: index).

Character class>>value: anInteger
        "Answer the Character whose value is anInteger."

        anInteger > 255 ifTrue: [^self basicNew setValue: anInteger].
        ^ CharacterTable at: anInteger + 1.

(Character classPool at: #CharacterTable) withIndexDo: [:ch :i | self
assert: (ch asInteger = (i-1))]

So, it is 1:1 correspondence between word, stored in wide string (self
wordAt: index),
and Character value, used for hashing. So, no mapping required.


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Levente Uzonyi-2
In reply to this post by christophe.jalady
On Sat, 15 May 2010, [hidden email] wrote:

> Should the hash function be the same between ByteString and WideString ?
> I mean: if a WideString contains the same characters than a ByteString, I guess that they should have both the same hashcode no ?

Yes, they should be the same. And they are the same, aren't they?


Levente

>
> Christophe
>
>
> ----- Mail Original -----
> De: "Igor Stasenko" <[hidden email]>
> ˙˙: "The general-purpose Squeak developers list" <[hidden email]>
> Envoyé: Samedi 15 Mai 2010 00h26:18 GMT +01:00 Amsterdam / Berlin / Berne / Rome / Stockholm / Vienne
> Objet: Re: [squeak-dev] WideString hash is way slower than ByteString hash.
>
> added implementation into examples package:
> http://www.squeaksource.com/NativeBoost/NativeBoost-Examples-Igor.Stasenko.1.mcz
>
> On 15 May 2010 01:14, Igor Stasenko <[hidden email]> wrote:
>> I implemented WideString hash in NB.
>>
>> |s|
>> s := WideString with: (Character value: 16r55E4).
>> [100000000 timesRepeat: [s hash]] timeToRun. 155718
>>
>>
>> |s|
>> s := WideString with: (Character value: 16r55E4).
>> [100000000 timesRepeat: [s nbHash]] timeToRun.  81231
>>
>> Which makes me think, that we're benching the outer loop, rather then
>> hash function itself :)
>>
>> So, here is more appropriate , i think:
>>
>> |s t1 t2 |
>> s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
>> 10 timesRepeat: [ s := s , s ].
>> self assert: (s hash = s nbHash).
>> t1 := [1000 timesRepeat: [s hash]] timeToRun.
>> t2 := [1000 timesRepeat: [s nbHash]] timeToRun.
>>
>> { t1. t2 }
>>  #(11479 134)
>>
>> ~ 85x faster :)
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Igor Stasenko
In reply to this post by christophe.jalady
On 15 May 2010 01:53,  <[hidden email]> wrote:
> Should the hash function be the same between ByteString and WideString ?
> I mean: if a WideString contains the same characters than a ByteString, I guess that they should have both the same hashcode no ?
>
Seems so.

|s |
s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
s at: 1 put: $a.
s class. WideString
s nbHash. 196130722
s nbHash 196130722
'aabcdefghijklmno' hash 196130722




--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Igor Stasenko
In reply to this post by Igor Stasenko
And besides, if someone would bother implementing a primitive
for hasing the WideString, i doubt that he will go and create
an instances of Character for each indice, and then read its value and
only then use
it for hashing.
So, i don't think this is cheating. Its just an optimization :)
Of course, Cog , even if it optimize things cleverly, still has to
follow a code, and should create a real instances of Character,
simply because it is written so, and it should honor the language semantics.


On 15 May 2010 01:53, Igor Stasenko <[hidden email]> wrote:

> On 15 May 2010 01:38, Eliot Miranda <[hidden email]> wrote:
>> Hi Igor,
>>     is the NB implementation mapping the character codes in the wide strings
>> into Character objects and taking the character hashes?  If so, very cool.
>>  The NB code is very fast.  If on the other hand you're just
>> short-circuiting the character code lookup then you're cheating :)
>>
> What mapping you have in mind?
>
> WideString>>at: index
>        "Answer the Character stored in the field of the receiver indexed by
> the argument."
>        ^ Character value: (self wordAt: index).
>
> Character class>>value: anInteger
>        "Answer the Character whose value is anInteger."
>
>        anInteger > 255 ifTrue: [^self basicNew setValue: anInteger].
>        ^ CharacterTable at: anInteger + 1.
>
> (Character classPool at: #CharacterTable) withIndexDo: [:ch :i | self
> assert: (ch asInteger = (i-1))]
>
> So, it is 1:1 correspondence between word, stored in wide string (self
> wordAt: index),
> and Character value, used for hashing. So, no mapping required.
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Eliot Miranda-2
The cardinal rule of running benchmarks is to compare apples to apples.  You've compared apples to oranges, i.e. an optimized reimplementation of WideString>>hash that eliminates the mapping of codes to characters, against the vanilla Squeak implementation.  You need to at least compare the NB implementation against

WideString methods for comparison
fastHash
| stringSize hash low |
stringSize := self size.
hash := ByteString identityHash bitAnd: 16rFFFFFFF.
1 to: stringSize do: [:pos |
hash := hash + (self wordAt: pos).
"Begin hashMultiply"
low := hash bitAnd: 16383.
hash := (16r260D * low + ((16r260D * (hash bitShift: -14) + (16r0065 * low) bitAnd: 16383) * 16384)) bitAnd: 16r0FFFFFFF.
].
^ hash

| s n |
s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
n := 100000.
{ [1 to: n do: [:i| s fastHash. s fastHash. s fastHash. s fastHash. s fastHash. s fastHash. s fastHash. s fastHash. s fastHash. s fastHash]] timeToRun.
 [1 to: n do: [:i| s hash. s hash. s hash. s hash. s hash. s hash. s hash. s hash. s hash. s hash]] timeToRun. }

     #(829 1254)

ASo your measurements tell us nothing about a general comparison of NB against the Squeak VM or Cog.  They only demonstrate (unsurprisingly) that a loop summing integers in an array goes PDQ.  On the other hand my numbers showed Cog 10x faster than the Squeak interpreter when executing exactly the same bytecode.

best
Eliot


On Fri, May 14, 2010 at 4:13 PM, Igor Stasenko <[hidden email]> wrote:
And besides, if someone would bother implementing a primitive
for hasing the WideString, i doubt that he will go and create
an instances of Character for each indice, and then read its value and
only then use
it for hashing.
So, i don't think this is cheating. Its just an optimization :)
Of course, Cog , even if it optimize things cleverly, still has to
follow a code, and should create a real instances of Character,
simply because it is written so, and it should honor the language semantics.


On 15 May 2010 01:53, Igor Stasenko <[hidden email]> wrote:
> On 15 May 2010 01:38, Eliot Miranda <[hidden email]> wrote:
>> Hi Igor,
>>     is the NB implementation mapping the character codes in the wide strings
>> into Character objects and taking the character hashes?  If so, very cool.
>>  The NB code is very fast.  If on the other hand you're just
>> short-circuiting the character code lookup then you're cheating :)
>>
> What mapping you have in mind?
>
> WideString>>at: index
>        "Answer the Character stored in the field of the receiver indexed by
> the argument."
>        ^ Character value: (self wordAt: index).
>
> Character class>>value: anInteger
>        "Answer the Character whose value is anInteger."
>
>        anInteger > 255 ifTrue: [^self basicNew setValue: anInteger].
>        ^ CharacterTable at: anInteger + 1.
>
> (Character classPool at: #CharacterTable) withIndexDo: [:ch :i | self
> assert: (ch asInteger = (i-1))]
>
> So, it is 1:1 correspondence between word, stored in wide string (self
> wordAt: index),
> and Character value, used for hashing. So, no mapping required.
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.




Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Igor Stasenko
On 15 May 2010 02:35, Eliot Miranda <[hidden email]> wrote:

> The cardinal rule of running benchmarks is to compare apples to apples.
>  You've compared apples to oranges, i.e. an optimized reimplementation of
> WideString>>hash that eliminates the mapping of codes to characters, against
> the vanilla Squeak implementation.  You need to at least compare the NB
> implementation against
> WideString methods for comparison
> fastHash
> | stringSize hash low |
> stringSize := self size.
> hash := ByteString identityHash bitAnd: 16rFFFFFFF.
> 1 to: stringSize do: [:pos |
> hash := hash + (self wordAt: pos).
> "Begin hashMultiply"
> low := hash bitAnd: 16383.
> hash := (16r260D * low + ((16r260D * (hash bitShift: -14) + (16r0065 * low)
> bitAnd: 16383) * 16384)) bitAnd: 16r0FFFFFFF.
> ].
> ^ hash
> | s n |
> s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
> n := 100000.
> { [1 to: n do: [:i| s fastHash. s fastHash. s fastHash. s fastHash. s
> fastHash. s fastHash. s fastHash. s fastHash. s fastHash. s fastHash]]
> timeToRun.
>  [1 to: n do: [:i| s hash. s hash. s hash. s hash. s hash. s hash. s hash. s
> hash. s hash. s hash]] timeToRun. }
>      #(829 1254)
> ASo your measurements tell us nothing about a general comparison of NB
> against the Squeak VM or Cog.  They only demonstrate (unsurprisingly) that a
> loop summing integers in an array goes PDQ.  On the other hand my numbers
> showed Cog 10x faster than the Squeak interpreter when executing exactly the
> same bytecode.

Yes, of course you're right.
But i didn't compared it with Cog, because i can't.
And NB is not for translating bytecodes into native code,
it is for authoring a primitives using native code.
So, my comparison is how faster it could be , if implemented primitively.

I can only imagine, how faster the whole thing would be if we
cross-hatch NB and Cog,
where Cog will serve as a smalltalk optimizer , and NB will serve for
manual optimizations
for heavy numerical crunching :)

> best
> Eliot
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Levente Uzonyi-2
In reply to this post by Igor Stasenko
Hi again,

On Sat, 15 May 2010, Igor Stasenko wrote:

> added implementation into examples package:
> http://www.squeaksource.com/NativeBoost/NativeBoost-Examples-Igor.Stasenko.1.mcz

just tried to run the following code:

'foo' asWideString nbHash

but I get an assertion failure at this line:
imul: ESI with: 16r260D;  " 16r260D * low "
The code generator is unhappy about ESI. In
AJInstructionDescription >> #emitimul:operand1:operand2:operand3:
There's an assertion:
self assert: op1 isRegTypeGPW.
If I just press proceed, it will be unhappy with the other two
registers passed to #imul:with:, but the code compiles and works, so
probably the assertion is wrong.


Levente

>
> On 15 May 2010 01:14, Igor Stasenko <[hidden email]> wrote:
>> I implemented WideString hash in NB.
>>
>> |s|
>> s := WideString with: (Character value: 16r55E4).
>> [100000000 timesRepeat: [s hash]] timeToRun. 155718
>>
>>
>> |s|
>> s := WideString with: (Character value: 16r55E4).
>> [100000000 timesRepeat: [s nbHash]] timeToRun.  81231
>>
>> Which makes me think, that we're benching the outer loop, rather then
>> hash function itself :)
>>
>> So, here is more appropriate , i think:
>>
>> |s t1 t2 |
>> s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
>> 10 timesRepeat: [ s := s , s ].
>> self assert: (s hash = s nbHash).
>> t1 := [1000 timesRepeat: [s hash]] timeToRun.
>> t2 := [1000 timesRepeat: [s nbHash]] timeToRun.
>>
>> { t1. t2 }
>>  #(11479 134)
>>
>> ~ 85x faster :)
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
>

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Igor Stasenko
2010/5/15 Levente Uzonyi <[hidden email]>:

> Hi again,
>
> On Sat, 15 May 2010, Igor Stasenko wrote:
>
>> added implementation into examples package:
>>
>> http://www.squeaksource.com/NativeBoost/NativeBoost-Examples-Igor.Stasenko.1.mcz
>
> just tried to run the following code:
>
> 'foo' asWideString nbHash
>
> but I get an assertion failure at this line:
> imul: ESI with: 16r260D;  " 16r260D * low "
> The code generator is unhappy about ESI. In
> AJInstructionDescription >> #emitimul:operand1:operand2:operand3:
> There's an assertion:
> self assert: op1 isRegTypeGPW.
> If I just press proceed, it will be unhappy with the other two registers
> passed to #imul:with:, but the code compiles and works, so probably the
> assertion is wrong.
>
ah yes, i just commented this assert out.
I don't sure, but it seems either placed in a wrong place or wrong.

>
> Levente
>
>>
>> On 15 May 2010 01:14, Igor Stasenko <[hidden email]> wrote:
>>>
>>> I implemented WideString hash in NB.
>>>
>>> |s|
>>> s := WideString with: (Character value: 16r55E4).
>>> [100000000 timesRepeat: [s hash]] timeToRun. 155718
>>>
>>>
>>> |s|
>>> s := WideString with: (Character value: 16r55E4).
>>> [100000000 timesRepeat: [s nbHash]] timeToRun.  81231
>>>
>>> Which makes me think, that we're benching the outer loop, rather then
>>> hash function itself :)
>>>
>>> So, here is more appropriate , i think:
>>>
>>> |s t1 t2 |
>>> s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
>>> 10 timesRepeat: [ s := s , s ].
>>> self assert: (s hash = s nbHash).
>>> t1 := [1000 timesRepeat: [s hash]] timeToRun.
>>> t2 := [1000 timesRepeat: [s nbHash]] timeToRun.
>>>
>>> { t1. t2 }
>>>  #(11479 134)
>>>
>>> ~ 85x faster :)
>>>
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko AKA sig.
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: WideString hash is way slower than ByteString hash.

Eliot Miranda-2
In reply to this post by Igor Stasenko


On Fri, May 14, 2010 at 4:43 PM, Igor Stasenko <[hidden email]> wrote:
On 15 May 2010 02:35, Eliot Miranda <[hidden email]> wrote:
> The cardinal rule of running benchmarks is to compare apples to apples.
>  You've compared apples to oranges, i.e. an optimized reimplementation of
> WideString>>hash that eliminates the mapping of codes to characters, against
> the vanilla Squeak implementation.  You need to at least compare the NB
> implementation against
> WideString methods for comparison
> fastHash
> | stringSize hash low |
> stringSize := self size.
> hash := ByteString identityHash bitAnd: 16rFFFFFFF.
> 1 to: stringSize do: [:pos |
> hash := hash + (self wordAt: pos).
> "Begin hashMultiply"
> low := hash bitAnd: 16383.
> hash := (16r260D * low + ((16r260D * (hash bitShift: -14) + (16r0065 * low)
> bitAnd: 16383) * 16384)) bitAnd: 16r0FFFFFFF.
> ].
> ^ hash
> | s n |
> s := (WideString with: (Character value: 16r55E4)) , 'abcdefghijklmno'.
> n := 100000.
> { [1 to: n do: [:i| s fastHash. s fastHash. s fastHash. s fastHash. s
> fastHash. s fastHash. s fastHash. s fastHash. s fastHash. s fastHash]]
> timeToRun.
>  [1 to: n do: [:i| s hash. s hash. s hash. s hash. s hash. s hash. s hash. s
> hash. s hash. s hash]] timeToRun. }
>      #(829 1254)
> ASo your measurements tell us nothing about a general comparison of NB
> against the Squeak VM or Cog.  They only demonstrate (unsurprisingly) that a
> loop summing integers in an array goes PDQ.  On the other hand my numbers
> showed Cog 10x faster than the Squeak interpreter when executing exactly the
> same bytecode.

Yes, of course you're right.
But i didn't compared it with Cog, because i can't.
And NB is not for translating bytecodes into native code,
it is for authoring a primitives using native code.
So, my comparison is how faster it could be , if implemented primitively.

I can only imagine, how faster the whole thing would be if we
cross-hatch NB and Cog,
where Cog will serve as a smalltalk optimizer , and NB will serve for
manual optimizations
for heavy numerical crunching :)

Yes, this is a very cool direction.   One effort should be AOStA/SIStA with Marcus, which will do adaptive optimization/speculative inlining a la Self & Hotspot.  Being able to directly generate machine code with NB and not have to rely on the VM's naive code generator would allow machine-specific optimization ad excellent register usage.  This could beat C.  The difficulty here is in portability.  Another more researchy direction would be a Klein approach where the Cog code generator is eliminated and replaced by NB, perfectly possible since Cog retains the interpreter which can be fallen back upon at any time.  Again portability is an issue.

best,
Eliot


> best
> Eliot
>



--
Best regards,
Igor Stasenko AKA sig.




12