CJKFont replace InputStream.read() to byte array reading ,improve init performance.#953
CJKFont replace InputStream.read() to byte array reading ,improve init performance.#953oymy wants to merge 1 commit into
Conversation
…ost in BufferedInputStream.read(); 10 times faster Signed-off-by: manyan.ouyang <manyan.ouyang@advancegroup.com>
|
Kudos, SonarCloud Quality Gate passed! |
|
Seems that PR #955 solves the same problem, but is shorter :) |
I think my solution is better, it benefits both loading from JAR and loading from disk ( when loading from disk , the InputStream returned by the class loader is already a BufferedInputStream) . I will do some tests to prove it. maybe in a few days. |
|
#955 has been merged now. If evidence is shown that this is faster, then we can reconsider. |
|
@andreasrosdal Test Explained:I added two readCMap methods in my test: Then test all three readCMap methods loading from disk /jar. Test Results:When loading from disk (run each methods 1000 times), the costs are:bytes: 251 When loading from jar (run each methos 1000 times), the costs are:bytes: 294 Test Results ExplainedWhen loading from diskThe underly InputStream returned from BaseFont.getResourceStream is already BufferedInputStream, so the performance of readCMapUsingBufferedStream is same as the old readCMap. When loading from jarreadCMap is very slow, because it reads every single byte one by one from the zip file. and the costs(decoding zip but only fetch one byte) are huge (check the logic of java.util.zip.DeflaterInputStream.read). ConclusionMy solution is faster in both loading from disk and jar. with a little more acceptable memory usage. My Test CodeCJKFontTest.java import org.junit.jupiter.api.Assertions; import java.io.BufferedInputStream; import static com.lowagie.text.pdf.BaseFont.RESOURCE_PATH; /**
}` |
|
@oymy Thank you for sharing the information. Though... Java authors claim that starting from Java 6, there were optimizations added that make this difference close to zero: https://bugs.openjdk.org/browse/JDK-4097272 |
@asolntsev Thank you for the comments. Yes. my solution is a radical version of BufferedInputStream. I did profiling ,and the result shows that the lock/unlock costs is not close to "zero" in this scenario. |









CJKFont.readCMap(String name) use InputStream.read() heavily ,which is slow.,
because the underling BufferedInputSteam does lock/unlock for every read().
Description of the new Feature/Bugfix
So load the stream into a byte[] ,then using the byte[] can avoid the costs,
leads at least 10 times faster initing CJKFont.
(with acceptable memory usage increments)
Related Issue: #
Unit-Tests for the new Feature/Bugfix
Compatibilities Issues
no
Testing details
no