Skip to content

Commit af98ae9

Browse files
committed
Avoid to flush an extra buffer when the string isn't too large in MessagePack#packString
1 parent fe287ba commit af98ae9

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

msgpack-core/src/main/java/org/msgpack/core/MessagePack.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public static class Config
5050
private final int stringEncoderBufferSize;
5151
private final int stringDecoderBufferSize;
5252
private final int packerBufferSize;
53+
private final int packerLargeStringThreshold;
5354
private final int packerRawDataCopyingThreshold;
5455

5556
public Config(
@@ -61,6 +62,7 @@ public Config(
6162
int stringEncoderBufferSize,
6263
int stringDecoderBufferSize,
6364
int packerBufferSize,
65+
int packerLargeStringLengthThreshold,
6466
int packerRawDataCopyingThreshold)
6567
{
6668
checkArgument(packerBufferSize > 0, "packer buffer size must be larger than 0: " + packerBufferSize);
@@ -75,6 +77,7 @@ public Config(
7577
this.stringEncoderBufferSize = stringEncoderBufferSize;
7678
this.stringDecoderBufferSize = stringDecoderBufferSize;
7779
this.packerBufferSize = packerBufferSize;
80+
this.packerLargeStringThreshold = packerLargeStringLengthThreshold;
7881
this.packerRawDataCopyingThreshold = packerRawDataCopyingThreshold;
7982
}
8083

@@ -133,6 +136,11 @@ public int getPackerBufferSize()
133136
return packerBufferSize;
134137
}
135138

139+
public int getPackerLargeStringLengthThreshold()
140+
{
141+
return packerLargeStringThreshold;
142+
}
143+
136144
public int getPackerRawDataCopyingThreshold()
137145
{
138146
return packerRawDataCopyingThreshold;
@@ -154,6 +162,7 @@ public static class ConfigBuilder
154162
private int stringEncoderBufferSize = 8192;
155163
private int stringDecoderBufferSize = 8192;
156164
private int packerBufferSize = 8192;
165+
private int packerLargeStringLengthThreshold = 512;
157166
private int packerRawDataCopyingThreshold = 512;
158167

159168
public Config build()
@@ -167,6 +176,7 @@ public Config build()
167176
stringEncoderBufferSize,
168177
stringDecoderBufferSize,
169178
packerBufferSize,
179+
packerLargeStringLengthThreshold,
170180
packerRawDataCopyingThreshold
171181
);
172182
}
@@ -219,6 +229,12 @@ public ConfigBuilder packerBufferSize(int size)
219229
return this;
220230
}
221231

232+
public ConfigBuilder packerLargeStringThreshold(int threshold)
233+
{
234+
this.packerLargeStringLengthThreshold = threshold;
235+
return this;
236+
}
237+
222238
public ConfigBuilder packerRawDataCopyingThreshold(int threshold)
223239
{
224240
this.packerRawDataCopyingThreshold = threshold;

msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,14 @@ public MessagePacker packDouble(double v)
442442
return this;
443443
}
444444

445+
private void packSmallString(String s)
446+
throws IOException
447+
{
448+
byte[] bytes = s.getBytes("UTF-8");
449+
packRawStringHeader(bytes.length);
450+
writePayload(bytes);
451+
}
452+
445453
/**
446454
* Pack the input String in UTF-8 encoding
447455
*
@@ -457,6 +465,12 @@ public MessagePacker packString(String s)
457465
return this;
458466
}
459467

468+
if (s.length() < config.getPackerLargeStringLengthThreshold()) {
469+
// Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer
470+
packSmallString(s);
471+
return this;
472+
}
473+
460474
CharBuffer in = CharBuffer.wrap(s);
461475
prepareEncoder();
462476

msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import org.msgpack.core.buffer.{ChannelBufferOutput, OutputStreamBufferOutput}
2222
import org.msgpack.value.ValueFactory
2323
import xerial.core.io.IOUtil
2424

25+
import scala.compat.Platform
2526
import scala.util.Random
2627

2728
/**
@@ -235,6 +236,25 @@ class MessagePackerTest
235236
up1.hasNext shouldBe false
236237
up1.close
237238
}
239+
240+
"pack a lot of String within expected time" in {
241+
val count = 500000
242+
243+
def measureDuration(outputStream: java.io.OutputStream) : Long = {
244+
val packer = MessagePack.newDefaultPacker(outputStream)
245+
val start = Platform.currentTime
246+
for (i <- 0 to count) {
247+
packer.packString("0123456789ABCDEF")
248+
}
249+
packer.close
250+
Platform.currentTime - start
251+
}
252+
253+
val baseDuration = measureDuration(new ByteArrayOutputStream())
254+
val (_, fileOutput) = createTempFileWithOutputStream
255+
val targetDuration = measureDuration(fileOutput)
256+
targetDuration shouldBe <= (baseDuration * 3)
257+
}
238258
}
239259

240260
"compute totalWrittenBytes" in {

0 commit comments

Comments
 (0)