JfrResultJsonSerializer.java

net.minecraft.util.profiling.jfr.serialize.JfrResultJsonSerializer

信息

  • 全限定名:net.minecraft.util.profiling.jfr.serialize.JfrResultJsonSerializer
  • 类型:public class
  • 包:net.minecraft.util.profiling.jfr.serialize
  • 源码路径:src/main/java/net/minecraft/util/profiling/jfr/serialize/JfrResultJsonSerializer.java
  • 起始行号:L41
  • 职责:

    TODO

字段/常量

  • BYTES_PER_SECOND

    • 类型: String
    • 修饰符: private static final
    • 源码定位: L42
    • 说明:

      TODO

  • COUNT

    • 类型: String
    • 修饰符: private static final
    • 源码定位: L43
    • 说明:

      TODO

  • DURATION_NANOS_TOTAL

    • 类型: String
    • 修饰符: private static final
    • 源码定位: L44
    • 说明:

      TODO

  • TOTAL_BYTES

    • 类型: String
    • 修饰符: private static final
    • 源码定位: L45
    • 说明:

      TODO

  • COUNT_PER_SECOND

    • 类型: String
    • 修饰符: private static final
    • 源码定位: L46
    • 说明:

      TODO

  • gson

    • 类型: Gson
    • 修饰符: final
    • 源码定位: L47
    • 说明:

      TODO

内部类/嵌套类型

构造器

方法

下面的方法块按源码顺序生成。

private static void serializePacketId(PacketIdentification identifier, JsonObject output) @ L49

  • 方法名:serializePacketId
  • 源码定位:L49
  • 返回类型:void
  • 修饰符:private static

参数:

  • identifier: PacketIdentification
  • output: JsonObject

说明:

TODO

private static void serializeChunkId(ChunkIdentification identifier, JsonObject output) @ L54

  • 方法名:serializeChunkId
  • 源码定位:L54
  • 返回类型:void
  • 修饰符:private static

参数:

  • identifier: ChunkIdentification
  • output: JsonObject

说明:

TODO

public String format(JfrStatsResult jfrStats) @ L61

  • 方法名:format
  • 源码定位:L61
  • 返回类型:String
  • 修饰符:public

参数:

  • jfrStats: JfrStatsResult

说明:

TODO

private JsonElement heap(GcHeapStat.Summary heapSummary) @ L83

  • 方法名:heap
  • 源码定位:L83
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • heapSummary: GcHeapStat.Summary

说明:

TODO

private JsonElement structureGen(List<StructureGenStat> structureGenStats) @ L92

  • 方法名:structureGen
  • 源码定位:L92
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • structureGenStats: List

说明:

TODO

private JsonElement chunkGen(List<Pair<ChunkStatus,TimedStatSummary<ChunkGenStat>>> chunkGenSummary) @ L141

  • 方法名:chunkGen
  • 源码定位:L141
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • chunkGenSummary: List<Pair<ChunkStatus,TimedStatSummary>>

说明:

TODO

private JsonElement threadAllocations(ThreadAllocationStat.Summary threadAllocationSummary) @ L180

  • 方法名:threadAllocations
  • 源码定位:L180
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • threadAllocationSummary: ThreadAllocationStat.Summary

说明:

TODO

private JsonElement serverTicks(List<TickTimeStat> tickTimeStats) @ L189

  • 方法名:serverTicks
  • 源码定位:L189
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • tickTimeStats: List

说明:

TODO

private JsonElement fps(List<FpsStat> fpsStats) @ L205

  • 方法名:fps
  • 源码定位:L205
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • fpsStats: List

说明:

TODO

private JsonElement fileIO(JfrStatsResult jfrStats) @ L221

  • 方法名:fileIO
  • 源码定位:L221
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • jfrStats: JfrStatsResult

说明:

TODO

private JsonElement fileIoSummary(FileIOStat.Summary io) @ L230

  • 方法名:fileIoSummary
  • 源码定位:L230
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • io: FileIOStat.Summary

说明:

TODO

private JsonElement network(JfrStatsResult jfrStats) @ L247

  • 方法名:network
  • 源码定位:L247
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • jfrStats: JfrStatsResult

说明:

TODO

private <T> JsonElement ioSummary(IoSummary<T> summary, BiConsumer<T,JsonObject> elementWriter) @ L254

  • 方法名:ioSummary
  • 源码定位:L254
  • 返回类型: JsonElement
  • 修饰符:private

参数:

  • summary: IoSummary
  • elementWriter: BiConsumer<T,JsonObject>

说明:

TODO

private JsonElement cpu(List<CpuLoadStat> cpuStats) @ L275

  • 方法名:cpu
  • 源码定位:L275
  • 返回类型:JsonElement
  • 修饰符:private

参数:

  • cpuStats: List

说明:

TODO

代码

public class JfrResultJsonSerializer {
    private static final String BYTES_PER_SECOND = "bytesPerSecond";
    private static final String COUNT = "count";
    private static final String DURATION_NANOS_TOTAL = "durationNanosTotal";
    private static final String TOTAL_BYTES = "totalBytes";
    private static final String COUNT_PER_SECOND = "countPerSecond";
    final Gson gson = new GsonBuilder().setPrettyPrinting().setLongSerializationPolicy(LongSerializationPolicy.DEFAULT).create();
 
    private static void serializePacketId(PacketIdentification identifier, JsonObject output) {
        output.addProperty("protocolId", identifier.protocolId());
        output.addProperty("packetId", identifier.packetId());
    }
 
    private static void serializeChunkId(ChunkIdentification identifier, JsonObject output) {
        output.addProperty("level", identifier.level());
        output.addProperty("dimension", identifier.dimension());
        output.addProperty("x", identifier.x());
        output.addProperty("z", identifier.z());
    }
 
    public String format(JfrStatsResult jfrStats) {
        JsonObject root = new JsonObject();
        root.addProperty("startedEpoch", jfrStats.recordingStarted().toEpochMilli());
        root.addProperty("endedEpoch", jfrStats.recordingEnded().toEpochMilli());
        root.addProperty("durationMs", jfrStats.recordingDuration().toMillis());
        Duration worldCreationDuration = jfrStats.worldCreationDuration();
        if (worldCreationDuration != null) {
            root.addProperty("worldGenDurationMs", worldCreationDuration.toMillis());
        }
 
        root.add("heap", this.heap(jfrStats.heapSummary()));
        root.add("cpuPercent", this.cpu(jfrStats.cpuLoadStats()));
        root.add("network", this.network(jfrStats));
        root.add("fileIO", this.fileIO(jfrStats));
        root.add("fps", this.fps(jfrStats.fps()));
        root.add("serverTick", this.serverTicks(jfrStats.serverTickTimes()));
        root.add("threadAllocation", this.threadAllocations(jfrStats.threadAllocationSummary()));
        root.add("chunkGen", this.chunkGen(jfrStats.chunkGenSummary()));
        root.add("structureGen", this.structureGen(jfrStats.structureGenStats()));
        return this.gson.toJson((JsonElement)root);
    }
 
    private JsonElement heap(GcHeapStat.Summary heapSummary) {
        JsonObject json = new JsonObject();
        json.addProperty("allocationRateBytesPerSecond", heapSummary.allocationRateBytesPerSecond());
        json.addProperty("gcCount", heapSummary.totalGCs());
        json.addProperty("gcOverHeadPercent", heapSummary.gcOverHead());
        json.addProperty("gcTotalDurationMs", heapSummary.gcTotalDuration().toMillis());
        return json;
    }
 
    private JsonElement structureGen(List<StructureGenStat> structureGenStats) {
        JsonObject root = new JsonObject();
        Optional<TimedStatSummary<StructureGenStat>> optionalSummary = TimedStatSummary.summary(structureGenStats);
        if (optionalSummary.isEmpty()) {
            return root;
        } else {
            TimedStatSummary<StructureGenStat> summary = optionalSummary.get();
            JsonArray structureJsonArray = new JsonArray();
            root.add("structure", structureJsonArray);
            structureGenStats.stream()
                .collect(Collectors.groupingBy(StructureGenStat::structureName))
                .forEach(
                    (structureName, timedStat) -> {
                        Optional<TimedStatSummary<StructureGenStat>> optionalStatSummary = TimedStatSummary.summary((List<StructureGenStat>)timedStat);
                        if (!optionalStatSummary.isEmpty()) {
                            TimedStatSummary<StructureGenStat> statSummary = optionalStatSummary.get();
                            JsonObject structureJson = new JsonObject();
                            structureJsonArray.add(structureJson);
                            structureJson.addProperty("name", structureName);
                            structureJson.addProperty("count", statSummary.count());
                            structureJson.addProperty("durationNanosTotal", statSummary.totalDuration().toNanos());
                            structureJson.addProperty("durationNanosAvg", statSummary.totalDuration().toNanos() / statSummary.count());
                            JsonObject percentiles = Util.make(new JsonObject(), self -> structureJson.add("durationNanosPercentiles", self));
                            statSummary.percentilesNanos().forEach((percentile, v) -> percentiles.addProperty("p" + percentile, v));
                            Function<StructureGenStat, JsonElement> structureGenStatJsonGenerator = structureGen -> {
                                JsonObject result = new JsonObject();
                                result.addProperty("durationNanos", structureGen.duration().toNanos());
                                result.addProperty("chunkPosX", structureGen.chunkPos().x());
                                result.addProperty("chunkPosZ", structureGen.chunkPos().z());
                                result.addProperty("structureName", structureGen.structureName());
                                result.addProperty("level", structureGen.level());
                                result.addProperty("success", structureGen.success());
                                return result;
                            };
                            root.add("fastest", structureGenStatJsonGenerator.apply(summary.fastest()));
                            root.add("slowest", structureGenStatJsonGenerator.apply(summary.slowest()));
                            root.add(
                                "secondSlowest",
                                (JsonElement)(summary.secondSlowest() != null
                                    ? structureGenStatJsonGenerator.apply(summary.secondSlowest())
                                    : JsonNull.INSTANCE)
                            );
                        }
                    }
                );
            return root;
        }
    }
 
    private JsonElement chunkGen(List<Pair<ChunkStatus, TimedStatSummary<ChunkGenStat>>> chunkGenSummary) {
        JsonObject json = new JsonObject();
        if (chunkGenSummary.isEmpty()) {
            return json;
        } else {
            json.addProperty("durationNanosTotal", chunkGenSummary.stream().mapToDouble(it -> it.getSecond().totalDuration().toNanos()).sum());
            JsonArray chunkJsonArray = Util.make(new JsonArray(), self -> json.add("status", self));
 
            for (Pair<ChunkStatus, TimedStatSummary<ChunkGenStat>> summaryByStatus : chunkGenSummary) {
                TimedStatSummary<ChunkGenStat> chunkStat = summaryByStatus.getSecond();
                JsonObject chunkStatusJson = Util.make(new JsonObject(), chunkJsonArray::add);
                chunkStatusJson.addProperty("state", summaryByStatus.getFirst().toString());
                chunkStatusJson.addProperty("count", chunkStat.count());
                chunkStatusJson.addProperty("durationNanosTotal", chunkStat.totalDuration().toNanos());
                chunkStatusJson.addProperty("durationNanosAvg", chunkStat.totalDuration().toNanos() / chunkStat.count());
                JsonObject percentiles = Util.make(new JsonObject(), self -> chunkStatusJson.add("durationNanosPercentiles", self));
                chunkStat.percentilesNanos().forEach((percentile, value) -> percentiles.addProperty("p" + percentile, value));
                Function<ChunkGenStat, JsonElement> chunkGenStatJsonGenerator = chunk -> {
                    JsonObject chunkGenStatJson = new JsonObject();
                    chunkGenStatJson.addProperty("durationNanos", chunk.duration().toNanos());
                    chunkGenStatJson.addProperty("level", chunk.level());
                    chunkGenStatJson.addProperty("chunkPosX", chunk.chunkPos().x());
                    chunkGenStatJson.addProperty("chunkPosZ", chunk.chunkPos().z());
                    chunkGenStatJson.addProperty("worldPosX", chunk.worldPos().x());
                    chunkGenStatJson.addProperty("worldPosZ", chunk.worldPos().z());
                    return chunkGenStatJson;
                };
                chunkStatusJson.add("fastest", chunkGenStatJsonGenerator.apply(chunkStat.fastest()));
                chunkStatusJson.add("slowest", chunkGenStatJsonGenerator.apply(chunkStat.slowest()));
                chunkStatusJson.add(
                    "secondSlowest",
                    (JsonElement)(chunkStat.secondSlowest() != null ? chunkGenStatJsonGenerator.apply(chunkStat.secondSlowest()) : JsonNull.INSTANCE)
                );
            }
 
            return json;
        }
    }
 
    private JsonElement threadAllocations(ThreadAllocationStat.Summary threadAllocationSummary) {
        JsonArray threads = new JsonArray();
        threadAllocationSummary.allocationsPerSecondByThread().forEach((threadName, bytesPerSecond) -> threads.add(Util.make(new JsonObject(), json -> {
            json.addProperty("thread", threadName);
            json.addProperty("bytesPerSecond", bytesPerSecond);
        })));
        return threads;
    }
 
    private JsonElement serverTicks(List<TickTimeStat> tickTimeStats) {
        if (tickTimeStats.isEmpty()) {
            return JsonNull.INSTANCE;
        } else {
            JsonObject json = new JsonObject();
            double[] tickTimesMs = tickTimeStats.stream().mapToDouble(tickTimeStat -> tickTimeStat.currentAverage().toNanos() / 1000000.0).toArray();
            DoubleSummaryStatistics summary = DoubleStream.of(tickTimesMs).summaryStatistics();
            json.addProperty("minMs", summary.getMin());
            json.addProperty("averageMs", summary.getAverage());
            json.addProperty("maxMs", summary.getMax());
            Map<Integer, Double> percentiles = Percentiles.evaluate(tickTimesMs);
            percentiles.forEach((percentile, value) -> json.addProperty("p" + percentile, value));
            return json;
        }
    }
 
    private JsonElement fps(List<FpsStat> fpsStats) {
        if (fpsStats.isEmpty()) {
            return JsonNull.INSTANCE;
        } else {
            JsonObject json = new JsonObject();
            int[] fps = fpsStats.stream().mapToInt(FpsStat::fps).toArray();
            IntSummaryStatistics summary = IntStream.of(fps).summaryStatistics();
            json.addProperty("minFPS", summary.getMin());
            json.addProperty("averageFPS", summary.getAverage());
            json.addProperty("maxFPS", summary.getMax());
            Map<Integer, Double> percentiles = Percentiles.evaluate(fps);
            percentiles.forEach((percentile, value) -> json.addProperty("p" + percentile, value));
            return json;
        }
    }
 
    private JsonElement fileIO(JfrStatsResult jfrStats) {
        JsonObject json = new JsonObject();
        json.add("write", this.fileIoSummary(jfrStats.fileWrites()));
        json.add("read", this.fileIoSummary(jfrStats.fileReads()));
        json.add("chunksRead", this.ioSummary(jfrStats.readChunks(), JfrResultJsonSerializer::serializeChunkId));
        json.add("chunksWritten", this.ioSummary(jfrStats.writtenChunks(), JfrResultJsonSerializer::serializeChunkId));
        return json;
    }
 
    private JsonElement fileIoSummary(FileIOStat.Summary io) {
        JsonObject json = new JsonObject();
        json.addProperty("totalBytes", io.totalBytes());
        json.addProperty("count", io.counts());
        json.addProperty("bytesPerSecond", io.bytesPerSecond());
        json.addProperty("countPerSecond", io.countsPerSecond());
        JsonArray topContributors = new JsonArray();
        json.add("topContributors", topContributors);
        io.topTenContributorsByTotalBytes().forEach(contributor -> {
            JsonObject contributorJson = new JsonObject();
            topContributors.add(contributorJson);
            contributorJson.addProperty("path", contributor.getFirst());
            contributorJson.addProperty("totalBytes", contributor.getSecond());
        });
        return json;
    }
 
    private JsonElement network(JfrStatsResult jfrStats) {
        JsonObject json = new JsonObject();
        json.add("sent", this.ioSummary(jfrStats.sentPacketsSummary(), JfrResultJsonSerializer::serializePacketId));
        json.add("received", this.ioSummary(jfrStats.receivedPacketsSummary(), JfrResultJsonSerializer::serializePacketId));
        return json;
    }
 
    private <T> JsonElement ioSummary(IoSummary<T> summary, BiConsumer<T, JsonObject> elementWriter) {
        JsonObject json = new JsonObject();
        json.addProperty("totalBytes", summary.getTotalSize());
        json.addProperty("count", summary.getTotalCount());
        json.addProperty("bytesPerSecond", summary.getSizePerSecond());
        json.addProperty("countPerSecond", summary.getCountsPerSecond());
        JsonArray topContributors = new JsonArray();
        json.add("topContributors", topContributors);
        summary.largestSizeContributors().forEach(contributor -> {
            JsonObject contributorJson = new JsonObject();
            topContributors.add(contributorJson);
            T identifier = contributor.getFirst();
            IoSummary.CountAndSize countAndSize = contributor.getSecond();
            elementWriter.accept(identifier, contributorJson);
            contributorJson.addProperty("totalBytes", countAndSize.totalSize());
            contributorJson.addProperty("count", countAndSize.totalCount());
            contributorJson.addProperty("averageSize", countAndSize.averageSize());
        });
        return json;
    }
 
    private JsonElement cpu(List<CpuLoadStat> cpuStats) {
        JsonObject json = new JsonObject();
        BiFunction<List<CpuLoadStat>, ToDoubleFunction<CpuLoadStat>, JsonObject> transformer = (cpuLoadStats, extractor) -> {
            JsonObject jsonGroup = new JsonObject();
            DoubleSummaryStatistics stats = cpuLoadStats.stream().mapToDouble(extractor).summaryStatistics();
            jsonGroup.addProperty("min", stats.getMin());
            jsonGroup.addProperty("average", stats.getAverage());
            jsonGroup.addProperty("max", stats.getMax());
            return jsonGroup;
        };
        json.add("jvm", transformer.apply(cpuStats, CpuLoadStat::jvm));
        json.add("userJvm", transformer.apply(cpuStats, CpuLoadStat::userJvm));
        json.add("system", transformer.apply(cpuStats, CpuLoadStat::system));
        return json;
    }
}

引用的其他类