[
https://issues.apache.org/jira/browse/IO-468?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14305183#comment-14305183
]
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
{
@Test
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);
inputStream.reset();
outputStream.reset();
}
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.
Regards
Bernd
> Avoid allocating memory for method internal buffers, use threadlocal memory
> instead
> -----------------------------------------------------------------------------------
>
> Key: IO-468
> URL: https://issues.apache.org/jira/browse/IO-468
> 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 IOUtils.java, 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 https://github.com/apache/commons-io/pull/6/files
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)