-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
28 changed files
with
433 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package perfio; | ||
|
||
import com.google.protobuf.compiler.PluginProtos as GPluginProtos | ||
import org.openjdk.jmh.annotations.* | ||
import org.openjdk.jmh.infra.* | ||
import perfio.protoapi.PluginProtos as PPluginProtos | ||
|
||
import java.io.{BufferedInputStream, BufferedOutputStream, ByteArrayOutputStream, FileInputStream, FileOutputStream} | ||
import java.nio.ByteOrder | ||
import java.nio.file.{Files, Path} | ||
import java.util.concurrent.TimeUnit | ||
|
||
@BenchmarkMode(Array(Mode.AverageTime)) | ||
@Fork(value = 1, jvmArgsAppend = Array("-Xmx12g", "-Xss32M", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseZGC", "--enable-native-access=ALL-UNNAMED", "--add-modules", "jdk.incubator.vector")) | ||
@Threads(1) | ||
@Warmup(iterations = 7, time = 1) | ||
@Measurement(iterations = 7, time = 1) | ||
@OutputTimeUnit(TimeUnit.MICROSECONDS) | ||
@State(Scope.Benchmark) | ||
class ReadWriteBenchmark: | ||
|
||
private var testData: Array[Byte] = null | ||
private val testDataFile = Path.of("src/main/resources/CodeGeneratorRequest-pack.bin") | ||
|
||
@Setup(Level.Trial) | ||
def buildTestData(): Unit = | ||
testData = Files.readAllBytes(testDataFile) | ||
assert(testData.length == 159366, s"testData.length ${testData.length}") | ||
|
||
@Benchmark | ||
def array_google(bh: Blackhole): Unit = | ||
val p = GPluginProtos.CodeGeneratorRequest.parseFrom(testData) | ||
val out = new ByteArrayOutputStream() | ||
p.writeTo(out) | ||
out.close() | ||
bh.consume(out.size()) | ||
|
||
@Benchmark | ||
def array_perfio(bh: Blackhole): Unit = | ||
val p = PPluginProtos.CodeGeneratorRequest.parseFrom(BufferedInput.ofArray(testData).order(ByteOrder.LITTLE_ENDIAN)) | ||
val bo = BufferedOutput.growing(4096) | ||
p.writeTo(bo) | ||
bo.close() | ||
bh.consume(bo.length()) | ||
|
||
@Benchmark | ||
def file_google(bh: Blackhole): Unit = | ||
val in = new BufferedInputStream(new FileInputStream(testDataFile.toFile)) | ||
val p = GPluginProtos.CodeGeneratorRequest.parseFrom(in) | ||
in.close() | ||
val out = new BufferedOutputStream(new FileOutputStream("/dev/null")) | ||
p.writeTo(out) | ||
out.close() | ||
|
||
@Benchmark | ||
def file_perfio(bh: Blackhole): Unit = | ||
val in = BufferedInput.of(new FileInputStream(testDataFile.toFile)).order(ByteOrder.LITTLE_ENDIAN) | ||
val p = PPluginProtos.CodeGeneratorRequest.parseFrom(in) | ||
in.close() | ||
val bo = BufferedOutput.ofFile(Path.of("/dev/null"), 8192) | ||
p.writeTo(bo) | ||
bo.close() | ||
|
||
@Benchmark | ||
def file_perfio_mapped(bh: Blackhole): Unit = | ||
val in = BufferedInput.ofMappedFile(testDataFile).order(ByteOrder.LITTLE_ENDIAN) | ||
val p = PPluginProtos.CodeGeneratorRequest.parseFrom(in) | ||
in.close() | ||
val bo = BufferedOutput.ofFile(Path.of("/dev/null"), 8192) | ||
p.writeTo(bo) | ||
bo.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package perfio | ||
|
||
import com.google.protobuf.compiler.PluginProtos as GPluginProtos | ||
import com.google.protobuf.{CodedOutputStream, GeneratedMessage as GGeneratedMessage, Parser as GParser} | ||
import org.openjdk.jmh.annotations.* | ||
import org.openjdk.jmh.infra.* | ||
import perfio.proto.runtime.GeneratedMessage as PGeneratedMessage | ||
import perfio.protoapi.PluginProtos as PPluginProtos | ||
|
||
import java.io.{BufferedOutputStream, ByteArrayOutputStream, FileOutputStream, OutputStream} | ||
import java.lang.invoke.{MethodHandles, MethodType} | ||
import java.nio.file.Path | ||
import java.util.concurrent.TimeUnit | ||
|
||
@BenchmarkMode(Array(Mode.AverageTime)) | ||
@Fork(value = 1, jvmArgsAppend = Array("-Xmx12g", "-Xss32M", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseZGC", "--enable-native-access=ALL-UNNAMED", "--add-modules", "jdk.incubator.vector")) | ||
@Threads(1) | ||
@Warmup(iterations = 15, time = 1) | ||
@Measurement(iterations = 10, time = 1) | ||
@OutputTimeUnit(TimeUnit.MICROSECONDS) | ||
@State(Scope.Benchmark) | ||
class SmallWriteBenchmark: | ||
|
||
@Param(Array("version1000")) | ||
var testCase: String = null | ||
|
||
private var gMessage: GGeneratedMessage = null | ||
private var pMessage: PGeneratedMessage = null | ||
private var count = 1; | ||
|
||
private def p2g(p: PGeneratedMessage, gp: GParser[? <: GGeneratedMessage]): GGeneratedMessage = { | ||
val out = BufferedOutput.growing() | ||
p.writeTo(out) | ||
out.close() | ||
gp.parseFrom(out.toInputStream) | ||
} | ||
|
||
val clearMemoMethod = { | ||
val lookup = MethodHandles.privateLookupIn(classOf[GGeneratedMessage], MethodHandles.lookup()) | ||
lookup.findVirtual(classOf[GGeneratedMessage], "setMemoizedSerializedSize", MethodType.methodType(Void.TYPE, Integer.TYPE)) | ||
} | ||
|
||
private def clearMemo(m: GGeneratedMessage): Unit = { | ||
clearMemoMethod.invokeExact(m, -1) | ||
} | ||
|
||
@Setup(Level.Trial) | ||
def buildInvocationData(): Unit = | ||
testCase match | ||
case "version1000" => | ||
pMessage = (new PPluginProtos.Version).setMajor(1).setMinor(2).setPatch(3) //.setSuffix("foo") | ||
gMessage = p2g(pMessage, GPluginProtos.Version.parser()) | ||
count = 1000 | ||
case "versionString1000" => | ||
pMessage = (new PPluginProtos.Version).setMajor(1).setMinor(2).setPatch(3).setSuffix("foo") | ||
gMessage = p2g(pMessage, GPluginProtos.Version.parser()) | ||
count = 1000 | ||
case "versionString1" => | ||
pMessage = (new PPluginProtos.Version).setMajor(1).setMinor(2).setPatch(3).setSuffix("foo") | ||
gMessage = p2g(pMessage, GPluginProtos.Version.parser()) | ||
count = 1 | ||
case "strings" => | ||
val r = new PPluginProtos.CodeGeneratorRequest | ||
for(i <- 1 to 1000) r.addFileToGenerate(s"file $i") | ||
pMessage = r | ||
gMessage = p2g(pMessage, GPluginProtos.CodeGeneratorRequest.parser()) | ||
count = 10 | ||
case "nested" => | ||
val r = new PPluginProtos.CodeGeneratorRequest | ||
r.setCompilerVersion((new PPluginProtos.Version).setMajor(1).setMinor(2).setPatch(3).setSuffix("foo")) | ||
pMessage = r | ||
gMessage = p2g(pMessage, GPluginProtos.CodeGeneratorRequest.parser()) | ||
count = 100 | ||
|
||
private def writeGoogle(out: OutputStream): Unit = | ||
val c = CodedOutputStream.newInstance(out, 4096) | ||
var i = 0 | ||
while i < count do | ||
//clearMemo(gMessage.asInstanceOf[GPluginProtos.CodeGeneratorRequest].getCompilerVersion) | ||
gMessage.writeTo(c) | ||
i += 1 | ||
c.flush() | ||
out.close() | ||
|
||
private def writePerfio(out: BufferedOutput): Unit = | ||
var i = 0 | ||
while i < count do | ||
pMessage.writeTo(out) | ||
i += 1 | ||
out.close() | ||
|
||
@Benchmark | ||
def array_google(bh: Blackhole): Unit = | ||
val baos = new ByteArrayOutputStream() | ||
writeGoogle(baos) | ||
bh.consume(baos.size()) | ||
|
||
@Benchmark | ||
def array_perfio(bh: Blackhole): Unit = | ||
val bo = BufferedOutput.growing(4096) | ||
writePerfio(bo) | ||
bh.consume(bo.length()) | ||
|
||
@Benchmark | ||
def file_google(bh: Blackhole): Unit = | ||
val out = new BufferedOutputStream(new FileOutputStream("/dev/null")) | ||
writeGoogle(out) | ||
out.close() | ||
|
||
@Benchmark | ||
def file_perfio(bh: Blackhole): Unit = | ||
val bo = BufferedOutput.ofFile(Path.of("/dev/null"), 8192) | ||
writePerfio(bo) | ||
bo.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,91 @@ | ||
package perfio | ||
|
||
import org.openjdk.jmh.annotations._ | ||
import org.openjdk.jmh.infra._ | ||
import com.google.protobuf.{CodedOutputStream, GeneratedMessage as GGeneratedMessage, Parser as GParser} | ||
import perfio.proto.runtime.GeneratedMessage as PGeneratedMessage | ||
import org.openjdk.jmh.annotations.* | ||
import org.openjdk.jmh.infra.* | ||
|
||
import java.util.concurrent.TimeUnit | ||
import com.google.protobuf.compiler.{PluginProtos => GPluginProtos} | ||
import perfio.protoapi.{PluginProtos => PPluginProtos} | ||
import com.google.protobuf.compiler.PluginProtos as GPluginProtos | ||
import perfio.protoapi.PluginProtos as PPluginProtos | ||
|
||
import java.io.{BufferedOutputStream, ByteArrayOutputStream, FileOutputStream} | ||
import java.io.{BufferedOutputStream, ByteArrayOutputStream, FileOutputStream, OutputStream} | ||
import java.lang.invoke.{MethodHandles, MethodType} | ||
import java.nio.ByteOrder | ||
import java.nio.file.{Files, Path} | ||
|
||
import scala.jdk.CollectionConverters._ | ||
|
||
@BenchmarkMode(Array(Mode.AverageTime)) | ||
@Fork(value = 1, jvmArgsAppend = Array("-Xmx12g", "-Xss32M", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseZGC", "--enable-native-access=ALL-UNNAMED", "--add-modules", "jdk.incubator.vector")) | ||
@Threads(1) | ||
@Warmup(iterations = 7, time = 1) | ||
@Measurement(iterations = 7, time = 1) | ||
@Warmup(iterations = 15, time = 1) | ||
@Measurement(iterations = 10, time = 1) | ||
@OutputTimeUnit(TimeUnit.MICROSECONDS) | ||
@State(Scope.Benchmark) | ||
class WriteBenchmark: | ||
|
||
private var testData: Array[Byte] = null | ||
private val testDataFile = Path.of("src/main/resources/CodeGeneratorRequest-pack.bin") | ||
private var gReq: GPluginProtos.CodeGeneratorRequest = null | ||
private var pReq: PPluginProtos.CodeGeneratorRequest = null | ||
private var testData: Array[Byte] = null | ||
private var gMessage: GGeneratedMessage = null | ||
private var pMessage: PGeneratedMessage = null | ||
|
||
private def p2g(p: PGeneratedMessage, gp: GParser[? <: GGeneratedMessage]): GGeneratedMessage = { | ||
val out = BufferedOutput.growing() | ||
p.writeTo(out) | ||
out.close() | ||
gp.parseFrom(out.toInputStream) | ||
} | ||
|
||
@Setup(Level.Trial) | ||
def buildTestData(): Unit = | ||
def buildTrialData(): Unit = | ||
testData = Files.readAllBytes(testDataFile) | ||
assert(testData.length == 159366, s"testData.length ${testData.length}") | ||
gReq = GPluginProtos.CodeGeneratorRequest.parseFrom(testData) | ||
pReq = PPluginProtos.CodeGeneratorRequest.parseFrom(BufferedInput.ofArray(testData).order(ByteOrder.LITTLE_ENDIAN)) | ||
val m = PPluginProtos.CodeGeneratorRequest.parseFrom(BufferedInput.ofArray(testData).order(ByteOrder.LITTLE_ENDIAN)) | ||
val pfs = m.getProtoFileList.asScala.toArray | ||
for i <- 1 to 10 do | ||
pfs.foreach(m.addProtoFile) | ||
val out = BufferedOutput.growing() | ||
m.writeTo(out) | ||
out.close() | ||
testData = out.copyToByteArray() | ||
|
||
@Setup(Level.Invocation) | ||
def buildInvocationData(): Unit = | ||
gMessage = GPluginProtos.CodeGeneratorRequest.parseFrom(testData) | ||
pMessage = PPluginProtos.CodeGeneratorRequest.parseFrom(BufferedInput.ofArray(testData).order(ByteOrder.LITTLE_ENDIAN)) | ||
|
||
private def writeGoogle(out: OutputStream): Unit = | ||
val c = CodedOutputStream.newInstance(out, 4096) | ||
gMessage.writeTo(c) | ||
c.flush() | ||
out.close() | ||
|
||
private def writePerfio(out: BufferedOutput): Unit = | ||
var i = 0 | ||
pMessage.writeTo(out) | ||
out.close() | ||
|
||
@Benchmark | ||
def array_google(bh: Blackhole): Unit = | ||
val baos = new ByteArrayOutputStream() | ||
gReq.writeTo(baos) | ||
baos.close() | ||
writeGoogle(baos) | ||
bh.consume(baos.size()) | ||
|
||
@Benchmark | ||
def array_perfio(bh: Blackhole): Unit = | ||
val bo = BufferedOutput.growing(4096) | ||
pReq.writeTo(bo) | ||
bo.close() | ||
writePerfio(bo) | ||
bh.consume(bo.length()) | ||
|
||
@Benchmark | ||
def file_google(bh: Blackhole): Unit = | ||
val out = new BufferedOutputStream(new FileOutputStream("/dev/null")) | ||
gReq.writeTo(out) | ||
writeGoogle(out) | ||
out.close() | ||
|
||
@Benchmark | ||
def file_perfio(bh: Blackhole): Unit = | ||
val bo = BufferedOutput.ofFile(Path.of("/dev/null"), 8192) | ||
pReq.writeTo(bo) | ||
writePerfio(bo) | ||
bo.close() |
9 changes: 9 additions & 0 deletions
9
proto-runtime/src/main/java/perfio/proto/runtime/GeneratedMessage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package perfio.proto.runtime; | ||
|
||
import perfio.BufferedOutput; | ||
|
||
import java.io.IOException; | ||
|
||
public abstract class GeneratedMessage { | ||
public abstract void writeTo(BufferedOutput out) throws IOException; | ||
} |
Oops, something went wrong.