You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@thrift.apache.org by Marty Weiner <ma...@pinterest.com> on 2011/09/17 09:02:45 UTC

Java Thrift is allocation heavy

I'm trying to understand (what I think is) a bug in the generated java
code.  My thrift schema generates this method:
public List<Long> listGet(String key) throws org.apache.thrift.TException {
... }

To avoid an allocation on every listGet request, I'd like to keep a
pre-allocated List<Long> buffer per thread, fill that, and return it.  When
I do this, it doesn't take much for me to get a ConcurrentModificationError,
possibly because the wrappers around my listGet method are holding onto it?
What's the recommended way to avoid the extra allocations?

Re: Java Thrift is allocation heavy

Posted by Marty Weiner <ma...@pinterest.com>.
Ah excellent.  So for avoiding allocation on a get request, you're suggesting I make a threadlocal buffer?  Or should it be a pool that reclaims objects instead of garbage collect them (not sure if that is possible).

On Sep 20, 2011, at 5:08 PM, Bryan Duxbury <br...@rapleaf.com> wrote:

> No, Thrift does not supply any threadsafe area. You have to use an object
> pool or ThreadLocal variable, etc.
> 
> On Tue, Sep 20, 2011 at 4:27 PM, Marty Weiner <ma...@pinterest.com> wrote:
> 
>> Ah ok.  It is multithreaded and concurrent requests are allowed.  Is there
>> a threadsafe area to allocate from?  I assumed each handler object was its
>> own thread.
>> 
>> On Sep 20, 2011, at 11:38 AM, Bryan Duxbury <br...@rapleaf.com> wrote:
>> 
>>> Are you using a multithreaded TServer with concurrent client requests? If
>>> so, then you can't declare just a single list in your handler. Handler
>>> access is not threadsafe.
>>> 
>>> On Tue, Sep 20, 2011 at 11:01 AM, Marty Weiner <ma...@pinterest.com>
>> wrote:
>>> 
>>>> Ah, sorry, I should have been clearer.  This is from the server end.
>>>> 
>>>> Some other thread can easily serialize my data?  So then that means that
>> I
>>>> must always
>>>> allocate a new List<Long> and return it?  Is there a way to avoid the
>>>> allocation overhead?  I'd
>>>> prefer to have my GC activity not scale with frequency of read requests,
>> if
>>>> possible.
>>>> 
>>>> By "thread local", I was referring to lists I allocated in my
>> handler.java
>>>> file (the derivation
>>>> of the interfaces made by the thrift generator).
>>>> 
>>>> Thanks for the help!
>>>> 
>>>> On Tue, Sep 20, 2011 at 9:21 AM, Bryan Duxbury <br...@rapleaf.com>
>> wrote:
>>>> 
>>>>> I presume that you're talking about this method from the server side of
>>>>> things. The problem is that, depending on the TServer you're using,
>> when
>>>>> you
>>>>> return the List<Long>, it might not necessarily be getting serialized
>> in
>>>>> the
>>>>> same thread.
>>>>> 
>>>>> Also, what is your "per thread" reservation mechanism? ThreadLocals?
>>>>> 
>>>>> On Sat, Sep 17, 2011 at 12:02 AM, Marty Weiner <ma...@pinterest.com>
>>>>> wrote:
>>>>> 
>>>>>> I'm trying to understand (what I think is) a bug in the generated java
>>>>>> code.  My thrift schema generates this method:
>>>>>> public List<Long> listGet(String key) throws
>>>> org.apache.thrift.TException
>>>>> {
>>>>>> ... }
>>>>>> 
>>>>>> To avoid an allocation on every listGet request, I'd like to keep a
>>>>>> pre-allocated List<Long> buffer per thread, fill that, and return it.
>>>>> When
>>>>>> I do this, it doesn't take much for me to get a
>>>>>> ConcurrentModificationError,
>>>>>> possibly because the wrappers around my listGet method are holding
>> onto
>>>>> it?
>>>>>> What's the recommended way to avoid the extra allocations?
>>>>>> 
>>>>> 
>>>> 
>> 

Re: Java Thrift is allocation heavy

Posted by Bryan Duxbury <br...@rapleaf.com>.
No, Thrift does not supply any threadsafe area. You have to use an object
pool or ThreadLocal variable, etc.

On Tue, Sep 20, 2011 at 4:27 PM, Marty Weiner <ma...@pinterest.com> wrote:

> Ah ok.  It is multithreaded and concurrent requests are allowed.  Is there
> a threadsafe area to allocate from?  I assumed each handler object was its
> own thread.
>
> On Sep 20, 2011, at 11:38 AM, Bryan Duxbury <br...@rapleaf.com> wrote:
>
> > Are you using a multithreaded TServer with concurrent client requests? If
> > so, then you can't declare just a single list in your handler. Handler
> > access is not threadsafe.
> >
> > On Tue, Sep 20, 2011 at 11:01 AM, Marty Weiner <ma...@pinterest.com>
> wrote:
> >
> >> Ah, sorry, I should have been clearer.  This is from the server end.
> >>
> >> Some other thread can easily serialize my data?  So then that means that
> I
> >> must always
> >> allocate a new List<Long> and return it?  Is there a way to avoid the
> >> allocation overhead?  I'd
> >> prefer to have my GC activity not scale with frequency of read requests,
> if
> >> possible.
> >>
> >> By "thread local", I was referring to lists I allocated in my
> handler.java
> >> file (the derivation
> >> of the interfaces made by the thrift generator).
> >>
> >> Thanks for the help!
> >>
> >> On Tue, Sep 20, 2011 at 9:21 AM, Bryan Duxbury <br...@rapleaf.com>
> wrote:
> >>
> >>> I presume that you're talking about this method from the server side of
> >>> things. The problem is that, depending on the TServer you're using,
> when
> >>> you
> >>> return the List<Long>, it might not necessarily be getting serialized
> in
> >>> the
> >>> same thread.
> >>>
> >>> Also, what is your "per thread" reservation mechanism? ThreadLocals?
> >>>
> >>> On Sat, Sep 17, 2011 at 12:02 AM, Marty Weiner <ma...@pinterest.com>
> >>> wrote:
> >>>
> >>>> I'm trying to understand (what I think is) a bug in the generated java
> >>>> code.  My thrift schema generates this method:
> >>>> public List<Long> listGet(String key) throws
> >> org.apache.thrift.TException
> >>> {
> >>>> ... }
> >>>>
> >>>> To avoid an allocation on every listGet request, I'd like to keep a
> >>>> pre-allocated List<Long> buffer per thread, fill that, and return it.
> >>> When
> >>>> I do this, it doesn't take much for me to get a
> >>>> ConcurrentModificationError,
> >>>> possibly because the wrappers around my listGet method are holding
> onto
> >>> it?
> >>>> What's the recommended way to avoid the extra allocations?
> >>>>
> >>>
> >>
>

Re: Java Thrift is allocation heavy

Posted by Marty Weiner <ma...@pinterest.com>.
Ah ok.  It is multithreaded and concurrent requests are allowed.  Is there a threadsafe area to allocate from?  I assumed each handler object was its own thread.

On Sep 20, 2011, at 11:38 AM, Bryan Duxbury <br...@rapleaf.com> wrote:

> Are you using a multithreaded TServer with concurrent client requests? If
> so, then you can't declare just a single list in your handler. Handler
> access is not threadsafe.
> 
> On Tue, Sep 20, 2011 at 11:01 AM, Marty Weiner <ma...@pinterest.com> wrote:
> 
>> Ah, sorry, I should have been clearer.  This is from the server end.
>> 
>> Some other thread can easily serialize my data?  So then that means that I
>> must always
>> allocate a new List<Long> and return it?  Is there a way to avoid the
>> allocation overhead?  I'd
>> prefer to have my GC activity not scale with frequency of read requests, if
>> possible.
>> 
>> By "thread local", I was referring to lists I allocated in my handler.java
>> file (the derivation
>> of the interfaces made by the thrift generator).
>> 
>> Thanks for the help!
>> 
>> On Tue, Sep 20, 2011 at 9:21 AM, Bryan Duxbury <br...@rapleaf.com> wrote:
>> 
>>> I presume that you're talking about this method from the server side of
>>> things. The problem is that, depending on the TServer you're using, when
>>> you
>>> return the List<Long>, it might not necessarily be getting serialized in
>>> the
>>> same thread.
>>> 
>>> Also, what is your "per thread" reservation mechanism? ThreadLocals?
>>> 
>>> On Sat, Sep 17, 2011 at 12:02 AM, Marty Weiner <ma...@pinterest.com>
>>> wrote:
>>> 
>>>> I'm trying to understand (what I think is) a bug in the generated java
>>>> code.  My thrift schema generates this method:
>>>> public List<Long> listGet(String key) throws
>> org.apache.thrift.TException
>>> {
>>>> ... }
>>>> 
>>>> To avoid an allocation on every listGet request, I'd like to keep a
>>>> pre-allocated List<Long> buffer per thread, fill that, and return it.
>>> When
>>>> I do this, it doesn't take much for me to get a
>>>> ConcurrentModificationError,
>>>> possibly because the wrappers around my listGet method are holding onto
>>> it?
>>>> What's the recommended way to avoid the extra allocations?
>>>> 
>>> 
>> 

Re: Java Thrift is allocation heavy

Posted by Bryan Duxbury <br...@rapleaf.com>.
Are you using a multithreaded TServer with concurrent client requests? If
so, then you can't declare just a single list in your handler. Handler
access is not threadsafe.

On Tue, Sep 20, 2011 at 11:01 AM, Marty Weiner <ma...@pinterest.com> wrote:

> Ah, sorry, I should have been clearer.  This is from the server end.
>
> Some other thread can easily serialize my data?  So then that means that I
> must always
> allocate a new List<Long> and return it?  Is there a way to avoid the
> allocation overhead?  I'd
> prefer to have my GC activity not scale with frequency of read requests, if
> possible.
>
> By "thread local", I was referring to lists I allocated in my handler.java
> file (the derivation
> of the interfaces made by the thrift generator).
>
> Thanks for the help!
>
> On Tue, Sep 20, 2011 at 9:21 AM, Bryan Duxbury <br...@rapleaf.com> wrote:
>
> > I presume that you're talking about this method from the server side of
> > things. The problem is that, depending on the TServer you're using, when
> > you
> > return the List<Long>, it might not necessarily be getting serialized in
> > the
> > same thread.
> >
> > Also, what is your "per thread" reservation mechanism? ThreadLocals?
> >
> > On Sat, Sep 17, 2011 at 12:02 AM, Marty Weiner <ma...@pinterest.com>
> > wrote:
> >
> > > I'm trying to understand (what I think is) a bug in the generated java
> > > code.  My thrift schema generates this method:
> > > public List<Long> listGet(String key) throws
> org.apache.thrift.TException
> > {
> > > ... }
> > >
> > > To avoid an allocation on every listGet request, I'd like to keep a
> > > pre-allocated List<Long> buffer per thread, fill that, and return it.
> >  When
> > > I do this, it doesn't take much for me to get a
> > > ConcurrentModificationError,
> > > possibly because the wrappers around my listGet method are holding onto
> > it?
> > > What's the recommended way to avoid the extra allocations?
> > >
> >
>

Re: Java Thrift is allocation heavy

Posted by Marty Weiner <ma...@pinterest.com>.
Ah, sorry, I should have been clearer.  This is from the server end.

Some other thread can easily serialize my data?  So then that means that I
must always
allocate a new List<Long> and return it?  Is there a way to avoid the
allocation overhead?  I'd
prefer to have my GC activity not scale with frequency of read requests, if
possible.

By "thread local", I was referring to lists I allocated in my handler.java
file (the derivation
of the interfaces made by the thrift generator).

Thanks for the help!

On Tue, Sep 20, 2011 at 9:21 AM, Bryan Duxbury <br...@rapleaf.com> wrote:

> I presume that you're talking about this method from the server side of
> things. The problem is that, depending on the TServer you're using, when
> you
> return the List<Long>, it might not necessarily be getting serialized in
> the
> same thread.
>
> Also, what is your "per thread" reservation mechanism? ThreadLocals?
>
> On Sat, Sep 17, 2011 at 12:02 AM, Marty Weiner <ma...@pinterest.com>
> wrote:
>
> > I'm trying to understand (what I think is) a bug in the generated java
> > code.  My thrift schema generates this method:
> > public List<Long> listGet(String key) throws org.apache.thrift.TException
> {
> > ... }
> >
> > To avoid an allocation on every listGet request, I'd like to keep a
> > pre-allocated List<Long> buffer per thread, fill that, and return it.
>  When
> > I do this, it doesn't take much for me to get a
> > ConcurrentModificationError,
> > possibly because the wrappers around my listGet method are holding onto
> it?
> > What's the recommended way to avoid the extra allocations?
> >
>

Re: Java Thrift is allocation heavy

Posted by Bryan Duxbury <br...@rapleaf.com>.
I presume that you're talking about this method from the server side of
things. The problem is that, depending on the TServer you're using, when you
return the List<Long>, it might not necessarily be getting serialized in the
same thread.

Also, what is your "per thread" reservation mechanism? ThreadLocals?

On Sat, Sep 17, 2011 at 12:02 AM, Marty Weiner <ma...@pinterest.com> wrote:

> I'm trying to understand (what I think is) a bug in the generated java
> code.  My thrift schema generates this method:
> public List<Long> listGet(String key) throws org.apache.thrift.TException {
> ... }
>
> To avoid an allocation on every listGet request, I'd like to keep a
> pre-allocated List<Long> buffer per thread, fill that, and return it.  When
> I do this, it doesn't take much for me to get a
> ConcurrentModificationError,
> possibly because the wrappers around my listGet method are holding onto it?
> What's the recommended way to avoid the extra allocations?
>