Skip to content

Commit

Permalink
Improve AppendableWriter performance (#1706)
Browse files Browse the repository at this point in the history
* Improve AppendableWriter performance

Override methods which by default create char arrays or convert
CharSequences to Strings.
This is not necessary for AppendableWriter because it can directly
append these values to the Appendable delegate.

* Add test for Streams.writerForAppendable
  • Loading branch information
Marcono1234 committed Jul 31, 2022
1 parent a4290c5 commit 5f2513a
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 2 deletions.
23 changes: 21 additions & 2 deletions gson/src/main/java/com/google/gson/internal/Streams.java
Expand Up @@ -93,12 +93,31 @@ private static final class AppendableWriter extends Writer {
appendable.append(currentWrite, offset, offset + length);
}

@Override public void flush() {}
@Override public void close() {}

// Override these methods for better performance
// They would otherwise unnecessarily create Strings or char arrays

@Override public void write(int i) throws IOException {
appendable.append((char) i);
}

@Override public void flush() {}
@Override public void close() {}
@Override public void write(String str, int off, int len) throws IOException {
// Appendable.append turns null -> "null", which is not desired here
$Gson$Preconditions.checkNotNull(str);
appendable.append(str, off, off + len);
}

@Override public Writer append(CharSequence csq) throws IOException {
appendable.append(csq);
return this;
}

@Override public Writer append(CharSequence csq, int start, int end) throws IOException {
appendable.append(csq, start, end);
return this;
}

/**
* A mutable char sequence pointing at a single char[].
Expand Down
68 changes: 68 additions & 0 deletions gson/src/test/java/com/google/gson/internal/StreamsTest.java
@@ -0,0 +1,68 @@
package com.google.gson.internal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.io.Writer;
import org.junit.Test;

public class StreamsTest {
@Test
public void testWriterForAppendable() throws IOException {
StringBuilder stringBuilder = new StringBuilder();
Writer writer = Streams.writerForAppendable(stringBuilder);

writer.append('a');
writer.append('\u1234');
writer.append("test");
writer.append(null); // test custom null handling mandated by `append`
writer.append("abcdef", 2, 4);
writer.append(null, 1, 3); // test custom null handling mandated by `append`
writer.append(',');

writer.write('a');
writer.write('\u1234');
// Should only consider the 16 low-order bits
writer.write(0x4321_1234);
writer.append(',');

writer.write("chars".toCharArray());
try {
writer.write((char[]) null);
fail();
} catch (NullPointerException e) {
}

writer.write("chars".toCharArray(), 1, 2);
try {
writer.write((char[]) null, 1, 2);
fail();
} catch (NullPointerException e) {
}
writer.append(',');

writer.write("string");
try {
writer.write((String) null);
fail();
} catch (NullPointerException e) {
}

writer.write("string", 1, 2);
try {
writer.write((String) null, 1, 2);
fail();
} catch (NullPointerException e) {
}

String actualOutput = stringBuilder.toString();
assertEquals("a\u1234testnullcdul,a\u1234\u1234,charsha,stringtr", actualOutput);

writer.flush();
writer.close();

// flush() and close() calls should have had no effect
assertEquals(actualOutput, stringBuilder.toString());
}
}

0 comments on commit 5f2513a

Please sign in to comment.