commons-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bernd Hopp (JIRA)" <>
Subject [jira] [Commented] (IO-468) Avoid allocating memory for method internal buffers, use threadlocal memory instead
Date Wed, 04 Feb 2015 14:50:34 GMT


Bernd Hopp commented on IO-468:

Hello Sebb, thanks for your comments. 

Your concerns regarding memory-usage are reasonable, so I simplified the code to use only
one static instance of the CharArrayThreadLocal and ByteArrayThreadLocal. This way, possible
memory leaks are prevented and all buffers are eventually released by the garbage collector
when the thread had finished. 

As for the skip-buffer, I would argue that after introducing ByteArrayThreadLocal it would
be redundant and memory-wasting to keep the SKIP_BUFFER, but that is just my opinion, I did
not do any measuring. 

Now here's a simple performance-test I wrote:

public class PerformanceTest
    public void test_performance() throws IOException
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(100000);

        byte[] input = new byte[100000];

        InputStream inputStream = new ByteArrayInputStream(input);

        long start = System.currentTimeMillis();

        for(int i = 0; i < 500000; i++){
            IOUtils.copy(inputStream, outputStream);

        long duration = System.currentTimeMillis() - start;

        System.out.println("took " + duration + " milliseconds");

On my Lenovo Thinkpad Core i7, running fedora core 21 and OpenJDK 1.8.0_31, I get 4413 milliseconds
for the old implementation and 3810 for the new one, that is about a 15 % boost in performance.
In setups where the Stream itself is the performance bottleneck, the difference won't be that
large. But I think it is clear that some scenarios could benefit significantly from the patch.


> Avoid allocating memory for method internal buffers, use threadlocal memory instead
> -----------------------------------------------------------------------------------
>                 Key: IO-468
>                 URL:
>             Project: Commons IO
>          Issue Type: Improvement
>          Components: Utilities
>    Affects Versions: 2.4
>         Environment: all environments
>            Reporter: Bernd Hopp
>            Priority: Minor
>              Labels: newbie, performance
>             Fix For: 2.5
>   Original Estimate: 12h
>  Remaining Estimate: 12h
> In a lot of places, we allocate new buffers dynamically via new byte[]. This is a performance
drawback since many of these allocations could be avoided if we would use threadlocal buffers
that can be reused. For example, consider the following code from, ln 2177:
> return copyLarge(input, output, inputOffset, length, new byte[DEFAULT_BUFFER_SIZE]);
> This code allocates new memory for every copy-process, that is not used outside of the
method and could easily and safely reused, as long as is is thread-local. So instead of allocating
new memory, a new utility-class could provide a thread-local bytearray like this:
> byte[] buffer = ThreadLocalByteArray.ofSize(DEFAULT_BUFFER_SIZE);
> return copyLarge(input, output, inputOffset, length, buffer);
> I have not measured the performance-benefits yet, but I would expect them to be significant,
especially when the streams itself are not the performance bottleneck. 
> Git PR is at

This message was sent by Atlassian JIRA

View raw message