Skip to content

Commit e3c9abe

Browse files
committed
perf: eliminate intermediate byte[] copies in StreamMessageConsume
- Add MessageJsonHandler.serialize(Message, OutputStream, Charset) - Serialize into ByteArrayOutputStream and write via writeTo(output) - Remove String.getBytes(...) and toByteArray() clone - Cache Charset instead of using encoding String No breaking changes: existing constructors retained; new overloads are additive.
1 parent 79e2cf7 commit e3c9abe

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

org.eclipse.lsp4j.jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
package org.eclipse.lsp4j.jsonrpc.json;
1313

1414
import java.io.IOException;
15+
import java.io.OutputStream;
16+
import java.io.OutputStreamWriter;
1517
import java.io.Reader;
1618
import java.io.StringReader;
1719
import java.io.StringWriter;
1820
import java.io.Writer;
21+
import java.nio.charset.Charset;
1922
import java.util.Collections;
2023
import java.util.Map;
2124
import java.util.function.Consumer;
@@ -149,6 +152,16 @@ public void serialize(Message message, Writer output) throws JsonIOException {
149152
gson.toJson(message, Message.class, output);
150153
}
151154

155+
public void serialize(Message message, OutputStream out, Charset charset) throws JsonIOException {
156+
try {
157+
final var writer = new OutputStreamWriter(out, charset);
158+
serialize(message, writer);
159+
writer.flush();
160+
} catch (IOException e) {
161+
throw new JsonIOException(e);
162+
}
163+
}
164+
152165
/**
153166
* Perform JSON serialization of the given object using the configuration of JSON-RPC messages
154167
* enhanced with the pretty printing option.

org.eclipse.lsp4j.jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageConsumer.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
******************************************************************************/
1212
package org.eclipse.lsp4j.jsonrpc.json;
1313

14+
import java.io.ByteArrayOutputStream;
1415
import java.io.IOException;
1516
import java.io.OutputStream;
17+
import java.nio.charset.Charset;
1618
import java.nio.charset.StandardCharsets;
1719

1820
import org.eclipse.lsp4j.jsonrpc.JsonRpcException;
@@ -24,22 +26,26 @@
2426
*/
2527
public class StreamMessageConsumer implements MessageConsumer, MessageConstants {
2628

27-
private final String encoding;
29+
private final Charset encoding;
2830
private final MessageJsonHandler jsonHandler;
2931

3032
private final Object outputLock = new Object();
3133

3234
private OutputStream output;
3335

3436
public StreamMessageConsumer(MessageJsonHandler jsonHandler) {
35-
this(null, StandardCharsets.UTF_8.name(), jsonHandler);
37+
this(null, StandardCharsets.UTF_8, jsonHandler);
3638
}
3739

3840
public StreamMessageConsumer(OutputStream output, MessageJsonHandler jsonHandler) {
39-
this(output, StandardCharsets.UTF_8.name(), jsonHandler);
41+
this(output, StandardCharsets.UTF_8, jsonHandler);
4042
}
4143

4244
public StreamMessageConsumer(OutputStream output, String encoding, MessageJsonHandler jsonHandler) {
45+
this(output, Charset.forName(encoding), jsonHandler);
46+
}
47+
48+
public StreamMessageConsumer(OutputStream output, Charset encoding, MessageJsonHandler jsonHandler) {
4349
this.output = output;
4450
this.encoding = encoding;
4551
this.jsonHandler = jsonHandler;
@@ -56,16 +62,16 @@ public void setOutput(OutputStream output) {
5662
@Override
5763
public void consume(Message message) {
5864
try {
59-
String content = jsonHandler.serialize(message);
60-
byte[] contentBytes = content.getBytes(encoding);
61-
int contentLength = contentBytes.length;
65+
final var content = new ByteArrayOutputStream(256);
66+
jsonHandler.serialize(message, content, encoding);
67+
int contentLength = content.size();
6268

6369
String header = getHeader(contentLength);
6470
byte[] headerBytes = header.getBytes(StandardCharsets.US_ASCII);
6571

6672
synchronized (outputLock) {
6773
output.write(headerBytes);
68-
output.write(contentBytes);
74+
content.writeTo(output);
6975
output.flush();
7076
}
7177
} catch (IOException exception) {
@@ -80,9 +86,9 @@ public void consume(Message message) {
8086
protected String getHeader(int contentLength) {
8187
final var headerBuilder = new StringBuilder();
8288
appendHeader(headerBuilder, CONTENT_LENGTH_HEADER, contentLength).append(CRLF);
83-
if (!StandardCharsets.UTF_8.name().equals(encoding)) {
89+
if (!StandardCharsets.UTF_8.equals(encoding)) {
8490
appendHeader(headerBuilder, CONTENT_TYPE_HEADER, JSON_MIME_TYPE);
85-
headerBuilder.append("; charset=").append(encoding).append(CRLF);
91+
headerBuilder.append("; charset=").append(encoding.name()).append(CRLF);
8692
}
8793
headerBuilder.append(CRLF);
8894
return headerBuilder.toString();

0 commit comments

Comments
 (0)