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
25 redef class ToolContext
26 var rta_metrics_phase
= new RTAMetricsPhase(self, null)
29 private class RTAMetricsPhase
31 redef fun process_mainmodule
(mainmodule
)
33 if not toolcontext
.opt_rta
.value
and not toolcontext
.opt_all
.value
then return
34 compute_rta_metrics
(toolcontext
.modelbuilder
, mainmodule
)
40 private var nlvt
: Int = 0
41 private var nlct
: Int = 0
43 private fun is_user_defined
: Bool do
45 if mtype
isa MNullableType then mtype
= mtype
.mtype
46 return self.as(MClassType).mclass
.is_user_defined
49 private fun get_depth
: Int do
51 if mtype
isa MNullableType then mtype
= mtype
.mtype
52 if not mtype
isa MGenericType then return 0
55 for ft
in mtype
.arguments
do
56 if ft
.get_depth
> depth
then depth
= ft
.get_depth
63 private var nlvt
: Int = 0
64 private var nlct
: Int = 0
65 private var live_types
: Set[MType] = new HashSet[MType]
66 private var cast_types
: Set[MType] = new HashSet[MType]
69 # Run a runtime type analysis and print metrics
70 fun compute_rta_metrics
(modelbuilder
: ModelBuilder, mainmodule
: MModule)
72 var analysis
= modelbuilder
.do_rapid_type_analysis
(mainmodule
)
74 var nlvt
= 0 # NLVT Number of Live Type
75 var nlvtg
= 0 # NLVTG Number of Generic Live Type
76 var nlvtslud
= 0 # NLCTSLUD Number of Live Type defined in SL and init in UD
77 var nlvtgslud
= 0 # NLVTGSLUD Number of Generic Live Type defined in SL and init in UD
78 var nlvtudud
= 0 # NLVTUDUD Number of Live Type defined in UD and init in UD
79 var nlvtgudud
= 0 # NLVTGUDUD Number of Generic Live Type defined in UD and init in UD
81 var nlct
= 0 # NLCT Number of Live Cast Type
82 var nlctg
= 0 # NLCTG Number of Generic Live Cast Type
83 var nlctslud
= 0 # NLCTSLUD Number of Live Cast Type defined in SL and init in UD
84 var nlctgslud
= 0 # NLCTGSLUD Number of Generic Live Cast Type defined in SL and init in UD
85 var nlctudud
= 0 # NLCTUDUD Number of Live Cast Type defined in UD and init in UD
86 var nlctgudud
= 0 # NLCTGUDUD Number of Generic Live Cast Type defined in UD and init in UD
88 var mtypes
= new HashSet[MClassType]
90 for mtype
in analysis
.live_types
do
93 mtype
.mclass
.nlvt
+= 1
94 mtype
.mclass
.live_types
.add
(mtype
)
95 if mtype
isa MGenericType then nlvtg
+= 1
96 if mtype
.is_user_defined
then
98 if mtype
isa MGenericType then nlvtgudud
+= 1
101 if mtype
isa MGenericType then nlvtgslud
+= 1
105 for mtype
in analysis
.live_cast_types
do
106 if mtype
isa MNullableType then mtype
= mtype
.mtype
107 if not mtype
isa MClassType then continue
110 mtype
.mclass
.nlct
+= 1
111 mtype
.mclass
.cast_types
.add
(mtype
)
112 if mtype
isa MGenericType then nlctg
+= 1
113 if mtype
.is_user_defined
then
115 if mtype
isa MGenericType then nlctgudud
+= 1
118 if mtype
isa MGenericType then nlctgslud
+= 1
123 if modelbuilder
.toolcontext
.opt_generate_csv
.value
then
124 var summaryCSV
= new CSVDocument(modelbuilder
.toolcontext
.output_dir
.join_path
("rta_sum_metrics.csv"))
125 summaryCSV
.set_header
("scope", "NLVT", "NLVTG", "NLCT", "NLVCTG")
126 summaryCSV
.add_line
("global", nlvt
, nlvtg
, nlct
, nlctg
)
127 summaryCSV
.add_line
("SLUD", nlvtslud
, nlvtgslud
, nlctslud
, nlctgslud
)
128 summaryCSV
.add_line
("UDUD", nlvtudud
, nlvtgudud
, nlctudud
, nlctgudud
)
131 var scalarCSV
= new CSVDocument(modelbuilder
.toolcontext
.output_dir
.join_path
("rta_scalar_metrics.csv"))
132 var udscalarCSV
= new CSVDocument(modelbuilder
.toolcontext
.output_dir
.join_path
("rta_ud_scalar_metrics.csv"))
133 scalarCSV
.set_header
("Type", "AGS", "DGS", "NLVT", "NLCT")
134 udscalarCSV
.set_header
("Type", "AGS", "DGS", "NLVT", "NLCT")
136 for mtype
in mtypes
do
138 if mtype
isa MGenericType then arity
= mtype
.arguments
.length
139 if mtype
.is_user_defined
then
140 udscalarCSV
.add_line
(mtype
, arity
, mtype
.get_depth
, mtype
.nlvt
, mtype
.nlct
)
142 scalarCSV
.add_line
(mtype
, arity
, mtype
.get_depth
, mtype
.nlvt
, mtype
.nlct
)
147 scalarCSV
= new CSVDocument(modelbuilder
.toolcontext
.output_dir
.join_path
("rta_scalar_class_metrics.csv"))
148 udscalarCSV
= new CSVDocument(modelbuilder
.toolcontext
.output_dir
.join_path
("rta_ud_scalar_class_metrics.csv"))
149 scalarCSV
.set_header
("Class", "AGS", "NLVV", "NLVT")
150 udscalarCSV
.set_header
("Class", "AGS", "NLVV", "inst")
152 for mclass
in modelbuilder
.model
.mclasses
do
153 if not mclass
.is_class
or mclass
.is_abstract
then continue
154 if mclass
.is_user_defined
then
155 udscalarCSV
.add_line
(mclass
.mclass_type
, mclass
.arity
, mclass
.live_types
.length
, mclass
.nlvt
)
157 scalarCSV
.add_line
(mclass
.mclass_type
, mclass
.arity
, mclass
.live_types
.length
, mclass
.nlvt
)
163 print
"--- RTA metrics ---"
164 print
"Number of live runtime classes: {analysis.live_classes.length}"
165 if analysis
.live_classes
.length
< 8 then print
"\t{analysis.live_classes.join(" ")}"
166 print
"Number of live runtime types (instantied resolved type): {analysis.live_types.length}"
167 if analysis
.live_types
.length
< 8 then print
"\t{analysis.live_types.join(" ")}"
168 print
"Number of live methods: {analysis.live_methods.length}"
169 if analysis
.live_methods
.length
< 8 then print
"\t{analysis.live_methods.join(" ")}"
170 print
"Number of live method definitions: {analysis.live_methoddefs.length}"
171 if analysis
.live_methoddefs
.length
< 8 then print
"\t{analysis.live_methoddefs.join(" ")}"
172 print
"Number of live runtime cast types (ie used in as and isa): {analysis.live_cast_types.length}"
173 if analysis
.live_cast_types
.length
< 8 then print
"\t{analysis.live_cast_types.join(" ")}"
176 for p
in analysis
.live_methods
do
177 for d
in p
.mpropdefs
do
178 if analysis
.live_methoddefs
.has
(d
) or d
.is_abstract
then continue
182 print
"Number of dead method definitions of live methods: {x}"