You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@jackrabbit.apache.org by Eric <th...@trivantisdev.com> on 2009/06/05 00:16:51 UTC
Performance Improvement Code Fix to AbstractRecord
We were having performance issues during the commit of a transaction
that contained a huge amount of node inserts. We found that a big chunk
of the commit time was spent in the method
org.apache.jackrabbit.core.journal.AbstractRecord.getOrCreateIndex().
In this class, the uuidIndex instance variable is an ArrayList and
uuidIndex.indexOf(nodeId) is called to search through this ArrayList to
see if a node is already in the list. ArrayList.indexOf() searches the
list from beginning to end calling NodeId.equals() until the entry is
located and then returns. This can be quite inefficient if the list
becomes large.
In our case, we had *42K* entries in this list with about *400K* calls
to getOrCreateIndex() resulting in over *9 billion* calls to
NodeId.equals(). By combining a HashMap with the ArrayList and checking
the HashMap instead of the ArrayList to see if the node is in the cache,
we traded the 400K calls to ArrayList.indexOf() (and the subsequent 9
billions calls to NodeId.equals()) for 400K calls HashMap.get() (and its
subsequent calls). Our commit time went from about 30 minutes to about
3 minutes.
There may be more elegant ways to fix this problem, but our changes to
AbstractRecord are listed below. Maybe some changes along these lines
could be incorporated into this class to improve performance. Thanks.
-------------------- old code --------------------
private int getOrCreateIndex(NodeId nodeId) {
int index = uuidIndex.indexOf(nodeId);
if (index == -1) {
uuidIndex.add(nodeId);
}
return index;
}
-------------------- new code --------------------
private final HashMap<String, Integer> uuidMap = new HashMap<String,
Integer>();
private int getOrCreateIndex(NodeId nodeId) {
Integer index = uuidMap.get(nodeId.toString());
if (index == null) {
uuidIndex.add(nodeId);
uuidMap.put(nodeId.toString(), uuidIndex.size() - 1);
index = -1;
}
return index;
}
Re: Performance Improvement Code Fix to AbstractRecord
Posted by Marcel Reutegger <ma...@gmx.net>.
Hi,
this has already been reported and fixed. See:
https://issues.apache.org/jira/browse/JCR-1988
regards
marcel
On Fri, Jun 5, 2009 at 00:16, Eric <th...@trivantisdev.com> wrote:
> We were having performance issues during the commit of a transaction that
> contained a huge amount of node inserts. We found that a big chunk of the
> commit time was spent in the method
> org.apache.jackrabbit.core.journal.AbstractRecord.getOrCreateIndex(). In
> this class, the uuidIndex instance variable is an ArrayList and
> uuidIndex.indexOf(nodeId) is called to search through this ArrayList to see
> if a node is already in the list. ArrayList.indexOf() searches the list
> from beginning to end calling NodeId.equals() until the entry is located and
> then returns. This can be quite inefficient if the list becomes large.
>
> In our case, we had *42K* entries in this list with about *400K* calls to
> getOrCreateIndex() resulting in over *9 billion* calls to NodeId.equals().
> By combining a HashMap with the ArrayList and checking the HashMap instead
> of the ArrayList to see if the node is in the cache, we traded the 400K
> calls to ArrayList.indexOf() (and the subsequent 9 billions calls to
> NodeId.equals()) for 400K calls HashMap.get() (and its subsequent calls).
> Our commit time went from about 30 minutes to about 3 minutes.
>
> There may be more elegant ways to fix this problem, but our changes to
> AbstractRecord are listed below. Maybe some changes along these lines could
> be incorporated into this class to improve performance. Thanks.
>
> -------------------- old code --------------------
>
> private int getOrCreateIndex(NodeId nodeId) {
> int index = uuidIndex.indexOf(nodeId);
>
> if (index == -1) {
> uuidIndex.add(nodeId);
> }
> return index;
> }
>
> -------------------- new code --------------------
>
> private final HashMap<String, Integer> uuidMap = new HashMap<String,
> Integer>();
>
> private int getOrCreateIndex(NodeId nodeId) {
> Integer index = uuidMap.get(nodeId.toString());
>
> if (index == null) {
> uuidIndex.add(nodeId);
> uuidMap.put(nodeId.toString(), uuidIndex.size() - 1);
> index = -1;
> }
> return index;
> }
>
>