Faster Float printing possible?

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

Faster Float printing possible?

GLASS mailing list
Hi guys, 

The app I am developing is a financial one and in many case I must serialize via JSON some large series of prices or fundamental data. Many times these numbers are SmallFloat and the printing to JSON takes quite some time. See below:

34.1% (15) WAJsonCanvas         >> render:                                                                                           31.8% (14) SmallDouble          >> jsonOn:
|  31.8% (14) WAJsonCanvas         >> binaryFloat:
|     31.8% (14) BinaryFloat          >> printOn:base: [SmallDouble]
|        31.8% (14) BinaryFloat          >> absPrintOn:base: [SmallDouble]
|            9.1% (4) GRUtf8CodecStream    >> nextPut:|            |   4.5% (2) WriteStream          >> nextPut: [AnsiWriteStream]
|            4.5% (2) BinaryFloat          >> >= [SmallDouble]
|            4.5% (2) Integer              >> * [SmallInteger]
|            |   2.3% (1) Number               >> _retry:coercing: [SmallInteger]
|            |      2.3% (1) Float                >> _coerce: [SmallDouble]
|            4.5% (2) BinaryFloat          >> timesTwoPower: [SmallDouble]
|            2.3% (1) Float                >> raisedToInteger: [SmallDouble]
|            2.3% (1) Character class      >> digitValue:
                                                                                                              


Now..this ends up doing:

WAJsonCanvas  >> binaryFloat: aBinaryFloat
  aBinaryFloat printOn: self document stream base: 10

And the implementation of 

BinaryFloat >> printOn: aStream base: base
  "Handle sign, zero, and NaNs; all other values passed to absPrintOn:base:"

  self isNaN
    ifTrue: [ 
      aStream nextPutAll: 'NaN'.
      ^ self ]. "check for NaN before sign"
  self > 0.0
    ifTrue: [ self absPrintOn: aStream base: base ]
    ifFalse: [ 
      self sign = -1
        ifTrue: [ aStream nextPutAll: '-' ].
      self = 0.0
        ifTrue: [ 
          aStream nextPutAll: '0.0'.
          ^ self ]
        ifFalse: [ self negated absPrintOn: aStream base: base ] ]


Above implementation is in *squeak-printing. And I know that this package does not receive much attention and possible gets outdated frequently. I suspect GemStone may have (at this time?) a faster way to achieve the above. 

Is there something like that I can use with faster times?

Thanks in advance


--

_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass
Reply | Threaded
Open this post in threaded view
|

Re: Faster Float printing possible?

GLASS mailing list

Mariano,

Float>>asString is implemented as a primitive and you could probably use that call just about anywhere you want ... I am not a floating point guy, so I cannot comment on where you will see differences in the output strings (if any at all) and of course I don't know how important precision is when you are passing around json ...

Dale


On 02/08/2017 08:51 AM, Mariano Martinez Peck via Glass wrote:
Hi guys, 

The app I am developing is a financial one and in many case I must serialize via JSON some large series of prices or fundamental data. Many times these numbers are SmallFloat and the printing to JSON takes quite some time. See below:

34.1% (15) WAJsonCanvas         >> render:                                                                                           31.8% (14) SmallDouble          >> jsonOn:
|  31.8% (14) WAJsonCanvas         >> binaryFloat:
|     31.8% (14) BinaryFloat          >> printOn:base: [SmallDouble]
|        31.8% (14) BinaryFloat          >> absPrintOn:base: [SmallDouble]
|            9.1% (4) GRUtf8CodecStream    >> nextPut:|            |   4.5% (2) WriteStream          >> nextPut: [AnsiWriteStream]
|            4.5% (2) BinaryFloat          >> >= [SmallDouble]
|            4.5% (2) Integer              >> * [SmallInteger]
|            |   2.3% (1) Number               >> _retry:coercing: [SmallInteger]
|            |      2.3% (1) Float                >> _coerce: [SmallDouble]
|            4.5% (2) BinaryFloat          >> timesTwoPower: [SmallDouble]
|            2.3% (1) Float                >> raisedToInteger: [SmallDouble]
|            2.3% (1) Character class      >> digitValue:
                                                                                                              


Now..this ends up doing:

WAJsonCanvas  >> binaryFloat: aBinaryFloat
  aBinaryFloat printOn: self document stream base: 10

And the implementation of 

BinaryFloat >> printOn: aStream base: base
  "Handle sign, zero, and NaNs; all other values passed to absPrintOn:base:"

  self isNaN
    ifTrue: [ 
      aStream nextPutAll: 'NaN'.
      ^ self ]. "check for NaN before sign"
  self > 0.0
    ifTrue: [ self absPrintOn: aStream base: base ]
    ifFalse: [ 
      self sign = -1
        ifTrue: [ aStream nextPutAll: '-' ].
      self = 0.0
        ifTrue: [ 
          aStream nextPutAll: '0.0'.
          ^ self ]
        ifFalse: [ self negated absPrintOn: aStream base: base ] ]


Above implementation is in *squeak-printing. And I know that this package does not receive much attention and possible gets outdated frequently. I suspect GemStone may have (at this time?) a faster way to achieve the above. 

Is there something like that I can use with faster times?

Thanks in advance


--


_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass


_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass
Reply | Threaded
Open this post in threaded view
|

Re: Faster Float printing possible?

GLASS mailing list


On Wed, Feb 8, 2017 at 3:31 PM, Dale Henrichs via Glass <[hidden email]> wrote:

Mariano,

Float>>asString is implemented as a primitive and you could probably use that call just about anywhere you want ... I am not a floating point guy,


Where is Martin when we need him?? hahahahahhaa
 

so I cannot comment on where you will see differences in the output strings (if any at all) and of course I don't know how important precision is when you are passing around json ...


Thanks Dale. That indeed gives me like .. around 2x performance improvement. As for the results, for JSON it looks like correct. But I would love to hear if Martin has something else to comment on.

Cheers,
 

Dale


On 02/08/2017 08:51 AM, Mariano Martinez Peck via Glass wrote:
Hi guys, 

The app I am developing is a financial one and in many case I must serialize via JSON some large series of prices or fundamental data. Many times these numbers are SmallFloat and the printing to JSON takes quite some time. See below:

34.1% (15) WAJsonCanvas         >> render:                                                                                           31.8% (14) SmallDouble          >> jsonOn:
|  31.8% (14) WAJsonCanvas         >> binaryFloat:
|     31.8% (14) BinaryFloat          >> printOn:base: [SmallDouble]
|        31.8% (14) BinaryFloat          >> absPrintOn:base: [SmallDouble]
|            9.1% (4) GRUtf8CodecStream    >> nextPut:|            |   4.5% (2) WriteStream          >> nextPut: [AnsiWriteStream]
|            4.5% (2) BinaryFloat          >> >= [SmallDouble]
|            4.5% (2) Integer              >> * [SmallInteger]
|            |   2.3% (1) Number               >> _retry:coercing: [SmallInteger]
|            |      2.3% (1) Float                >> _coerce: [SmallDouble]
|            4.5% (2) BinaryFloat          >> timesTwoPower: [SmallDouble]
|            2.3% (1) Float                >> raisedToInteger: [SmallDouble]
|            2.3% (1) Character class      >> digitValue:
                                                                                                              


Now..this ends up doing:

WAJsonCanvas  >> binaryFloat: aBinaryFloat
  aBinaryFloat printOn: self document stream base: 10

And the implementation of 

BinaryFloat >> printOn: aStream base: base
  "Handle sign, zero, and NaNs; all other values passed to absPrintOn:base:"

  self isNaN
    ifTrue: [ 
      aStream nextPutAll: 'NaN'.
      ^ self ]. "check for NaN before sign"
  self > 0.0
    ifTrue: [ self absPrintOn: aStream base: base ]
    ifFalse: [ 
      self sign = -1
        ifTrue: [ aStream nextPutAll: '-' ].
      self = 0.0
        ifTrue: [ 
          aStream nextPutAll: '0.0'.
          ^ self ]
        ifFalse: [ self negated absPrintOn: aStream base: base ] ]


Above implementation is in *squeak-printing. And I know that this package does not receive much attention and possible gets outdated frequently. I suspect GemStone may have (at this time?) a faster way to achieve the above. 

Is there something like that I can use with faster times?

Thanks in advance


--


_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass


_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass




--

_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass
Reply | Threaded
Open this post in threaded view
|

Re: Faster Float printing possible?

GLASS mailing list
On 02/08/2017 11:59 AM, Mariano Martinez Peck via Glass wrote:
On Wed, Feb 8, 2017 at 3:31 PM, Dale Henrichs via Glass <[hidden email]> wrote:

Mariano,

Float>>asString is implemented as a primitive and you could probably use that call just about anywhere you want ... I am not a floating point guy,


Where is Martin when we need him?? hahahahahhaa
 

so I cannot comment on where you will see differences in the output strings (if any at all) and of course I don't know how important precision is when you are passing around json ...


Thanks Dale. That indeed gives me like .. around 2x performance improvement. As for the results, for JSON it looks like correct. But I would love to hear if Martin has something else to comment on.

Hi Mariano,

I guess I have something of a reputation. :-)

Printing binary floats in decimal is a surprisingly complex topic, with quite a few papers published on the topic.

I haven't looked at your case in detail (especially the JSON conversion) but IIRC the Float>>asString primitive uses a double printing routine in libc, which should be both fast and accurate. Though there *was* for several years a bug in glibc that made it print an insufficient number of digits for a small percentage of floats, so that when read back in the resulting float was one LSB off from the original float. That was fixed in glibc several years ago, so recent Linux distributions should do correct printing now.

Regards,

-Martin


_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass
Reply | Threaded
Open this post in threaded view
|

Re: Faster Float printing possible?

GLASS mailing list


On Wed, Feb 8, 2017 at 5:41 PM, Martin McClure <[hidden email]> wrote:
On 02/08/2017 11:59 AM, Mariano Martinez Peck via Glass wrote:
On Wed, Feb 8, 2017 at 3:31 PM, Dale Henrichs via Glass <[hidden email]> wrote:

Mariano,

Float>>asString is implemented as a primitive and you could probably use that call just about anywhere you want ... I am not a floating point guy,


Where is Martin when we need him?? hahahahahhaa
 

so I cannot comment on where you will see differences in the output strings (if any at all) and of course I don't know how important precision is when you are passing around json ...


Thanks Dale. That indeed gives me like .. around 2x performance improvement. As for the results, for JSON it looks like correct. But I would love to hear if Martin has something else to comment on.

Hi Mariano,


Here he is!
 

I guess I have something of a reputation. :-)


hahahaahha you bet. 
 

Printing binary floats in decimal is a surprisingly complex topic, with quite a few papers published on the topic.

I haven't looked at your case in detail (especially the JSON conversion) but IIRC the Float>>asString primitive uses a double printing routine in libc, which should be both fast and accurate. Though there *was* for several years a bug in glibc that made it print an insufficient number of digits for a small percentage of floats, so that when read back in the resulting float was one LSB off from the original float. That was fixed in glibc several years ago, so recent Linux distributions should do correct printing now.



OK great. So.... I guess the double printing feature is the one used by `printf` ? Because Float >> #asString comment say:

 The receiver is printed using the C printf format string '%.16g'  .


Else you  may be talking of another method?


Thanks! 

--

_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass
Reply | Threaded
Open this post in threaded view
|

Re: Faster Float printing possible?

GLASS mailing list
On 02/08/2017 12:50 PM, Mariano Martinez Peck wrote:
OK great. So.... I guess the double printing feature is the one used by `printf` ? Because Float >> #asString comment say:

 The receiver is printed using the C printf format string '%.16g'  .

Right. The primitive is basically a wrapper for printf(), except for INFs and NaNs, and the test for those is cheap.

Regards,

-Martin



_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass
Reply | Threaded
Open this post in threaded view
|

Re: Faster Float printing possible?

GLASS mailing list
In reply to this post by GLASS mailing list

Well, Float>>asString is one of these locale oriented methods ... JSON will not be happy, when your application would run in a different area ... asStringLocaleC is a better alternative ... these locale oriented methods are the pain ...


Marten

Mariano Martinez Peck via Glass <[hidden email]> hat am 8. Februar 2017 um 20:59 geschrieben:



On Wed, Feb 8, 2017 at 3:31 PM, Dale Henrichs via Glass <[hidden email]> wrote:

Mariano,

Float>>asString is implemented as a primitive and you could probably use that call just about anywhere you want ... I am not a floating point guy,




_______________________________________________
Glass mailing list
[hidden email]
http://lists.gemtalksystems.com/mailman/listinfo/glass