Class StreamCharBuffer
- All Implemented Interfaces:
Externalizable
,Serializable
,CharSequence
StreamCharBuffer is a multipurpose in-memory buffer that can replace JDK in-memory buffers (StringBuffer, StringBuilder, StringWriter).
Grails GSP rendering uses this class as a buffer that is optimized for performance.
StreamCharBuffer keeps the buffer in a linked list of "chunks". The main difference compared to JDK in-memory buffers (StringBuffer, StringBuilder & StringWriter) is that the buffer can be held in several smaller buffers ("chunks" here). In JDK in-memory buffers, the buffer has to be expanded whenever it gets filled up. The old buffer's data is copied to the new one and the old one is discarded. In StreamCharBuffer, there are several ways to prevent unnecessary allocation & copy operations. The StreamCharBuffer contains a linked list of different type of chunks: char arrays, java.lang.String chunks and other StreamCharBuffers as sub chunks. A StringChunk is appended to the linked list whenever a java.lang.String of a length that exceeds the "stringChunkMinSize" value is written to the buffer.
Grails tag libraries also use a StreamCharBuffer to "capture" the output of the taglib and return it to the caller. The buffer can be appended to it's parent buffer directly without extra object generation (like converting to java.lang.String in between). for example this line of code in a taglib would just append the buffer returned from the body closure evaluation to the buffer of the taglib:
out << body()
other example:
out << g.render(template: '/some/template', model:[somebean: somebean])
There's no extra java.lang.String generation overhead.
There's a java.io.Writer interface for appending character data to the buffer and a java.io.Reader interface for reading data.
Each getReader()
call will create a new reader instance that keeps
it own state.
There is a alternative method getReader(boolean)
for creating the
reader. When reader is created by calling getReader(true), the reader will
remove already read characters from the buffer. In this mode only a single
reader instance is supported.
There's also several other options for reading data:
readAsCharArray()
reads the buffer to a char[] arrayreadAsString()
reads the buffer and wraps the char[] data as a StringwriteTo(Writer)
writes the buffer to a java.io.WritertoCharArray()
returns the buffer as a char[] array, caches the return value internally so that this method can be called several times.toString()
returns the buffer as a String, caches the return value internally
By using the "connectTo" method, one can connect the buffer directly to a target java.io.Writer. The internal buffer gets flushed automaticly to the target whenever the buffer gets filled up. See connectTo(Writer).
This class is not thread-safe. Object instances of this class are intended to be used by a single Thread. The Reader and Writer interfaces can be open simultaneous and the same Thread can write and read several times.
Main operation principle:
StreamCharBuffer keeps the buffer in a linked link of "chunks". The main difference compared to JDK in-memory buffers (StringBuffer, StringBuilder & StringWriter) is that the buffer can be held in several smaller buffers ("chunks" here). In JDK in-memory buffers, the buffer has to be expanded whenever it gets filled up. The old buffer's data is copied to the new one and the old one is discarded. In StreamCharBuffer, there are several ways to prevent unnecessary allocation & copy operations.
There can be several different type of chunks: char arrays (
CharBufferChunk
), String chunks (StringChunk
) and other
StreamCharBuffers as sub chunks (StreamCharBufferSubChunk
).
Child StreamCharBuffers can be changed after adding to parent buffer. The flush() method must be called on the child buffer's Writer to notify the parent that the child buffer's content has been changed (used for calculating total size).
A StringChunk is appended to the linked list whenever a java.lang.String of a length that exceeds the "stringChunkMinSize" value is written to the buffer.
If the buffer is in "connectTo" mode, any String or char[] that's length is over writeDirectlyToConnectedMinSize gets written directly to the target. The buffer content will get fully flushed to the target before writing the String or char[].
There can be several targets "listening" the buffer in "connectTo" mode. The same content will be written to all targets.
Growable chunksize: By default, a newly allocated chunk's size will grow based on the total size of all written chunks. The default growProcent value is 100. If the total size is currently 1024, the newly created chunk will have a internal buffer that's size is 1024. Growable chunksize can be turned off by setting the growProcent to 0. There's a default maximum chunksize of 1MB by default. The minimum size is the initial chunksize size.
System Property name | Description | Default value |
---|---|---|
streamcharbuffer.chunksize | default chunk size - the size the first allocated buffer | 512 |
streamcharbuffer.maxchunksize | maximum chunk size - the maximum size of the allocated buffer | 1048576 |
streamcharbuffer.growprocent | growing buffer percentage - the newly allocated buffer is defined by total_size * (growpercent/100) | 100 |
streamcharbuffer.subbufferchunkminsize | minimum size of child StreamCharBuffer chunk - if the size is smaller, the content is copied to the parent buffer | 512 |
streamcharbuffer.substringchunkminsize | minimum size of String chunks - if the size is smaller, the content is copied to the buffer | 512 |
streamcharbuffer.chunkminsize | minimum size of chunk that gets written directly to the target in connected mode. | 256 |
Configuration values can also be changed for each instance of StreamCharBuffer individually. Default values are defined with System Properties.
See org.codehaus.groovy.grails.web.util.StreamCharBuffer file licensed under ASL v2.0 Copyright 2009 the original author or authors. Author Lari Hotari, Sagire Software Oy- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interface
Interface for a Writer that gets initialized if it is used Can be used for passing in to "connectTo" method of StreamCharBufferfinal class
This is the java.io.Reader implementation for StreamCharBufferfinal class
This is the java.io.Writer implementation for StreamCharBuffer -
Constructor Summary
ConstructorsConstructorDescriptionStreamCharBuffer
(int chunkSize) StreamCharBuffer
(int chunkSize, int growProcent) StreamCharBuffer
(int chunkSize, int growProcent, int maxChunkSize) -
Method Summary
Modifier and TypeMethodDescriptionvoid
appendStreamCharBufferChunk
(StreamCharBuffer subBuffer) protected static final void
arrayCopy
(char[] src, int srcPos, char[] dest, int destPos, int length) boolean
char
charAt
(int index) final void
clear()
Clears the buffer and notifies the parents of this buffer of the changefinal void
Connect this buffer to a target Writer.final void
final void
final void
connectTo
(StreamCharBuffer.LazyInitializingWriter w, boolean autoFlush) boolean
equals uses String.equals to check for equality to support compatibility with String instances in maps, sets, etc.int
Creates a new Reader instance for reading/consuming data from the buffer.getReader
(boolean removeAfterReading) Like getReader(), but when removeAfterReading is true, the read data will be removed from the buffer.int
int
int
Writer interface for adding/writing data to the buffer.int
hashCode()
Uses String's hashCode to support compatibility with String instances in maps, sets, etc.protected boolean
boolean
boolean
isEmpty()
boolean
int
length()
char[]
Reads the buffer to a char[].Reads the buffer to a String.void
final void
final void
reset()
final void
reset
(boolean resetChunkSize) resets the state of this buffer (empties it)protected void
void
setChunkMinSize
(int chunkMinSize) void
setPreferSubChunkWhenWritingToOtherBuffer
(boolean preferSubChunkWhenWritingToOtherBuffer) void
setSubBufferChunkMinSize
(int subBufferChunkMinSize) void
setSubStringChunkMinSize
(int stringChunkMinSize) Minimum size for a String to be added as a StringChunk instead of copying content to the char[] buffer of the current StreamCharBufferChunkvoid
setWriteDirectlyToConnectedMinSize
(int writeDirectlyToConnectedMinSize) Minimum size for a String or char[] to get written directly to connected writer (in "connectTo" mode).int
size()
subSequence
(int start, int end) char[]
Reads the buffer to a char[].toString()
Reads (and empties) the buffer to a String, but caches the return value for subsequent calls.void
Writes the buffer content to a target java.io.Writervoid
Writes the buffer content to a target java.io.WriterMethods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
Methods inherited from interface java.lang.CharSequence
chars, codePoints
-
Constructor Details
-
StreamCharBuffer
public StreamCharBuffer() -
StreamCharBuffer
public StreamCharBuffer(int chunkSize) -
StreamCharBuffer
public StreamCharBuffer(int chunkSize, int growProcent) -
StreamCharBuffer
public StreamCharBuffer(int chunkSize, int growProcent, int maxChunkSize)
-
-
Method Details
-
isPreferSubChunkWhenWritingToOtherBuffer
public boolean isPreferSubChunkWhenWritingToOtherBuffer() -
setPreferSubChunkWhenWritingToOtherBuffer
public void setPreferSubChunkWhenWritingToOtherBuffer(boolean preferSubChunkWhenWritingToOtherBuffer) -
reset
public final void reset() -
reset
public final void reset(boolean resetChunkSize) resets the state of this buffer (empties it)- Parameters:
resetChunkSize
-
-
clear
public final void clear()Clears the buffer and notifies the parents of this buffer of the change -
connectTo
Connect this buffer to a target Writer. When the buffer (a chunk) get filled up, it will automaticly write it's content to the Writer- Parameters:
w
-
-
connectTo
-
connectTo
-
connectTo
-
removeConnections
public final void removeConnections() -
getSubStringChunkMinSize
public int getSubStringChunkMinSize() -
setSubStringChunkMinSize
public void setSubStringChunkMinSize(int stringChunkMinSize) Minimum size for a String to be added as a StringChunk instead of copying content to the char[] buffer of the current StreamCharBufferChunk- Parameters:
stringChunkMinSize
-
-
getSubBufferChunkMinSize
public int getSubBufferChunkMinSize() -
setSubBufferChunkMinSize
public void setSubBufferChunkMinSize(int subBufferChunkMinSize) -
getWriteDirectlyToConnectedMinSize
public int getWriteDirectlyToConnectedMinSize() -
setWriteDirectlyToConnectedMinSize
public void setWriteDirectlyToConnectedMinSize(int writeDirectlyToConnectedMinSize) Minimum size for a String or char[] to get written directly to connected writer (in "connectTo" mode).- Parameters:
writeDirectlyToConnectedMinSize
-
-
getChunkMinSize
public int getChunkMinSize() -
setChunkMinSize
public void setChunkMinSize(int chunkMinSize) -
getWriter
Writer interface for adding/writing data to the buffer.- Returns:
- the Writer
-
getReader
Creates a new Reader instance for reading/consuming data from the buffer. Each call creates a new instance that will keep it's reading state. There can be several readers on the buffer. (single thread only supported)- Returns:
- the Reader
-
getReader
Like getReader(), but when removeAfterReading is true, the read data will be removed from the buffer.- Parameters:
removeAfterReading
-- Returns:
- the Reader
-
writeTo
Writes the buffer content to a target java.io.Writer- Parameters:
target
-- Throws:
IOException
-
writeTo
Writes the buffer content to a target java.io.Writer- Parameters:
target
- WriterflushTarget
- calls target.flush() before finishingemptyAfter
- empties the buffer if true- Throws:
IOException
-
readAsCharArray
public char[] readAsCharArray()Reads the buffer to a char[].- Returns:
- the chars
-
readAsString
Reads the buffer to a String.- Returns:
- the String
-
toString
Reads (and empties) the buffer to a String, but caches the return value for subsequent calls. If more content has been added between 2 calls, the returned value will be joined from the previously cached value and the data read from the buffer.- Specified by:
toString
in interfaceCharSequence
- Overrides:
toString
in classObject
- See Also:
-
hashCode
public int hashCode()Uses String's hashCode to support compatibility with String instances in maps, sets, etc. -
equals
equals uses String.equals to check for equality to support compatibility with String instances in maps, sets, etc. -
plus
-
plus
-
toCharArray
public char[] toCharArray()Reads the buffer to a char[]. Caches the result if there aren't any readers.- Returns:
- the chars
-
size
public int size() -
isEmpty
public boolean isEmpty()- Specified by:
isEmpty
in interfaceCharSequence
-
appendStreamCharBufferChunk
- Throws:
IOException
-
isConnectedMode
public boolean isConnectedMode() -
isChunkSizeResizeable
protected boolean isChunkSizeResizeable() -
resizeChunkSizeAsProcentageOfTotalSize
protected void resizeChunkSizeAsProcentageOfTotalSize() -
arrayCopy
protected static final void arrayCopy(char[] src, int srcPos, char[] dest, int destPos, int length) -
charAt
public char charAt(int index) - Specified by:
charAt
in interfaceCharSequence
-
length
public int length()- Specified by:
length
in interfaceCharSequence
-
subSequence
- Specified by:
subSequence
in interfaceCharSequence
-
asBoolean
public boolean asBoolean() -
readExternal
- Specified by:
readExternal
in interfaceExternalizable
- Throws:
IOException
ClassNotFoundException
-
writeExternal
- Specified by:
writeExternal
in interfaceExternalizable
- Throws:
IOException
-