简体   繁体   中英

Java performance gradually degrades

I have a Java class that does something like this:

public void slowsDownOverTime() {
    for (int i=0 ; i<nIter ; i++) {
        BigObject bigObject = new BigObject();
        // some code here that populates big object ...
        CustomSerializer.write(bigObject);
    }
}

What I observe is that as the code iterates, the time needed by the serializer to write gets longer and longer. When it starts, the serializer runs in milliseconds; after a few tens of thousands of iterations, it takes several seconds to run.

The disk to which the serializer writes is nowhere near full, and the Java heap space in use is nowhere near its maximum when this happens.

To the extent possible I've reduced the number and size of objects created and destroyed during this cycle. That basically exhausts my toolkit for addressing this sort of problem!

Any suggestions for how I understand and correct the gradual performance degradation would be greatly appreciated!

I think, this is caused by the code left out (some code here that populates big object ...). Try this:

public void slowsDownOverTime() {
    BigObject bigObject = new BigObject();
    // some code here that populates big object ...
    for (int i=0 ; i<nIter ; i++) {
        CustomSerializer.write(bigObject);
    }
}

This will always write the same object and I expect this not to degrade in performance.

I think the left out code builds a growing data structure that is being referenced by bigObject . Keep in mind that, when serializing, Java traverses all dependent objects down to depth and serializes also all dependent objects. So it will write more and more data with each iteration. This can be the cause for degarding performace and use of much disk space.

After much fruitless mucking about with jvisualvm's profiler, I resorted to adding a ton of logging. This gave me a clue that the problem was in a Hibernate operation that was performed to populate the BigObject. I was able to fix the performance issue by evicting each object that I retrieved as soon as I retrieved it.

I'm not much of a Hibernate expert, but I think that what was happening is that even though the objects were going out of scope in my code (and thus getting garbage collected), Hibernate was keeping a copy of each object in its cache. Then when it performed the next retrieval, it compared the retrieved object to all the cached ones. As the cache population rose, this operation would take longer and longer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM