1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Jean Privat <jean@pryen.org>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
21 private import rapid_type_analysis
22 private import metrics_base
23 import mmodules_metrics
24 import mclasses_metrics
27 redef class ToolContext
28 var rta_metrics_phase
: Phase = new RTAMetricsPhase(self, null)
31 private class RTAMetricsPhase
33 redef fun process_mainmodule
(mainmodule
, given_mmodules
)
35 if not toolcontext
.opt_rta
.value
and not toolcontext
.opt_all
.value
then return
36 var csv
= toolcontext
.opt_csv
.value
37 var out
= "{toolcontext.opt_dir.value or else "metrics"}/rta"
40 print toolcontext
.format_h1
("\n# RTA metrics")
42 print toolcontext
.format_h2
("\n ## Live instances by mainmodules")
43 var mmetrics
= new MetricSet
44 mmetrics
.register
(new MNLC(toolcontext
.modelbuilder
))
45 mmetrics
.register
(new MNLT(toolcontext
.modelbuilder
))
46 mmetrics
.register
(new MNCT(toolcontext
.modelbuilder
))
47 mmetrics
.register
(new MNLI(toolcontext
.modelbuilder
))
48 mmetrics
.register
(new MNLM(toolcontext
.modelbuilder
))
49 mmetrics
.register
(new MNLMD(toolcontext
.modelbuilder
))
50 mmetrics
.register
(new MNLDD(toolcontext
.modelbuilder
))
51 mmetrics
.collect
(new HashSet[MModule].from
([mainmodule
]))
52 mmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
53 if csv
then mmetrics
.to_csv
.save
("{out}/{mainmodule}.csv")
55 var mtypes
= new HashSet[MType]
56 var analysis
= new RapidTypeAnalysis(toolcontext
.modelbuilder
, mainmodule
)
58 mtypes
.add_all
(analysis
.live_types
)
59 mtypes
.add_all
(analysis
.live_cast_types
)
61 print toolcontext
.format_h2
("\n ## Total live instances by mclasses")
62 var cmetrics
= new MetricSet
63 cmetrics
.register
(analysis
.cnli
)
64 cmetrics
.register
(analysis
.cnlc
)
65 cmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
66 if csv
then cmetrics
.to_csv
.save
("{out}/mclasses.csv")
68 print toolcontext
.format_h2
("\n ## Total live instances by mtypes")
69 var tmetrics
= new MetricSet
70 tmetrics
.register
(analysis
.tnli
)
71 tmetrics
.register
(analysis
.tnlc
)
72 tmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
73 if csv
then tmetrics
.to_csv
.save
("{out}/mtypes.csv")
75 print toolcontext
.format_h2
("\n ## MType complexity")
76 var gmetrics
= new MetricSet
77 gmetrics
.register
(new TAGS)
78 gmetrics
.register
(new TDGS)
79 gmetrics
.collect
(mtypes
)
80 gmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
81 if csv
then gmetrics
.to_csv
.save
("{out}/complexity.csv")
83 callsite_info
(analysis
)
85 # dump type and method infos
87 analysis
.live_types_to_csv
.save
("{out}/rta_types.csv")
88 analysis
.live_methods_to_tree
.write_to_file
("{out}/rta_methods.dat")
92 fun callsite_info
(rta
: RapidTypeAnalysis)
94 print toolcontext
.format_h2
("\n ## Callsites")
95 print
"* {rta.live_callsites.length} live callsites"
97 var csep
= new Counter[MPropDef]
98 var cglo
= new Counter[MPropDef]
99 var morphisme
= new Counter[Int]
100 for cs
in rta
.live_callsites
do
101 csep
.inc
(cs
.mpropdef
)
102 var targets
= rta
.live_targets
(cs
)
106 morphisme
.inc
(targets
.length
)
109 print toolcontext
.format_h3
("MMethodDef locally designated (by number of CallSites)")
111 csep
.print_elements
(5)
113 print toolcontext
.format_h3
("MMethodDef possibly invoked at runtime (by number of CallSites)")
115 cglo
.print_elements
(5)
121 # MModule Metric: Number of Live Types
125 redef fun name
do return "mnli"
126 redef fun desc
do return "number of live instances in a mmodule"
128 var modelbuilder
: ModelBuilder
129 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
131 redef fun collect
(mainmodules
) do
132 for mainmodule
in mainmodules
do
133 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
134 analysis
.run_analysis
135 values
[mainmodule
] = analysis
.tnli
.sum
140 # MModule Metric: Number of Live Types
144 redef fun name
do return "mnlt"
145 redef fun desc
do return "number of live mtypes in a mmodule"
147 var modelbuilder
: ModelBuilder
148 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
150 redef fun collect
(mainmodules
) do
151 for mainmodule
in mainmodules
do
152 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
153 analysis
.run_analysis
154 values
[mainmodule
] = analysis
.live_types
.length
159 # MModule Metric: Number of Live Cast Types
163 redef fun name
do return "mnct"
164 redef fun desc
do return "number of live cast mtypes in a mmodule"
166 var modelbuilder
: ModelBuilder
167 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
169 redef fun collect
(mainmodules
) do
170 for mainmodule
in mainmodules
do
171 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
172 analysis
.run_analysis
173 values
[mainmodule
] = analysis
.live_cast_types
.length
178 # MModule Metric: Number of Live Classes
182 redef fun name
do return "mnlc"
183 redef fun desc
do return "number of live mclasses in a mmodule"
185 var modelbuilder
: ModelBuilder
186 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
188 redef fun collect
(mainmodules
) do
189 for mainmodule
in mainmodules
do
190 var live
= new HashSet[MClass]
191 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
192 analysis
.run_analysis
193 for mtype
in analysis
.live_types
do
194 live
.add
(mtype
.mclass
)
196 values
[mainmodule
] = live
.length
201 # MModule Metric: Number of Live Methods
205 redef fun name
do return "mnlm"
206 redef fun desc
do return "number of live methods in a mmodule"
208 var modelbuilder
: ModelBuilder
209 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
211 redef fun collect
(mainmodules
) do
212 for mainmodule
in mainmodules
do
213 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
214 analysis
.run_analysis
215 values
[mainmodule
] = analysis
.live_methods
.length
220 # MModule Metric: Number of Live MethodDefs
224 redef fun name
do return "mnlmd"
225 redef fun desc
do return "number of live method definitions in a mmodule"
227 var modelbuilder
: ModelBuilder
228 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
230 redef fun collect
(mainmodules
) do
231 for mainmodule
in mainmodules
do
232 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
233 analysis
.run_analysis
234 values
[mainmodule
] = analysis
.live_methoddefs
.length
239 # MModule Metric: Number of Dead MethodDefs
243 redef fun name
do return "mnldd"
244 redef fun desc
do return "number of dead method definitions in a mmodule"
246 var modelbuilder
: ModelBuilder
247 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
249 redef fun collect
(mainmodules
) do
250 for mainmodule
in mainmodules
do
252 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
253 analysis
.run_analysis
254 for mmethod
in analysis
.live_methods
do
255 for mdef
in mmethod
.mpropdefs
do
256 if analysis
.live_methoddefs
.has
(mdef
) or mdef
.is_abstract
then continue
260 values
[mainmodule
] = dead
267 # Class Metric: Number of Live Instances
269 # count all the `new` made on each mclass
273 redef fun name
do return "cnli"
274 redef fun desc
do return "number of live instances for a mclass"
276 redef fun collect
(mclasses
) do end
279 # Class Metric: Number of Live Cast
281 # count all the cast made on each mclass type
285 redef fun name
do return "cnlc"
286 redef fun desc
do return "number of live cast for a mclass type"
288 redef fun collect
(mclasses
) do end
293 # A metric about MType
294 interface MTypeMetric
296 redef type ELM: MType
299 # Type Metric: Number of Live Instances
301 # count all the `new` made on each types
305 redef fun name
do return "tnli"
306 redef fun desc
do return "number of live instances for a mtype"
308 redef fun collect
(mtypes
) do end
311 # Type Metric: Number of Live Cast
313 # count all the cast made to each types
317 redef fun name
do return "tnlc"
318 redef fun desc
do return "number of live casts to a mtype"
320 redef fun collect
(mtypes
) do end
323 # Type Metric: Arity of Generic Signature
326 # tags(Map[X, Y]) = 2
330 redef fun name
do return "tags"
331 redef fun desc
do return "arity of generic signature"
333 redef fun collect
(mtypes
) do
334 for mtype
in mtypes
do
335 if mtype
isa MGenericType then
336 values
[mtype
] = mtype
.arguments
.length
344 # Type Metric: Depth of Generic Signature
347 # tdgs(Map[X, List[Y]]) = 2
351 redef fun name
do return "tdos"
352 redef fun desc
do return "depth of generic signature"
354 redef fun collect
(mtypes
) do
355 for mtype
in mtypes
do
356 values
[mtype
] = mtype
.signature_depth
363 redef class RapidTypeAnalysis
369 redef fun add_new
(recv
, mtype
) do
371 tnli
.values
.inc
(mtype
)
372 cnli
.values
.inc
(mtype
.mclass
)
375 redef fun add_cast
(mtype
) do
377 tnlc
.values
.inc
(mtype
)
379 if mtype
isa MNullableType then mtype
= mtype
.mtype
380 if mtype
isa MClassType then
381 cnlc
.values
.inc
(mtype
.mclass
)
389 private fun signature_depth
: Int do
391 if mtype
isa MNullableType then mtype
= mtype
.mtype
392 if not mtype
isa MGenericType then return 0
395 for ft
in mtype
.arguments
do
396 var ftd
= ft
.signature_depth
397 if ftd
> depth
then depth
= ftd