@@ -21,11 +21,9 @@ import dotty.tools.dotc.typer.TyperPhase
2121 *
2222 * Run with: scala3-bench-micro / Jmh / run AnnotationsMappingBenchmark
2323 */
24- @ Fork (value = 5 )
25- // Set to 0 to record all iterations. We remove the first iterations manually
26- // when processing the results.
27- @ Warmup (iterations = 0 , time = 1 , timeUnit = SECONDS )
28- @ Measurement (iterations = 10 , time = 1 , timeUnit = SECONDS )
24+ @ Fork (value = 4 )
25+ @ Warmup (iterations = 4 , time = 1 , timeUnit = SECONDS )
26+ @ Measurement (iterations = 4 , time = 1 , timeUnit = SECONDS )
2927@ BenchmarkMode (Array (JMHMode .Throughput ))
3028@ State (Scope .Thread )
3129class AnnotationsMappingBenchmark :
@@ -38,17 +36,11 @@ class AnnotationsMappingBenchmark:
3836 @ Param (Array (" v1" , " v2" , " v3" , " v4" ))
3937 var valName : String = null
4038
41- @ Param (Array (" current" , " oldCheck" , " newCheckEquals" , " newCheckEq" , " noCheck" , " noCheckCopySymbols" ))
42- var typeMapName : String = null
43-
4439 @ Param (Array (" id" , " mapInts" ))
4540 var typeFunctionName : String = null
4641
4742 @ Setup (Level .Iteration )
4843 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- */
5244 val testPhase =
5345 new Phase :
5446 final override def phaseName = " testPhase"
@@ -58,20 +50,15 @@ class AnnotationsMappingBenchmark:
5850 specialIntTp = pkg.requiredClass(" Test" ).requiredType(" SpecialInt" ).typeRef
5951 context = ctx
6052
61- /** A custom compiler that only runs the `Parser`, `TyperPhase` and
62- * `testPhase`.
63- */
6453 val compiler =
6554 new Compiler :
6655 private final val baseCompiler = new Compiler ()
6756 final override def phases = List (List (Parser ()), List (TyperPhase ()), List (testPhase))
6857
69- /** A custom driver that uses `compiler`. */
7058 val driver =
7159 new Driver :
7260 final override def newCompiler (using Context ): Compiler = compiler
7361
74- // Runs the driver with the test file.
7562 driver.process(Array (" -classpath" , System .getProperty(" BENCH_CLASS_PATH" ), " tests/someAnnotatedTypes.scala" ))
7663
7764 typeFunction =
@@ -80,142 +67,8 @@ class AnnotationsMappingBenchmark:
8067 case " mapInts" => tp => (if tp frozen_=:= defn.IntType then specialIntTp else tp)
8168 case _ => throw new IllegalArgumentException (s " Unknown type function: $typeFunctionName" )
8269
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 ) =
70+ typeMap =
8871 new TypeMap (using context):
8972 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" )
21773
218- @ Benchmark
219- def applyTypeMap () =
220- val res = typeMap.apply(tp)
221- // println(res.show(using context))
74+ @ Benchmark def applyTypeMap () = typeMap.apply(tp)
0 commit comments