You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@drill.apache.org by Jacques Nadeau <ja...@apache.org> on 2013/07/28 03:13:53 UTC
escape analysis, stack allocation and scalar replacement for
ValueHolders for non-primitive types
Hey Guys,
I've been working on the right ValueHolder interfaces to avoid object
allocation inside evaluation loops. It's easy when we're dealing with
primitives but becomes more sticky when we're dealing with complex
types like strings. There are two reasons I'm focused on this. The
first is stack allocation. The second is scalar replacement. Stack
allocation seems to work very well. However, scalar replacement seems
slightly less reliable. I basically modeled three things we'll be
doing:
- Simple method (with alloc and without -- the current runtime
evaluation already using this alloc approach)
- Set (one using multiple parameters, the other using a single object
that contained primitives)
- Get (one using multiple methods, one using a passed in object that
is then populated, the third creating an object inside the get method
and returning that object)
I had been hoping that the latest JRE was smart enough to do scalar
replacements across a single method boundary. It looks like it works
in most cases. Strangely, it doesn't seem to work correctly in the
set(Object) method. That said, it doesn't seem like that big of a
deal and just leads me to think that this should be done with multiple
parameters on the ValueVector.Accessor's.
Thoughts? I didn't spend a lot of time trying to make this a super
accurate benchmark so let me know if you think there are holes in my
benchmark?
Jacques
-----
gist: https://gist.github.com/jacques-n/6096934
====With Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
-XX:MaxDirectMemorySize=4G)
initial
noalloc alloc ret alloc
method 523 538
set 593 788
get 425 558 424
warmed up
noalloc alloc ret alloc
method 336 337
set 261 630
get 406 379 402
====No Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
-XX:MaxDirectMemorySize=4G -XX:-DoEscapeAnalysis)
initial
noalloc alloc ret alloc
method 532 3982
set 619 1850
get 429 1985 2096
warmed up
noalloc alloc ret alloc
method 337 3546
set 299 1817
get 414 2133 2038
Run leveraging Oracle JRE 7u25 on a 2.3ghz 2012 Macbook Pro.
Re: escape analysis, stack allocation and scalar replacement for
ValueHolders for non-primitive types
Posted by Lisen Mu <im...@gmail.com>.
As you said, as long as no impact on performance, it's ok. And It's great
to have easier way to write udf.
Thanks for the reply.
On Mon, Jul 29, 2013 at 12:39 AM, Jacques Nadeau <ja...@apache.org> wrote:
> Good catch. Updated data below with EH made a static class. Now JVM
> seems to be cleaning everything up nicely.
>
> Regarding your other question. Straight primitives would work when
> there are appropriate primitive types. However, there are many types
> that don't have primitives (such as varbinary). Additionally function
> implementation (and especially udf implementation) seems much easier
> with holder class. My thinking was that if the layer of abstraction
> is useful and doesn't impact performance (which appears true), why not
> make life easier for function writers.
>
> J
>
>
>
> ====With Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
> -XX:MaxDirectMemorySize=4G)
> initial
> noalloc alloc ret alloc
> method 523 538
> set 593 599
> get 425 558 424
>
> warmed up
> noalloc alloc ret alloc
> method 336 337
> set 261 265
> get 406 379 402
>
> ====No Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
> -XX:MaxDirectMemorySize=4G -XX:-DoEscapeAnalysis)
> initial
> noalloc alloc ret alloc
> method 532 3982
> set 619 1850
> get 429 1985 2096
>
> warmed up
> noalloc alloc ret alloc
> method 337 3546
> set 299 1817
> get 414 2133 2038
>
>
>
>
> On Sun, Jul 28, 2013 at 8:34 AM, Lisen Mu <im...@gmail.com> wrote:
> > Jacques,
> >
> > I've tested your gist, and it seems that making class EH static helps a
> lot.
> >
> >
> > P.S. is it possible to avoid using ValueHolder classes?
> >
> > like, for projection expression 'col_a + col_b', can we generate
> evaluator
> > classes simply as:
> >
> > int eval(int index) {
> > return v1.accessor().get(index) + v2.accessor().get(index);
> > }
> >
> >
> >
> >
> > On Sun, Jul 28, 2013 at 9:13 AM, Jacques Nadeau <ja...@apache.org>
> wrote:
> >
> >> Hey Guys,
> >>
> >> I've been working on the right ValueHolder interfaces to avoid object
> >> allocation inside evaluation loops. It's easy when we're dealing with
> >> primitives but becomes more sticky when we're dealing with complex
> >> types like strings. There are two reasons I'm focused on this. The
> >> first is stack allocation. The second is scalar replacement. Stack
> >> allocation seems to work very well. However, scalar replacement seems
> >> slightly less reliable. I basically modeled three things we'll be
> >> doing:
> >>
> >> - Simple method (with alloc and without -- the current runtime
> >> evaluation already using this alloc approach)
> >> - Set (one using multiple parameters, the other using a single object
> >> that contained primitives)
> >> - Get (one using multiple methods, one using a passed in object that
> >> is then populated, the third creating an object inside the get method
> >> and returning that object)
> >>
> >> I had been hoping that the latest JRE was smart enough to do scalar
> >> replacements across a single method boundary. It looks like it works
> >> in most cases. Strangely, it doesn't seem to work correctly in the
> >> set(Object) method. That said, it doesn't seem like that big of a
> >> deal and just leads me to think that this should be done with multiple
> >> parameters on the ValueVector.Accessor's.
> >>
> >> Thoughts? I didn't spend a lot of time trying to make this a super
> >> accurate benchmark so let me know if you think there are holes in my
> >> benchmark?
> >>
> >> Jacques
> >>
> >> -----
> >>
> >> gist: https://gist.github.com/jacques-n/6096934
> >>
> >> ====With Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
> >> -XX:MaxDirectMemorySize=4G)
> >> initial
> >> noalloc alloc ret alloc
> >> method 523 538
> >> set 593 788
> >> get 425 558 424
> >>
> >> warmed up
> >> noalloc alloc ret alloc
> >> method 336 337
> >> set 261 630
> >> get 406 379 402
> >>
> >> ====No Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
> >> -XX:MaxDirectMemorySize=4G -XX:-DoEscapeAnalysis)
> >> initial
> >> noalloc alloc ret alloc
> >> method 532 3982
> >> set 619 1850
> >> get 429 1985 2096
> >>
> >> warmed up
> >> noalloc alloc ret alloc
> >> method 337 3546
> >> set 299 1817
> >> get 414 2133 2038
> >>
> >> Run leveraging Oracle JRE 7u25 on a 2.3ghz 2012 Macbook Pro.
> >>
>
Re: escape analysis, stack allocation and scalar replacement for
ValueHolders for non-primitive types
Posted by Jacques Nadeau <ja...@apache.org>.
Good catch. Updated data below with EH made a static class. Now JVM
seems to be cleaning everything up nicely.
Regarding your other question. Straight primitives would work when
there are appropriate primitive types. However, there are many types
that don't have primitives (such as varbinary). Additionally function
implementation (and especially udf implementation) seems much easier
with holder class. My thinking was that if the layer of abstraction
is useful and doesn't impact performance (which appears true), why not
make life easier for function writers.
J
====With Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
-XX:MaxDirectMemorySize=4G)
initial
noalloc alloc ret alloc
method 523 538
set 593 599
get 425 558 424
warmed up
noalloc alloc ret alloc
method 336 337
set 261 265
get 406 379 402
====No Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
-XX:MaxDirectMemorySize=4G -XX:-DoEscapeAnalysis)
initial
noalloc alloc ret alloc
method 532 3982
set 619 1850
get 429 1985 2096
warmed up
noalloc alloc ret alloc
method 337 3546
set 299 1817
get 414 2133 2038
On Sun, Jul 28, 2013 at 8:34 AM, Lisen Mu <im...@gmail.com> wrote:
> Jacques,
>
> I've tested your gist, and it seems that making class EH static helps a lot.
>
>
> P.S. is it possible to avoid using ValueHolder classes?
>
> like, for projection expression 'col_a + col_b', can we generate evaluator
> classes simply as:
>
> int eval(int index) {
> return v1.accessor().get(index) + v2.accessor().get(index);
> }
>
>
>
>
> On Sun, Jul 28, 2013 at 9:13 AM, Jacques Nadeau <ja...@apache.org> wrote:
>
>> Hey Guys,
>>
>> I've been working on the right ValueHolder interfaces to avoid object
>> allocation inside evaluation loops. It's easy when we're dealing with
>> primitives but becomes more sticky when we're dealing with complex
>> types like strings. There are two reasons I'm focused on this. The
>> first is stack allocation. The second is scalar replacement. Stack
>> allocation seems to work very well. However, scalar replacement seems
>> slightly less reliable. I basically modeled three things we'll be
>> doing:
>>
>> - Simple method (with alloc and without -- the current runtime
>> evaluation already using this alloc approach)
>> - Set (one using multiple parameters, the other using a single object
>> that contained primitives)
>> - Get (one using multiple methods, one using a passed in object that
>> is then populated, the third creating an object inside the get method
>> and returning that object)
>>
>> I had been hoping that the latest JRE was smart enough to do scalar
>> replacements across a single method boundary. It looks like it works
>> in most cases. Strangely, it doesn't seem to work correctly in the
>> set(Object) method. That said, it doesn't seem like that big of a
>> deal and just leads me to think that this should be done with multiple
>> parameters on the ValueVector.Accessor's.
>>
>> Thoughts? I didn't spend a lot of time trying to make this a super
>> accurate benchmark so let me know if you think there are holes in my
>> benchmark?
>>
>> Jacques
>>
>> -----
>>
>> gist: https://gist.github.com/jacques-n/6096934
>>
>> ====With Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
>> -XX:MaxDirectMemorySize=4G)
>> initial
>> noalloc alloc ret alloc
>> method 523 538
>> set 593 788
>> get 425 558 424
>>
>> warmed up
>> noalloc alloc ret alloc
>> method 336 337
>> set 261 630
>> get 406 379 402
>>
>> ====No Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
>> -XX:MaxDirectMemorySize=4G -XX:-DoEscapeAnalysis)
>> initial
>> noalloc alloc ret alloc
>> method 532 3982
>> set 619 1850
>> get 429 1985 2096
>>
>> warmed up
>> noalloc alloc ret alloc
>> method 337 3546
>> set 299 1817
>> get 414 2133 2038
>>
>> Run leveraging Oracle JRE 7u25 on a 2.3ghz 2012 Macbook Pro.
>>
Re: escape analysis, stack allocation and scalar replacement for
ValueHolders for non-primitive types
Posted by Lisen Mu <im...@gmail.com>.
Jacques,
I've tested your gist, and it seems that making class EH static helps a lot.
P.S. is it possible to avoid using ValueHolder classes?
like, for projection expression 'col_a + col_b', can we generate evaluator
classes simply as:
int eval(int index) {
return v1.accessor().get(index) + v2.accessor().get(index);
}
On Sun, Jul 28, 2013 at 9:13 AM, Jacques Nadeau <ja...@apache.org> wrote:
> Hey Guys,
>
> I've been working on the right ValueHolder interfaces to avoid object
> allocation inside evaluation loops. It's easy when we're dealing with
> primitives but becomes more sticky when we're dealing with complex
> types like strings. There are two reasons I'm focused on this. The
> first is stack allocation. The second is scalar replacement. Stack
> allocation seems to work very well. However, scalar replacement seems
> slightly less reliable. I basically modeled three things we'll be
> doing:
>
> - Simple method (with alloc and without -- the current runtime
> evaluation already using this alloc approach)
> - Set (one using multiple parameters, the other using a single object
> that contained primitives)
> - Get (one using multiple methods, one using a passed in object that
> is then populated, the third creating an object inside the get method
> and returning that object)
>
> I had been hoping that the latest JRE was smart enough to do scalar
> replacements across a single method boundary. It looks like it works
> in most cases. Strangely, it doesn't seem to work correctly in the
> set(Object) method. That said, it doesn't seem like that big of a
> deal and just leads me to think that this should be done with multiple
> parameters on the ValueVector.Accessor's.
>
> Thoughts? I didn't spend a lot of time trying to make this a super
> accurate benchmark so let me know if you think there are holes in my
> benchmark?
>
> Jacques
>
> -----
>
> gist: https://gist.github.com/jacques-n/6096934
>
> ====With Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
> -XX:MaxDirectMemorySize=4G)
> initial
> noalloc alloc ret alloc
> method 523 538
> set 593 788
> get 425 558 424
>
> warmed up
> noalloc alloc ret alloc
> method 336 337
> set 261 630
> get 406 379 402
>
> ====No Escape Analysis enabled==== (-XX:+UnlockDiagnosticVMOptions
> -XX:MaxDirectMemorySize=4G -XX:-DoEscapeAnalysis)
> initial
> noalloc alloc ret alloc
> method 532 3982
> set 619 1850
> get 429 1985 2096
>
> warmed up
> noalloc alloc ret alloc
> method 337 3546
> set 299 1817
> get 414 2133 2038
>
> Run leveraging Oracle JRE 7u25 on a 2.3ghz 2012 Macbook Pro.
>