[
https://issues.apache.org/jira/browse/XGC-93?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14989263#comment-14989263
]
Matthias Reischenbacher commented on XGC-93:
--------------------------------------------
Ok, done. Committed fix with:
http://svn.apache.org/viewvc?view=revision&revision=1712525
@[~aklm]: thanks for your change. Please resolve issue, I'm missing rights to
do so. Thanks.
> Calling DeflaterOutputStream.write(byte) byte by byte causes blocked threads
> in multi session-environments
> ----------------------------------------------------------------------------------------------------------
>
> Key: XGC-93
> URL: https://issues.apache.org/jira/browse/XGC-93
> Project: XMLGraphicsCommons
> Issue Type: Improvement
> Components: postscript
> Affects Versions: trunk
> Environment: WebSphere Application Server 7.0 with AIX 7.1 and JDK
> 1.6.0
> fop.jar, Implementation-Version: 1.1, Build-Id: 20121016-224756-ICT (glenn
> [Mac OS X 10.8.1 x86_64, Java 1.6.0_35-b10-428-11M3811, Target Java 1.5])
> xmlgraphics-commons-1.5.jar, Implementation-Version: 1.5, Build-Id:
> 20121016-215324-ICT (glenn [Mac OS X 10.8.1 x86_64, Java
> 1.6.0_35-b10-428-11M3811])
> Reporter: Andre Klemann
> Labels: easyfix, performance
> Fix For: trunk
>
> Attachments: xgc-93.patch
>
>
> The method
> org.apache.xmlgraphics.ps.ImageEncodingHelper.optimizedWriteTo(OutputStream)
> from xmlgraphics-commons-1.5.jar calls the method
> DeflaterOutputStream.write(byte) byte by byte (see lines 242 - 244):
> private boolean optimizedWriteTo(OutputStream out)
> throws IOException {
> if (this.firstTileDump) {
> Raster raster = image.getTile(0, 0);
> DataBuffer buffer = raster.getDataBuffer();
> if (buffer instanceof DataBufferByte) {
> byte[] bytes = ((DataBufferByte) buffer).getData();
> // see determineEncodingColorModel() to see why we permute B
> and R here
> if (isBGR) {
> for (int i = 0; i < bytes.length; i += 3) {
> out.write(bytes[i + 2]); // 242
> out.write(bytes[i + 1]); // 243
> out.write(bytes[i]); // 244
> }
> } else {
> out.write(bytes);
> }
> return true;
> }
> }
> return false;
> }
> Under WebSphere, in a multi-session environment, this leads to warnings about
> possibly hanging threads:
> [07.03.13 08:34:22:673 MEZ] 0000000d ThreadMonitor W WSVR0605W: Thread
> "WebContainer : 1303" (00000547) has been active for 165445 milliseconds and
> may be hung. There is/are 1 thread(s) in total in the server that may be
> hung.
> at java.util.zip.Deflater.deflateBytes(Native Method)
> at java.util.zip.Deflater.deflate(Deflater.java:306)
> at
> java.util.zip.DeflaterOutputStream.deflate(DeflaterOutputStream.java:153)
> at
> java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:112)
> at
> java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:89)
> at
> org.apache.xmlgraphics.ps.ImageEncodingHelper.optimizedWriteTo(ImageEncodingHelper.java:242)
> ...
> [07.03.13 08:38:18:886 MEZ] 00000547 ThreadMonitor W WSVR0606W: Thread
> "WebContainer : 1303" (00000547) was previously reported to be hung but has
> completed. It was active for approximately 401662 milliseconds. There
> is/are 0 thread(s) in total in the server that still may be hung.
> [07.03.13 08:40:22:723 MEZ] 0000002d ThreadMonitor W WSVR0605W: Thread
> "WebContainer : 1323" (0000055b) has been active for 221920 milliseconds and
> may be hung. There is/are 1 thread(s) in total in the server that may be
> hung.
> at java.util.zip.Deflater.deflateBytes(Native Method)
> at java.util.zip.Deflater.deflate(Deflater.java:306)
> at
> java.util.zip.DeflaterOutputStream.deflate(DeflaterOutputStream.java:153)
> at
> java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:112)
> at
> java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:89)
> at
> org.apache.xmlgraphics.ps.ImageEncodingHelper.optimizedWriteTo(ImageEncodingHelper.java:244)
> ...
> The threads will finish their work, but this takes a long time.
> The reason for this is, that the number n of calls to
> java.util.zip.DeflaterOutputStream.write(byte) might be in a hight range. I
> have seen cases, where n=4094496. This leads to n calls of
> DeflaterOutputSteam.write(byte[] b, int off, int len), where off=0 and len=1:
> public void write(byte[] b, int off, int len) throws IOException {
> if (def.finished()) {
> throw new IOException("write beyond end of stream");
> }
> if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
> throw new IndexOutOfBoundsException();
> } else if (len == 0) {
> return;
> }
> if (!def.finished()) {
> // Deflate no more than stride bytes at a time. This avoids
> // excess copying in deflateBytes (see Deflater.c)
> int stride = buf.length;
> for (int i = 0; i < len; i+= stride) {
> def.setInput(b, off + i, Math.min(stride, len - i)); //
> line 116
> while (!def.needsInput()) {
> deflate();
> // line 118
> }
> }
> }
> }
> Since java.util.zip.Deflater internally uses synchronized blocks, esspecially
> in setInput(byte[], int, int) and deflate(byte[], int, int), one should
> reduce the number of calls to these methods as much as possible.
> The number of calls of Deflater.setInput(byte[] b, int off, int len) in line
> 116
> above could, e.g., be reduced by the factor 512 (=buffer.length), if the
> method ImageEncodingHelper.optimizedWriteTo() would be written in this way:
> private boolean optimizedWriteTo(OutputStream out)
> throws IOException {
> if (this.firstTileDump) {
> Raster raster = image.getTile(0, 0);
> DataBuffer buffer = raster.getDataBuffer();
> if (buffer instanceof DataBufferByte) {
> byte[] bytes = ((DataBufferByte) buffer).getData();
> // see determineEncodingColorModel() to see why we permute B
> and R here
> if (isBGR) {
> byte[] bytesPermutated = new byte[bytes.length];
> for (int i = 0; i < bytes.length; i += 3) {
> bytesPermutated[i] = bytes[i+2];
> bytesPermutated[i+1] = bytes[i+1];
> bytesPermutated[i+2] = bytes[i];
> }
> out.write(bytesPermutated);
> } else {
> out.write(bytes);
> }
> return true;
> }
> }
> return false;
> }
> In this version, n calls of DeflaterOutputStream.write(byte) are replaced by
> one call of DeflaterOutputStream(byte[]), which is much faster and offers
> less blocking potential.
> Without this optimization and with activated zlib compression in FOP 1.1, we
> always got warnings from WeSphere's thread monitor, that some threads may
> hang.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]