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.
20 private import rapid_type_analysis
22 import mmodules_metrics
23 import mclasses_metrics
25 redef class ToolContext
26 var rta_metrics_phase
: Phase = new RTAMetricsPhase(self, null)
29 private class RTAMetricsPhase
31 redef fun process_mainmodule
(mainmodule
, given_mmodules
)
33 if not toolcontext
.opt_rta
.value
and not toolcontext
.opt_all
.value
then return
34 var csv
= toolcontext
.opt_csv
.value
35 var out
= "{toolcontext.opt_dir.value or else "metrics"}/rta"
38 print toolcontext
.format_h1
("\n# RTA metrics")
40 print toolcontext
.format_h2
("\n ## Live instances by mainmodules")
41 var mmetrics
= new MetricSet
42 mmetrics
.register
(new MNLC(toolcontext
.modelbuilder
))
43 mmetrics
.register
(new MNLT(toolcontext
.modelbuilder
))
44 mmetrics
.register
(new MNCT(toolcontext
.modelbuilder
))
45 mmetrics
.register
(new MNLI(toolcontext
.modelbuilder
))
46 mmetrics
.register
(new MNLM(toolcontext
.modelbuilder
))
47 mmetrics
.register
(new MNLMD(toolcontext
.modelbuilder
))
48 mmetrics
.register
(new MNLDD(toolcontext
.modelbuilder
))
49 mmetrics
.collect
(new HashSet[MModule].from
([mainmodule
]))
50 mmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
51 if csv
then mmetrics
.to_csv
.write_to_file
("{out}/{mainmodule}.csv")
53 var mtypes
= new HashSet[MType]
54 var analysis
= new RapidTypeAnalysis(toolcontext
.modelbuilder
, mainmodule
)
56 mtypes
.add_all
(analysis
.live_types
)
57 mtypes
.add_all
(analysis
.live_cast_types
)
59 print toolcontext
.format_h2
("\n ## Total live instances by mclasses")
60 var cmetrics
= new MetricSet
61 cmetrics
.register
(analysis
.cnli
)
62 cmetrics
.register
(analysis
.cnlc
)
63 cmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
64 if csv
then cmetrics
.to_csv
.write_to_file
("{out}/mclasses.csv")
66 print toolcontext
.format_h2
("\n ## Total live instances by mtypes")
67 var tmetrics
= new MetricSet
68 tmetrics
.register
(analysis
.tnli
)
69 tmetrics
.register
(analysis
.tnlc
)
70 tmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
71 if csv
then tmetrics
.to_csv
.write_to_file
("{out}/mtypes.csv")
73 print toolcontext
.format_h2
("\n ## MType complexity")
74 var gmetrics
= new MetricSet
75 gmetrics
.register
(new TAGS)
76 gmetrics
.register
(new TDGS)
77 gmetrics
.collect
(mtypes
)
78 gmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
79 if csv
then gmetrics
.to_csv
.write_to_file
("{out}/complexity.csv")
81 callsite_info
(analysis
)
83 # dump type and method infos
85 analysis
.live_types_to_csv
.write_to_file
("{out}/rta_types.csv")
86 analysis
.live_methods_to_tree
.write_to_file
("{out}/rta_methods.dat")
90 fun callsite_info
(rta
: RapidTypeAnalysis)
92 print toolcontext
.format_h2
("\n ## Callsites")
93 print
"* {rta.live_callsites.length} live callsites"
95 var csep
= new Counter[MPropDef]
96 var cglo
= new Counter[MPropDef]
97 var morphisme
= new Counter[Int]
98 for cs
in rta
.live_callsites
do
100 var targets
= rta
.live_targets
(cs
)
104 morphisme
.inc
(targets
.length
)
107 print toolcontext
.format_h3
("MMethodDef locally designated (by number of CallSites)")
109 csep
.print_elements
(5)
111 print toolcontext
.format_h3
("MMethodDef possibly invoked at runtime (by number of CallSites)")
113 cglo
.print_elements
(5)
119 # MModule Metric: Number of Live Types
123 redef fun name
do return "mnli"
124 redef fun desc
do return "number of live instances in a mmodule"
126 var modelbuilder
: ModelBuilder
127 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
129 redef fun collect
(mainmodules
) do
130 for mainmodule
in mainmodules
do
131 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
132 analysis
.run_analysis
133 values
[mainmodule
] = analysis
.tnli
.sum
138 # MModule Metric: Number of Live Types
142 redef fun name
do return "mnlt"
143 redef fun desc
do return "number of live mtypes in a mmodule"
145 var modelbuilder
: ModelBuilder
146 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
148 redef fun collect
(mainmodules
) do
149 for mainmodule
in mainmodules
do
150 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
151 analysis
.run_analysis
152 values
[mainmodule
] = analysis
.live_types
.length
157 # MModule Metric: Number of Live Cast Types
161 redef fun name
do return "mnct"
162 redef fun desc
do return "number of live cast mtypes in a mmodule"
164 var modelbuilder
: ModelBuilder
165 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
167 redef fun collect
(mainmodules
) do
168 for mainmodule
in mainmodules
do
169 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
170 analysis
.run_analysis
171 values
[mainmodule
] = analysis
.live_cast_types
.length
176 # MModule Metric: Number of Live Classes
180 redef fun name
do return "mnlc"
181 redef fun desc
do return "number of live mclasses in a mmodule"
183 var modelbuilder
: ModelBuilder
184 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
186 redef fun collect
(mainmodules
) do
187 for mainmodule
in mainmodules
do
188 var live
= new HashSet[MClass]
189 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
190 analysis
.run_analysis
191 for mtype
in analysis
.live_types
do
192 live
.add
(mtype
.mclass
)
194 values
[mainmodule
] = live
.length
199 # MModule Metric: Number of Live Methods
203 redef fun name
do return "mnlm"
204 redef fun desc
do return "number of live methods in a mmodule"
206 var modelbuilder
: ModelBuilder
207 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
209 redef fun collect
(mainmodules
) do
210 for mainmodule
in mainmodules
do
211 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
212 analysis
.run_analysis
213 values
[mainmodule
] = analysis
.live_methods
.length
218 # MModule Metric: Number of Live MethodDefs
222 redef fun name
do return "mnlmd"
223 redef fun desc
do return "number of live method definitions in a mmodule"
225 var modelbuilder
: ModelBuilder
226 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
228 redef fun collect
(mainmodules
) do
229 for mainmodule
in mainmodules
do
230 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
231 analysis
.run_analysis
232 values
[mainmodule
] = analysis
.live_methoddefs
.length
237 # MModule Metric: Number of Dead MethodDefs
241 redef fun name
do return "mnldd"
242 redef fun desc
do return "number of dead method definitions in a mmodule"
244 var modelbuilder
: ModelBuilder
245 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
247 redef fun collect
(mainmodules
) do
248 for mainmodule
in mainmodules
do
250 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
251 analysis
.run_analysis
252 for mmethod
in analysis
.live_methods
do
253 for mdef
in mmethod
.mpropdefs
do
254 if analysis
.live_methoddefs
.has
(mdef
) or mdef
.is_abstract
then continue
258 values
[mainmodule
] = dead
265 # Class Metric: Number of Live Instances
267 # count all the `new` made on each mclass
271 redef fun name
do return "cnli"
272 redef fun desc
do return "number of live instances for a mclass"
274 redef fun collect
(mclasses
) do end
277 # Class Metric: Number of Live Cast
279 # count all the cast made on each mclass type
283 redef fun name
do return "cnlc"
284 redef fun desc
do return "number of live cast for a mclass type"
286 redef fun collect
(mclasses
) do end
291 # A metric about MType
292 interface MTypeMetric
294 redef type ELM: MType
297 # Type Metric: Number of Live Instances
299 # count all the `new` made on each types
303 redef fun name
do return "tnli"
304 redef fun desc
do return "number of live instances for a mtype"
306 redef fun collect
(mtypes
) do end
309 # Type Metric: Number of Live Cast
311 # count all the cast made to each types
315 redef fun name
do return "tnlc"
316 redef fun desc
do return "number of live casts to a mtype"
318 redef fun collect
(mtypes
) do end
321 # Type Metric: Arity of Generic Signature
324 # tags(Map[X, Y]) = 2
328 redef fun name
do return "tags"
329 redef fun desc
do return "arity of generic signature"
331 redef fun collect
(mtypes
) do
332 for mtype
in mtypes
do
333 if mtype
isa MGenericType then
334 values
[mtype
] = mtype
.arguments
.length
342 # Type Metric: Depth of Generic Signature
345 # tdgs(Map[X, List[Y]]) = 2
349 redef fun name
do return "tdos"
350 redef fun desc
do return "depth of generic signature"
352 redef fun collect
(mtypes
) do
353 for mtype
in mtypes
do
354 values
[mtype
] = mtype
.signature_depth
361 redef class RapidTypeAnalysis
367 redef fun add_new
(recv
, mtype
) do
369 tnli
.values
.inc
(mtype
)
370 cnli
.values
.inc
(mtype
.mclass
)
373 redef fun add_cast
(mtype
) do
375 tnlc
.values
.inc
(mtype
)
377 mtype
= mtype
.undecorate
378 if mtype
isa MClassType then
379 cnlc
.values
.inc
(mtype
.mclass
)
387 private fun signature_depth
: Int do
388 var mtype
= self.undecorate
389 if not mtype
isa MGenericType then return 0
392 for ft
in mtype
.arguments
do
393 var ftd
= ft
.signature_depth
394 if ftd
> depth
then depth
= ftd