Skip to main content

[JSR-354] Re: Number representation on MonetaryAmount

  • From: Anatole Tresch <atsticks@...>
  • To: Jsr 354 JavaMoney Public Mailinglist <jcurrency_mail@...>
  • Subject: [JSR-354] Re: Number representation on MonetaryAmount
  • Date: Mon, 30 Sep 2013 08:53:23 +0200

Hi Stephen

OK, seems reasonable, so I will include your conversion proposal within
next days and see, how much faster we get.
Thanks for that input and enjoy your day!

Anatole


2013/9/30 Stephen Colebourne <scolebourne@...>

> These results are probably about what I'd expect except that the basic
> Money case using BD is faster than expected at 20 times slower.
>
> It is a natural expectation that mixing types will result in a slower
> answer, because the from() method has a greater conversion to do. Most
> users of the API will be using a single money implementation - it will
> be rare for them to be using more than one implementation. If they do
> use more than one implementation, it is likely that the second one
> will be the JDK9 implementation which a 3rd party library would be
> able to refer to and optimise for.
>
> asNumber() has never been an acceptable thing to use because the
> Number interface is useless. Given a Number, there is no way to
> accurately extract the numerical value. The best that can be done (and
> what I assume you did) was to check instanceof BD and cast. Simply
> calling doubleValue() or longValue() will never be sufficient,
> especially for a money API.
>
> In JDK9 there will be the possibility to add a factory to BD that can
> create from the three arguments. Alternately, a Rational class could
> be developed and proposed to the JDK separate to this JSR.
>
> The fastest BD constructor is the (long,int) one - (unscaled, scale).
>
> Thus the fastest BD conversion is likely to involve special casing.
> Something like (but handling negatives):
> if (denom == 100 && whole < Long.MAX_VALUE / 1000) {
>  return BD.valueOf(whole * 100 + numerator, 2);
> } else if (denom == 1) {
>  return BD.valueOf(whole, 0);
> } else if (denom == 1000 && whole < Long.MAX_VALUE / 10000) {
>  return BD.valueOf(whole * 1000 + numerator, 3);
> } else {
>  ... create slow
> }
>
> or something like this
> array = {1, 10, 100, 1000, ...}
> for (int i = 0; i < array.length; i++) {
>   if (denom == array[i]) {
>     try {
>       long total = Math.multiplyExact(whole, denom)
>       total = Math.addExact(total, numerator);
>       return BD.valueOf(total, i);
>     } catch (ArithmeticException ex) {
>       ... create slow
>     }
>   }
> }
>  ... create slow
>
> Stephen
>
>
> On 29 September 2013 16:58, Anatole Tresch <atsticks@...> wrote:
> > Hi all/Stephen/Werner
> >
> > I was playing aroung with different variants of money implementations,
> one
> > using BD, one using a single long hereby using s scale of 5 digits for
> > representation of the minor units.
> >
> > I then measured performance for 1.000.000 executions of some arithmetic
> > functions as follows:
> >
> > Money money1 = Money.of(EURO, BigDecimal.ONE);
> > for (int i = 0; i < NUM; i++) {
> > money1 = money1.add(Money.of(EURO, 1234567.3444));
> > money1 = money1.subtract(Money.of(EURO, 232323));
> > money1 = money1.multiply(3.4);
> > money1 = money1.divide(5.456);
> > }
> >
> > FastMoney money1 = FastMoney.of(EURO, BigDecimal.ONE);
> > for (int i = 0; i < NUM; i++) {
> > money1 = money1.add(FastMoney.of(EURO, 1234567.3444));
> > money1 = money1.subtract(FastMoney.of(EURO, 232323));
> > money1 = money1.multiply(3.4);
> > money1 = money1.divide(5.456);
> > }
> >
> > This gaves me different execution times (and results):
> >
> > Duration for 1000000 operations (Money/BD): 3557 ms (3 ns per loop) ->
> EUR
> > 1657407.962529182
> > Duration for 1000000 operations (FastMoney/long): 178 ms (0 ns per loop)
> ->
> > EUR 1657407.96251
> >
> > When only slightly adapting the code above to:
> >
> > FastMoney money1 = FastMoney.of(EURO, BigDecimal.ONE);
> > for (int i = 0; i < NUM; i++) {
> > money1 = money1.add(Money.of(EURO, 1234567.3444));
> > money1 = money1.subtract(FastMoney.of(EURO, 232323));
> > money1 = money1.multiply(3.4);
> > money1 = money1.divide(5.456);
> > }
> >
> > we have quite an unexpected impact (we are ten times slower!):
> >
> > Duration for 1000000 operations (FastMoney/Money mixed): 1524 ms (1 ns
> per
> > loop) -> EUR 1657407.96251
> >
> > The issue is, that FastMoney must convert from Money in the
> > FastMoney.from(MoneytaryAmount)  using the numeric representation as
> > whole,nominator/denominator . The acceptable result shown above, was
> > possible, beacuse I added temporarely the method
> >
> > Number asNumber()
> >
> > to the interface and used this one, instead of creating a new Number
> > instance myself. When using BigDecimal within from you are significantly
> > slower (about 12 ns/loop).
> >
> > So question: WDYT on using asNumber() instead of the methods returning
> longs
> > for whole, fraction nominator, fraction denominator? This would allow us
> to
> > support a real high speed money implementation (compared to only fast
> one).
> >
> > Or can somebody provide me with code that is capable of creating a Number
> > real fast from the current interface...?
> >
> > Or other ideas, hints?
> >
> > Cheers,
> > Anatole
> >
> > PS.: Hope all is clear, its late now, and I have to end my night's
> hacking
> > tour......
> >
> >
> > --
> > Anatole Tresch
> > Java Lead Engineer, JSR Spec Lead
> > Glärnischweg 10
> > CH - 8620 Wetzikon
> >
> > Switzerland, Europe Zurich, GMT+1
> > Twitter:  @atsticks
> > Blogs: http://javaremarkables.blogspot.ch/
> > Google: atsticks
> > Mobile  +41-76 344 62 79
>



-- 
*Anatole Tresch*
Java Lead Engineer, JSR Spec Lead
Glärnischweg 10
CH - 8620 Wetzikon

*Switzerland, Europe Zurich, GMT+1*
*Twitter:  @atsticks*
*Blogs: **http://javaremarkables.blogspot.ch/*
*Google: atsticks
Mobile  +41-76 344 62 79*


[JSR-354] Number representation on MonetaryAmount

Anatole Tresch 09/29/2013

[JSR-354] Re: Number representation on MonetaryAmount

Stephen Colebourne 09/30/2013

[JSR-354] Re: Number representation on MonetaryAmount

Anatole Tresch 09/30/2013
 
 
Close
loading
Please Confirm
Close