/* * SPDX-License-Identifier: MIT */ package ta4jexamples.rules; import java.text.NumberFormat; import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.ta4j.core.Rule; import org.ta4j.core.TradingRecord; import org.ta4j.core.rules.AbstractRule; import org.ta4j.core.rules.AndRule; import org.ta4j.core.rules.FixedRule; /** * Comparative benchmark for eager vs lazy rule naming. *
* Scenarios: *
* Note: The volatile write in setName() is an observable side effect that * prevents complete dead-code elimination, but the string construction work * (StringBuilder operations) may still be optimized if the result is never * read. */ static final class NoNameLeakAndRule extends AbstractRule { private final Rule rule1; private final Rule rule2; NoNameLeakAndRule(Rule rule1, Rule rule2) { this.rule1 = rule1; this.rule2 = rule2; // Eagerly construct and set the name, but use class names instead of // calling getName() on children to avoid triggering their lazy name resolution. // This allows us to test if JIT can eliminate the string construction // overhead when the name is never accessed. setName(buildNameWithoutChildNames()); } @Override public boolean isSatisfied(int index, TradingRecord tradingRecord) { boolean satisfied = rule1.isSatisfied(index, tradingRecord) && rule2.isSatisfied(index, tradingRecord); traceIsSatisfied(index, satisfied); return satisfied; } private String buildNameWithoutChildNames() { StringBuilder builder = new StringBuilder(getClass().getSimpleName()); builder.append('('); builder.append(rule1 == null ? "null" : rule1.getClass().getSimpleName()); builder.append(','); builder.append(rule2 == null ? "null" : rule2.getClass().getSimpleName()); builder.append(')'); return builder.toString(); } } private static final class ScenarioStats { int runs; double totalDurationNanos; double totalThroughput; double minThroughput = Double.MAX_VALUE; double maxThroughput = Double.MIN_VALUE; long totalChecksum; } }