diff --git a/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/online/command/OnlineAppReport.java b/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/online/command/OnlineAppReport.java index 678609d..c04d759 100755 --- a/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/online/command/OnlineAppReport.java +++ b/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/online/command/OnlineAppReport.java @@ -36,13 +36,15 @@ import com.tsurugidb.benchmark.costaccounting.online.periodic.BenchPeriodicUpdateStockTask; import com.tsurugidb.benchmark.costaccounting.online.task.BenchOnlineTask; import com.tsurugidb.benchmark.costaccounting.util.BenchConst; +import com.tsurugidb.benchmark.costaccounting.util.PathUtil; public class OnlineAppReport { private static final Logger LOG = LoggerFactory.getLogger(OnlineAppReport.class); private static final String HEADER1 = "# Online Application Report"; - private final StringBuilder onlineAppReport = new StringBuilder(HEADER1 + "\n"); + private final StringBuilder onlineAppReport = new StringBuilder(2048).append(HEADER1 + "\n"); + private final StringBuilder csvReport = new StringBuilder(2048).append(OnlineTimeRecord.CSV_HEADER + "\n"); public void writeOnlineAppReport(OnlineConfig config, OnlineAppReportHeader title, Path onlineReportPath, long dedicatedTime, Path compareBaseFile) { LOG.debug("Creating an online application report for {}", title); @@ -57,6 +59,14 @@ public void writeOnlineAppReport(OnlineConfig config, OnlineAppReportHeader titl } catch (IOException e) { throw new UncheckedIOException(e.getMessage(), e); } + + Path csvReportPath = PathUtil.convertExt(onlineReportPath, "csv"); + LOG.debug("Writing online application csv reports to {}", csvReportPath.toAbsolutePath()); + try { + Files.writeString(csvReportPath, csvReport.toString()); + } catch (IOException e) { + throw new UncheckedIOException(e.getMessage(), e); + } } private String createOnlineAppReport(OnlineConfig config, OnlineAppReportHeader title, long dedicatedTime, Path compareBaseFile) { @@ -150,6 +160,9 @@ private void cerateOnlineTimeReport(OnlineConfig config, StringBuilder sb, Strin var record = OnlineTimeRecord.of(config, taskName, dedicatedTime, counter, compareBaseRecord); sb.append(record); sb.append("\n"); + + record.toCsv(csvReport); + csvReport.append("\n"); } // compare base diff --git a/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/online/command/OnlineTimeRecord.java b/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/online/command/OnlineTimeRecord.java index 545d67d..9af111b 100755 --- a/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/online/command/OnlineTimeRecord.java +++ b/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/online/command/OnlineTimeRecord.java @@ -29,10 +29,17 @@ public class OnlineTimeRecord { "| title | tx option | cover rate | dedicated time[ms] | numbers of txs | latency
avg[ms] | latency
min[ms] | latency
max[ms] | committed tx through put[task/s] |", // "|-------|-----------|-----------:|-------------------:|---------------:|-------------------:|-------------------:|-------------------:|---------------------------------:|"); + public static final String CSV_HEADER = "title, tx option, cover rate(config), cover rate, dedicated time[ms], numbers of txs," // + + " latency avg[ms], latency avg rate[%]," // + + " latency min[ms], latency min rate[%]" // + + " latency max[ms], latency max rate[%]" // + + " committed tx through put[task/s], committed tx through put rate[%]"; + public static OnlineTimeRecord of(OnlineConfig config, String taskName, long dedicatedTime, BenchDbCounter counter, OnlineTimeRecord compareBaseRecord) { var record = new OnlineTimeRecord(); record.taskName = taskName; record.txOption = counter.getTxOptionDescription(taskName); + record.configCoverRate = config.getCoverRate(); record.coverRate = config.getCoverRateForReport(taskName); record.dedicatedTime = dedicatedTime; var time = counter.getTime(taskName, CounterName.TASK_SUCCESS); @@ -100,6 +107,8 @@ private static double parseDouble(String s) { return Double.parseDouble(s.replace(",", "")); } + int configCoverRate; + String taskName; String txOption; String coverRate; @@ -183,4 +192,56 @@ private String toString(ToDoubleFunction getter) { } return s; } + + public void toCsv(StringBuilder sb) { + sb.append(taskName); + sb.append(","); + sb.append(txOption.replace(',', ':')); + sb.append(","); + sb.append(configCoverRate); + sb.append(","); + sb.append(coverRate); + + // dedicated time + sb.append(","); + sb.append(dedicatedTime); + + { + // numbers of txs + sb.append(","); + sb.append(numbersOfTxs); + + // latency + sb.append(","); + appendCsv(sb, OnlineTimeRecord::latencyAvg); + sb.append(","); + appendCsv(sb, OnlineTimeRecord::latencyMin); + sb.append(","); + appendCsv(sb, OnlineTimeRecord::latencyMax); + + // committed tx through put + sb.append(","); + appendCsv(sb, OnlineTimeRecord::committedTxThroughPut); + } + } + + private void appendCsv(StringBuilder sb, ToDoubleFunction getter) { + double value = getter.applyAsDouble(this); + if (Double.isNaN(value)) { + sb.append("-,-"); + return; + } + sb.append(String.format("%.3f", value)); + + sb.append(","); + if (this.compareBaseRecord != null) { + double base = getter.applyAsDouble(compareBaseRecord); + if (Double.isNaN(base) || base == 0) { + sb.append("-"); + } + sb.append(String.format("%.2f", value / base * 100)); // [%] + } else { + sb.append("-"); + } + } } diff --git a/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/util/PathUtil.java b/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/util/PathUtil.java new file mode 100755 index 0000000..f4b8836 --- /dev/null +++ b/java/cost-accounting-benchmark/src/main/java/com/tsurugidb/benchmark/costaccounting/util/PathUtil.java @@ -0,0 +1,47 @@ +/* + * Copyright 2023-2024 Project Tsurugi. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tsurugidb.benchmark.costaccounting.util; + +import java.nio.file.Path; + +public class PathUtil { + + public static Path convertExt(Path path, String newExt) { + String fileName; + { + Path fileNamePath = path.getFileName(); + if (fileNamePath != null) { + fileName = fileNamePath.toString(); + } else { + fileName = ""; + } + } + + int n = fileName.lastIndexOf('.'); + if (n >= 0) { + fileName = fileName.substring(0, n) + "." + newExt; + } else { + fileName += "." + newExt; + } + + Path parent = path.getParent(); + if (parent != null) { + return parent.resolve(fileName); + } else { + return Path.of(fileName); + } + } +}