ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Clinton Begin <clinton.be...@gmail.com>
Subject Re: ibatis 3 memory leak
Date Mon, 18 Jan 2010 16:10:45 GMT
Hmm... it looks to me like your situation is a perfect storm.

 * You're loading lots of objects.
 * You're loading big objects.
 * You are guaranteeing an N+1 selects problem with that for loop.

No one of these situations should create a major problem, but all three
together are a guaranteed disappointment.

That said, I'm surprised that 2000 rows would be that much of a problem...
how big are these objects really?

Also, memory wise, there should be almost no difference between using one
session or multiple.  And no, I would not open multiple as in your second
example.

As for the serialization error, that might be a bug if LoadPair wasn't
serializable.

Clinton

On Mon, Jan 18, 2010 at 8:24 AM, Dave Rafkind <dave.rafkind@gmail.com>wrote:

> Ok, that's some good information, I understand that you should marshall
> your objects with care. Unfortunately for me at some point I will have to
> marshall every single one of my database rows into an object graph. However
> what I took from your advice was not to be so stingy in re-using the session
> objects. So if I do something like this:
>
> for (id : ids) {
>   SqlSession session2 = sessionMapper.openSession();
>   MyObject o = session2.select("getOne", id.getActualId());
>   session2.close();
> }
>
> Now memory usage is pretty good! However now performance is terrible. In
> attempting to rectify this I tried to put in a custom cache implementation,
> logging cache access to see how it was performing. I noticed it was never
> actually using the cache (never doing cache.putObject).
> I noticed that according to this discussion:
>
>
> http://markmail.org/search/?q=select+commit+cache+list%3Aorg.apache.ibatis.user-java#query:select%20commit%20cache%20list%3Aorg.apache.ibatis.user-java+page:1+mid:4mmwki3dnp57gweu+state:results
>
> ...commits don't occur (and thus cache fill doesn't occur) unless a
> transaction is committed. So for a pure read-only use case of the db the
> cache won't be very useful, right?
>
> Additionally, putting in a "session2.commit()" before the call to close()
> causes the following error (which I assume, but don't know is caused by
> committing when nothing actually needs to be comitted:)
>
> ### Error committing transaction.  Cause:
> org.apache.ibatis.cache.CacheException: Error serializing object.  Cause:
> java.io.NotSerializableException:
> org.apache.ibatis.executor.loader.ResultLoaderRegistry$LoadPair
>
>
>
> On Thu, Jan 14, 2010 at 2:44 PM, Clinton Begin <clinton.begin@gmail.com>wrote:
>
>> By nested results, yes, I mean collections and associations.  And by
>> "flattening" I mean avoiding the use of those.
>>
>> iBATIS exhibits this behavior, the same way any ORM would, because the
>> object instances need to be cached to preserve object identity.  So as
>> you're result set is being read through, each unique object is stored.
>> iBATIS isn't quite as effcient as something like Hibernate can be with
>> circular references though, in that depending on how you map it out, you may
>> end up with multiple instances of the same data (parent/child relationships
>> mapped with resultMap).
>>
>> So with iBATIS, the most memory efficient approach is to use nested select
>> associations/collections.  But for query performance, nested resultMaps are
>> ideal.  I often find I need to use a combination of both to get the best
>> optimization.  But if I often don't load lists of complete objects either.
>> If I'm loading a large list, I'll use a lighter weight representation, and
>> then only load the complete object graph for individual instances.  I've
>> never found a case where this wasn't a good idea anyway.  Even when working
>> with something like Rails, a rich domain ORM, I would often write optimized
>> lightweight queries for large lists of flatter objects.
>>
>> The memory should not be significantly more than will ultimately be
>> required to store your final result set.   And any additional memory used
>> should be released upon the closing of the SqlSession.
>>
>> If the memory isn't being released at the end of the session, that's a
>> different story... but otherwise, this is normal behavior.
>>
>> Clinton
>>
>>
>> On Thu, Jan 14, 2010 at 11:20 AM, Dave Rafkind <dave.rafkind@gmail.com>wrote:
>>
>>> Thanks for the reply. What do you mean by nested result maps or selects?
>>> Do you mean collections or associations with their own selects and result
>>> maps? Why would ibatis exhibit this behavior in that case?
>>>
>>>  And by flattening, you mean the same kind of stuff used to avoid the n+1
>>> select problem?
>>>
>>> On Thu, Jan 14, 2010 at 1:02 PM, Clinton Begin <clinton.begin@gmail.com>wrote:
>>>
>>>> If it uses nested result maps or nested selects, I'm afraid you're out
>>>> of luck.   You'll need to reduce the query results, or flatten out the
>>>> results.
>>>>
>>>> Clinton
>>>>
>>>> On 2010-01-14, Dave Rafkind <dave.rafkind@gmail.com> wrote:
>>>> > Hi ibatis list, I'm new to ibatis so perhaps this is a noob question.
>>>> I'm
>>>> > using Ibatis 3 (ibatis-3-core-3.0.0.216.jar) with a somewhat
>>>> complicated
>>>> > schema (plenty of circular links etc).
>>>> >
>>>> > I'm doing something like this:
>>>> >
>>>> > List<MyIdObject> ids = session.selectList("getAll");
>>>> >
>>>> > for (id : ids) {
>>>> >   MyObject o = session.select("getOne", id.getActualId());
>>>> > }
>>>> >
>>>> > The first query returns a list about 2k big, and the second query in
>>>> the for
>>>> > loop returns objects that are somewhat large (have several collections
>>>> in
>>>> > them, a discriminator, etc).
>>>> >
>>>> > The problem I have is that as the for loop marches on it uses an
>>>> > ever-increasing amount of memory. I would assuming that when the
>>>> objects in
>>>> > the body of the for loop go out of scope they can get garbage
>>>> collected, but
>>>> > apparently that never happens; is there some weird interaction with
>>>> the
>>>> > "first-level cache"? Should I be going about this a different way?
>>>> >
>>>> > Thanks!
>>>> > Dave
>>>> >
>>>>
>>>> --
>>>> Sent from my mobile device
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-java-unsubscribe@ibatis.apache.org
>>>> For additional commands, e-mail: user-java-help@ibatis.apache.org
>>>>
>>>>
>>>
>>
>

Mime
View raw message