From: Maros Marsalek Date: Fri, 24 Apr 2015 09:02:45 +0000 (+0200) Subject: Custom BufferedWriter implementation without newLine() X-Git-Tag: release/beryllium~611 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=5273304e9f607a15c1c17aca1c05d7aac2c0260e Custom BufferedWriter implementation without newLine() This BufferedWriter does not provide newLine() method and does not read the line.separator property via AccessController when its initialized. Whithout this expensive call, its allocation is much faster. Used in netconf message encoder to make the netconf serialization faster. Change-Id: I88a65c7a82ff7c44b9ad3a3adfe7d7482a5fdc70 Signed-off-by: Maros Marsalek --- diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/BufferedWriter.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/BufferedWriter.java new file mode 100644 index 0000000000..07c11b7d8e --- /dev/null +++ b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/BufferedWriter.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.nettyutil.handler; + + +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.Writer; +import javax.annotation.concurrent.NotThreadSafe; + +/** + * Custom BufferedWriter optimized for netconf pipeline implemented instead of default BufferedWriter provided by jdk. + *

+ * The line separator instance field in java.io.BufferedWriter is + * assigned using AccessController and takes considerable amount of time especially + * if lots of BufferedWriters are created in the system. + *

+ * This implementation should only be used if newLine method is not required + * such as netconf message to XML encoders. + * Methods in this implementation are not synchronized. + */ +@NotThreadSafe +public final class BufferedWriter extends Writer { + + private static final int DEFAULT_CHAR_BUFFER_SIZE = 8192; + + private final Writer writer; + private final char buffer[]; + private final int bufferSize; + + private int nextChar = 0; + + public BufferedWriter(final Writer writer) { + this(writer, DEFAULT_CHAR_BUFFER_SIZE); + } + + public BufferedWriter(final Writer writer, final int bufferSize) { + super(writer); + Preconditions.checkArgument(bufferSize > 0, "Buffer size <= 0"); + this.writer = writer; + this.buffer = new char[bufferSize]; + this.bufferSize = bufferSize; + } + + private void flushBuffer() throws IOException { + if (nextChar == 0) + return; + writer.write(buffer, 0, nextChar); + nextChar = 0; + } + + @Override + public void write(final int c) throws IOException { + if (nextChar >= bufferSize) + flushBuffer(); + buffer[nextChar++] = (char) c; + } + + @Override + public void write(final char[] buffer, final int offset, final int length) throws IOException { + if ((offset < 0) || (offset > buffer.length) || (length < 0) || + ((offset + length) > buffer.length) || ((offset + length) < 0)) { + throw new IndexOutOfBoundsException(String.format("Buffer size: %d, Offset: %d, Length: %d", buffer.length, offset, length)); + } else if (length == 0) { + return; + } + + if (length >= bufferSize) { + flushBuffer(); + writer.write(buffer, offset, length); + return; + } + + int b = offset; + final int t = offset + length; + while (b < t) { + final int d = Math.min(bufferSize - nextChar, t - b); + System.arraycopy(buffer, b, this.buffer, nextChar, d); + b += d; + nextChar += d; + if (nextChar >= bufferSize) + flushBuffer(); + } + } + + @Override + public void write(final String string, final int offset, final int length) throws IOException { + int b = offset; + final int t = offset + length; + while (b < t) { + final int d = Math.min(bufferSize - nextChar, t - b); + string.getChars(b, b + d, buffer, nextChar); + b += d; + nextChar += d; + if (nextChar >= bufferSize) + flushBuffer(); + } + } + + @Override + public void flush() throws IOException { + flushBuffer(); + writer.flush(); + } + + @Override + public void close() throws IOException { + try { + flushBuffer(); + } finally { + writer.close(); + } + } +} diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToXMLEncoder.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToXMLEncoder.java index 99251b00d4..cf6dbb63b6 100644 --- a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToXMLEncoder.java +++ b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToXMLEncoder.java @@ -13,7 +13,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; -import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; @@ -50,7 +49,10 @@ public class NetconfMessageToXMLEncoder extends MessageToByteEncoder