Skip to content

Commit 4a35fa8

Browse files
committed
Simplify AnnotationsMappingBenchmark
1 parent 302cb2a commit 4a35fa8

File tree

3 files changed

+40
-168
lines changed

3 files changed

+40
-168
lines changed

bench-micro/scripts/compare.sh

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env bash
2+
3+
name=$1
4+
commit_1=$2
5+
commit_2=$3
6+
runs=2
7+
8+
if [ -z "$name" ] || [ -z "$commit_1" ] || [ -z "$commit_2" ]; then
9+
echo "Usage: $0 <benchmark-name> <commit-1> <commit-2>"
10+
exit 1
11+
fi
12+
13+
run_benchmark() {
14+
jvm=$1
15+
jvm_coursier_id=$2
16+
run=$3
17+
hash=$4
18+
json_file=results/$name-$jvm-$run.json
19+
txt_file=results/$name-$jvm-$run.txt
20+
echo "Running $name benchmark with JVM $jvm at commit $hash, run $run out of $runs"
21+
git checkout $hash
22+
git clean -fdx
23+
eval "$(coursier java --jvm "$jvm_coursier_id" --env)"
24+
rm -rf "$json_file" "$stdout_file" .bloop .sbt .bsp .metals target
25+
sbt "clean; scala3-bench-micro / Jmh / run -rf JSON -rff $json_file -o $txt_file $name"
26+
}
27+
28+
read -p "WARNING: this script will brutally reset your Dotty repo (git clean -fdx). Type 'y' to continue." -n 1 -r
29+
echo # new line
30+
if [[ $REPLY =~ ^[Yy]$ ]]
31+
then
32+
for run in $(seq 1 $runs); do
33+
for hash in $commit_1 $commit_2; do
34+
run_benchmark openjdk "adoptium:1.17.0.11" $run $hash
35+
run_benchmark graal "graalvm-java17:22.3.3" $run $hash
36+
done
37+
done
38+
fi

bench-micro/scripts/run.sh

-21
This file was deleted.

bench-micro/src/main/scala/dotty/tools/benchmarks/AnnotationsMappingBenchmark.scala

+2-147
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,11 @@ class AnnotationsMappingBenchmark:
3838
@Param(Array("v1", "v2", "v3", "v4"))
3939
var valName: String = null
4040

41-
@Param(Array("current", "oldCheck", "newCheckEquals", "newCheckEq", "noCheck", "noCheckCopySymbols"))
42-
var typeMapName: String = null
43-
4441
@Param(Array("id", "mapInts"))
4542
var typeFunctionName: String = null
4643

4744
@Setup(Level.Iteration)
4845
def setup(): Unit =
49-
/** A custom phase that is used to retrieve the `Type`s and `Context` to be
50-
* used in the benchmark.
51-
*/
5246
val testPhase =
5347
new Phase:
5448
final override def phaseName = "testPhase"
@@ -58,20 +52,15 @@ class AnnotationsMappingBenchmark:
5852
specialIntTp = pkg.requiredClass("Test").requiredType("SpecialInt").typeRef
5953
context = ctx
6054

61-
/** A custom compiler that only runs the `Parser`, `TyperPhase` and
62-
* `testPhase`.
63-
*/
6455
val compiler =
6556
new Compiler:
6657
private final val baseCompiler = new Compiler()
6758
final override def phases = List(List(Parser()), List(TyperPhase()), List(testPhase))
6859

69-
/** A custom driver that uses `compiler`. */
7060
val driver =
7161
new Driver:
7262
final override def newCompiler(using Context): Compiler = compiler
7363

74-
// Runs the driver with the test file.
7564
driver.process(Array("-classpath", System.getProperty("BENCH_CLASS_PATH"), "tests/someAnnotatedTypes.scala"))
7665

7766
typeFunction =
@@ -80,142 +69,8 @@ class AnnotationsMappingBenchmark:
8069
case "mapInts" => tp => (if tp frozen_=:= defn.IntType then specialIntTp else tp)
8170
case _ => throw new IllegalArgumentException(s"Unknown type function: $typeFunctionName")
8271

83-
/** Creates a new `TypeMap` that uses `mapConcreteAnnotationWith` to map
84-
* concrete annotations. It is used to compare several ways to map these
85-
* annotations.
86-
*/
87-
def makeTypeMap(mapConcreteAnnotationWith: (ConcreteAnnotation, TypeMap) => Context ?=> Annotation) =
72+
typeMap =
8873
new TypeMap(using context):
8974
final override def apply(tp: Type): Type = typeFunction(mapOver(tp))
90-
final override def mapOver(tp: Type) =
91-
tp match
92-
case tp @ AnnotatedType(underlying, annot) =>
93-
val underlying1 = this(underlying)
94-
val annot1 =
95-
annot match
96-
case annot: ConcreteAnnotation => mapConcreteAnnotationWith(annot, this)
97-
case _ => annot.mapWith(this)
98-
if annot1 eq EmptyAnnotation then underlying1
99-
else derivedAnnotatedType(tp, underlying1, annot1)
100-
case _ => super.mapOver(tp)
101-
102-
/** Retrieves all argument from a tree. This old implementation does not
103-
* include type arguments.
104-
*/
105-
def oldAllArguments(tree: Tree)(using Context): List[Tree] =
106-
tpd.unsplice(tree) match
107-
case Apply(fn, args) => oldAllArguments(fn) ::: args
108-
case TypeApply(fn, _) => oldAllArguments(fn)
109-
case Block(_, expr) => oldAllArguments(expr)
110-
case _ => Nil
111-
112-
/** This is the old (<= d1489734b7) implementation of `Annotation.mapWith`.
113-
* It 1. does not include type arguments and 2. uses `frozen_=:=` to
114-
* compare types and 3. does not copy all symbols.
115-
*/
116-
def oldMapWith(annot: ConcreteAnnotation, tm: TypeMap)(using Context): Annotation =
117-
val tree = annot.tree
118-
val args = oldAllArguments(tree)
119-
if args.isEmpty then annot
120-
else
121-
val findDiff = new TreeAccumulator[Type]:
122-
def apply(x: Type, tree: Tree)(using Context): Type =
123-
if tm.isRange(x) then x
124-
else
125-
val tp1 = tm(tree.tpe)
126-
foldOver(if tp1 frozen_=:= tree.tpe then x else tp1, tree)
127-
val diff = findDiff(NoType, args)
128-
if tm.isRange(diff) then EmptyAnnotation
129-
else if diff.exists then annot.derivedAnnotation(tm.mapOver(tree))
130-
else annot
131-
132-
/** Retrieves all argument from a tree, including type arguments. */
133-
def newAllArguments(tree: Tree)(using Context): List[Tree] =
134-
tpd.unsplice(tree) match
135-
case Apply(fn, args) => newAllArguments(fn) ::: args
136-
case TypeApply(fn, args) => newAllArguments(fn) ::: args
137-
case Block(_, expr) => newAllArguments(expr)
138-
case _ => Nil
139-
140-
/** This is the new implementation of `Annotation.mapWith`. It 1. includes
141-
* type arguments and 2. uses `==` to compare types and 3. copies all
142-
* symbols by using a custom `TreeTypeMap` that overrides `withMappedSyms`.
143-
*/
144-
def newMapWithEquals(annot: ConcreteAnnotation, tm: TypeMap)(using Context): Annotation =
145-
val tree = annot.tree
146-
val args = newAllArguments(tree)
147-
if args.isEmpty then annot
148-
else
149-
val findDiff = new TreeAccumulator[Type]:
150-
def apply(x: Type, tree: Tree)(using Context): Type =
151-
if tm.isRange(x) then x
152-
else
153-
val tp1 = tm(tree.tpe)
154-
foldOver(if tp1 == tree.tpe then x else tp1, tree)
155-
val diff = findDiff(NoType, args)
156-
if tm.isRange(diff) then EmptyAnnotation
157-
else if diff.exists then
158-
val ttm =
159-
new TreeTypeMap(tm):
160-
final override def withMappedSyms(syms: List[Symbol]): TreeTypeMap =
161-
withMappedSyms(syms, mapSymbols(syms, this, mapAlways = true))
162-
annot.derivedAnnotation(ttm.transform(tree))
163-
else annot
164-
165-
/** Exactly the same as `newMapWithEquals`, but uses `eq` instead of `==` to
166-
* compare types.
167-
*/
168-
def newMapWithEq(annot: ConcreteAnnotation, tm: TypeMap)(using Context): Annotation =
169-
val tree = annot.tree
170-
val args = newAllArguments(tree)
171-
if args.isEmpty then annot
172-
else
173-
val findDiff = new TreeAccumulator[Type]:
174-
def apply(x: Type, tree: Tree)(using Context): Type =
175-
if tm.isRange(x) then x
176-
else
177-
val tp1 = tm(tree.tpe)
178-
foldOver(if tp1 eq tree.tpe then x else tp1, tree)
179-
val diff = findDiff(NoType, args)
180-
if tm.isRange(diff) then EmptyAnnotation
181-
else if diff.exists then
182-
val ttm =
183-
new TreeTypeMap(tm):
184-
final override def withMappedSyms(syms: List[Symbol]): TreeTypeMap =
185-
withMappedSyms(syms, mapSymbols(syms, this, mapAlways = true))
186-
annot.derivedAnnotation(ttm.transform(tree))
187-
else annot
188-
189-
def noCheckMapWith(annot: ConcreteAnnotation, tm: TypeMap)(using Context): Annotation =
190-
annot.derivedAnnotation(tm.mapOver(annot.tree))
191-
192-
def noCheckCopySymbolsMapWith(annot: ConcreteAnnotation, tm: TypeMap)(using Context): Annotation =
193-
val ttm =
194-
new TreeTypeMap(tm):
195-
final override def withMappedSyms(syms: List[Symbol]): TreeTypeMap =
196-
withMappedSyms(syms, mapSymbols(syms, this, mapAlways = true))
197-
annot.derivedAnnotation(ttm.transform(annot.tree))
198-
199-
typeMap =
200-
typeMapName match
201-
case "current" =>
202-
new TypeMap(using context):
203-
final override def apply(tp: Type): Type = typeFunction(mapOver(tp))
204-
case "oldCheck" =>
205-
makeTypeMap(oldMapWith)
206-
case "newCheckEquals" =>
207-
// This should be the same as `current`, modulo a few indirections.
208-
makeTypeMap(newMapWithEq)
209-
case "newCheckEq" =>
210-
makeTypeMap(newMapWithEq)
211-
case "noCheck" =>
212-
makeTypeMap(noCheckMapWith)
213-
case "noCheckCopySymbols" =>
214-
makeTypeMap(noCheckCopySymbolsMapWith)
215-
case _ =>
216-
throw new IllegalArgumentException(s"Unknown type map: $typeMapName")
21775

218-
@Benchmark
219-
def applyTypeMap() =
220-
val res = typeMap.apply(tp)
221-
// println(res.show(using context))
76+
@Benchmark def applyTypeMap() = typeMap.apply(tp)

0 commit comments

Comments
 (0)