diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/TraceFormat.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/TraceFormat.java index 24e2ca1184..77504269da 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/TraceFormat.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/TraceFormat.java @@ -27,6 +27,7 @@ import com.github.benmanes.caffeine.cache.simulator.parser.address.AddressTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.address.penalties.AddressPenaltiesTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.arc.ArcTraceReader; +import com.github.benmanes.caffeine.cache.simulator.parser.baleen.BaleenTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.cache2k.Cache2kTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.cachelib.CachelibTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.camelab.CamelabTraceReader; @@ -41,6 +42,7 @@ import com.github.benmanes.caffeine.cache.simulator.parser.lrb.LrbTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.scarab.ScarabTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.snia.cambridge.CambridgeTraceReader; +import com.github.benmanes.caffeine.cache.simulator.parser.snia.enterprise.EnterpriseTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.snia.keyvalue.ObjectStoreTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.snia.parallel.K5cloudTraceReader; import com.github.benmanes.caffeine.cache.simulator.parser.snia.parallel.TencentBlockTraceReader; @@ -69,6 +71,7 @@ public enum TraceFormat { ADDRESS_PENALTIES(AddressPenaltiesTraceReader::new), ADAPT_SIZE(AdaptSizeTraceReader::new), ARC(ArcTraceReader::new), + BALEEN(BaleenTraceReader::new), CACHE2K(Cache2kTraceReader::new), CACHELIB(CachelibTraceReader::new), CAMELAB(CamelabTraceReader::new), @@ -83,6 +86,7 @@ public enum TraceFormat { OUTBRAIN(OutbrainTraceReader::new), SCARAB(ScarabTraceReader::new), SNIA_CAMBRIDGE(CambridgeTraceReader::new), + SNIA_ENTERPRISE(EnterpriseTraceReader::new), SNIA_K5CLOUD(K5cloudTraceReader::new), SNIA_OBJECT_STORE(ObjectStoreTraceReader::new), SNIA_SYSTOR(SystorTraceReader::new), diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/baleen/BaleenTraceReader.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/baleen/BaleenTraceReader.java new file mode 100644 index 0000000000..256b8a3b8a --- /dev/null +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/baleen/BaleenTraceReader.java @@ -0,0 +1,60 @@ +/* + * Copyright 2024 Ben Manes. All Rights Reserved. + * + * 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.github.benmanes.caffeine.cache.simulator.parser.baleen; + +import java.math.RoundingMode; +import java.util.stream.LongStream; + +import com.github.benmanes.caffeine.cache.simulator.parser.TextTraceReader; +import com.github.benmanes.caffeine.cache.simulator.parser.TraceReader.KeyOnlyTraceReader; +import com.google.common.math.IntMath; + +/** + * A reader for the trace files provided by the authors of the Baleen algorithm. See + * traces. + * + * @author ben.manes@gmail.com (Ben Manes) + */ +public final class BaleenTraceReader extends TextTraceReader implements KeyOnlyTraceReader { + private static final int SEGMENT_SIZE = 128 * 1024; + + public BaleenTraceReader(String filePath) { + super(filePath); + } + + @Override + public LongStream keys() { + return lines() + .dropWhile(line -> line.startsWith("#")) + .map(line -> line.split(" ", 6)) + .filter(line -> isRead(line[4].charAt(0))) + .flatMapToLong(line -> { + long block = Long.parseLong(line[0]); + long byteOffset = Long.parseLong(line[1]); + int size = Integer.parseInt(line[2]); + + int startSegment = Math.toIntExact(byteOffset / SEGMENT_SIZE); + int sequence = IntMath.divide(size, SEGMENT_SIZE, RoundingMode.UP); + + long startKey = ((long) Long.hashCode(block) << 32) | startSegment; + return LongStream.range(startKey, startKey + sequence); + }); + } + + private static boolean isRead(char operation) { + return (operation == '1') || (operation == '2') || (operation == '5'); + } +} diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/baleen/package-info.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/baleen/package-info.java new file mode 100644 index 0000000000..4aba96f214 --- /dev/null +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/baleen/package-info.java @@ -0,0 +1,4 @@ +@CheckReturnValue +package com.github.benmanes.caffeine.cache.simulator.parser.baleen; + +import com.google.errorprone.annotations.CheckReturnValue; diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/snia/enterprise/EnterpriseTraceReader.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/snia/enterprise/EnterpriseTraceReader.java new file mode 100644 index 0000000000..849536cc18 --- /dev/null +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/snia/enterprise/EnterpriseTraceReader.java @@ -0,0 +1,69 @@ +/* + * Copyright 2024 Ben Manes. All Rights Reserved. + * + * 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.github.benmanes.caffeine.cache.simulator.parser.snia.enterprise; + +import java.math.RoundingMode; +import java.util.function.Predicate; +import java.util.stream.LongStream; + +import com.github.benmanes.caffeine.cache.simulator.parser.TextTraceReader; +import com.github.benmanes.caffeine.cache.simulator.parser.TraceReader.KeyOnlyTraceReader; +import com.google.common.math.IntMath; + +/** + * A reader for the SNIA Microsoft Enterprise trace files provided by + * SNIA in the + * Event Tracing for Windows format. + * + * @author ben.manes@gmail.com (Ben Manes) + */ +public final class EnterpriseTraceReader + extends TextTraceReader implements KeyOnlyTraceReader { + private static final int BLOCK_SIZE = 4096; + + public EnterpriseTraceReader(String filePath) { + super(filePath); + } + + @Override + public LongStream keys() { + return lines() + .dropWhile(new SkipHeader()) + .filter(line -> line.stripLeading().startsWith("DiskRead,")) + .map(line -> line.split(",", 8)) + .flatMapToLong(line -> { + long byteOffset = Long.parseLong(line[5].strip().substring(2), 16); + int size = Integer.parseInt(line[6].strip().substring(2), 16); + + long startBlock = byteOffset / BLOCK_SIZE; + int sequence = IntMath.divide(size, BLOCK_SIZE, RoundingMode.UP); + return LongStream.range(startBlock, startBlock + sequence); + }); + } + + private static final class SkipHeader implements Predicate { + private boolean isHeader; + + @Override public boolean test(String line) { + if (line.equals("BeginHeader")) { + isHeader = true; + } else if (line.equals("EndHeader")) { + isHeader = false; + } + return isHeader; + } + } +} diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/snia/enterprise/package-info.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/snia/enterprise/package-info.java new file mode 100644 index 0000000000..aa18824326 --- /dev/null +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/parser/snia/enterprise/package-info.java @@ -0,0 +1,4 @@ +@CheckReturnValue +package com.github.benmanes.caffeine.cache.simulator.parser.snia.enterprise; + +import com.google.errorprone.annotations.CheckReturnValue; diff --git a/simulator/src/main/resources/reference.conf b/simulator/src/main/resources/reference.conf index 04eae47eb6..9d6de88fbc 100644 --- a/simulator/src/main/resources/reference.conf +++ b/simulator/src/main/resources/reference.conf @@ -500,6 +500,7 @@ caffeine.simulator { # adapt-size: format from the authors of the AdaptSize algorithm # address: format of UCSD program address traces # address-penalties: format of UCSD program address traces with hit & miss penalties + # baleen: format from the authors of the Baleen algorithm # cache2k: format from the author of the Cache2k library # cachelib: format from the author of the Cachelib library # camelab: format of the Camelab storage traces @@ -514,6 +515,7 @@ caffeine.simulator { # outbrain: format of Outbrain's trace provided on Kaggle # scarab: format of Scarab Research traces # snia-cambridge: format of the SNIA MSR Cambridge traces + # snia-enterprise: format of the SNIA MS Enterprise traces # snia-k5cloud: format of the SNIA K5cloud traces # snia-object-store: format of the SNIA IBM ObjectStore traces # snia-systor: format of the SNIA SYSTOR '17 traces