47 "allocation activities at different callsites.", |
49 "allocation activities at different callsites.", |
48 "BOOLEAN", false, "false"), |
50 "BOOLEAN", false, "false"), |
49 _shutdown("shutdown", "request runtime to shutdown itself and free the " \ |
51 _shutdown("shutdown", "request runtime to shutdown itself and free the " \ |
50 "memory used by runtime.", |
52 "memory used by runtime.", |
51 "BOOLEAN", false, "false"), |
53 "BOOLEAN", false, "false"), |
52 _auto_shutdown("autoShutdown", "automatically shutdown itself under " \ |
54 _statistics("statistics", "print tracker statistics for tuning purpose.", \ |
53 "stress situation", |
55 "BOOLEAN", false, "false"), |
54 "BOOLEAN", true, "true"), |
|
55 #ifndef PRODUCT |
|
56 _debug("debug", "print tracker statistics. Debug only, not thread safe", \ |
|
57 "BOOLEAN", false, "false"), |
|
58 #endif |
|
59 _scale("scale", "Memory usage in which scale, KB, MB or GB", |
56 _scale("scale", "Memory usage in which scale, KB, MB or GB", |
60 "STRING", false, "KB") { |
57 "STRING", false, "KB") { |
61 _dcmdparser.add_dcmd_option(&_summary); |
58 _dcmdparser.add_dcmd_option(&_summary); |
62 _dcmdparser.add_dcmd_option(&_detail); |
59 _dcmdparser.add_dcmd_option(&_detail); |
63 _dcmdparser.add_dcmd_option(&_baseline); |
60 _dcmdparser.add_dcmd_option(&_baseline); |
64 _dcmdparser.add_dcmd_option(&_summary_diff); |
61 _dcmdparser.add_dcmd_option(&_summary_diff); |
65 _dcmdparser.add_dcmd_option(&_detail_diff); |
62 _dcmdparser.add_dcmd_option(&_detail_diff); |
66 _dcmdparser.add_dcmd_option(&_shutdown); |
63 _dcmdparser.add_dcmd_option(&_shutdown); |
67 _dcmdparser.add_dcmd_option(&_auto_shutdown); |
64 _dcmdparser.add_dcmd_option(&_statistics); |
68 #ifndef PRODUCT |
|
69 _dcmdparser.add_dcmd_option(&_debug); |
|
70 #endif |
|
71 _dcmdparser.add_dcmd_option(&_scale); |
65 _dcmdparser.add_dcmd_option(&_scale); |
72 } |
66 } |
73 |
67 |
|
68 |
|
69 size_t NMTDCmd::get_scale(const char* scale) const { |
|
70 if (scale == NULL) return 0; |
|
71 return NMTUtil::scale_from_name(scale); |
|
72 } |
|
73 |
74 void NMTDCmd::execute(DCmdSource source, TRAPS) { |
74 void NMTDCmd::execute(DCmdSource source, TRAPS) { |
|
75 // Check NMT state |
|
76 // native memory tracking has to be on |
|
77 if (MemTracker::tracking_level() == NMT_off) { |
|
78 output()->print_cr("Native memory tracking is not enabled"); |
|
79 return; |
|
80 } else if (MemTracker::tracking_level() == NMT_minimal) { |
|
81 output()->print_cr("Native memory tracking has been shutdown"); |
|
82 return; |
|
83 } |
|
84 |
75 const char* scale_value = _scale.value(); |
85 const char* scale_value = _scale.value(); |
76 size_t scale_unit; |
86 size_t scale_unit = get_scale(scale_value); |
77 if (strcmp(scale_value, "KB") == 0 || strcmp(scale_value, "kb") == 0) { |
87 if (scale_unit == 0) { |
78 scale_unit = K; |
|
79 } else if (strcmp(scale_value, "MB") == 0 || |
|
80 strcmp(scale_value, "mb") == 0) { |
|
81 scale_unit = M; |
|
82 } else if (strcmp(scale_value, "GB") == 0 || |
|
83 strcmp(scale_value, "gb") == 0) { |
|
84 scale_unit = G; |
|
85 } else { |
|
86 output()->print_cr("Incorrect scale value: %s", scale_value); |
88 output()->print_cr("Incorrect scale value: %s", scale_value); |
87 return; |
89 return; |
88 } |
90 } |
89 |
91 |
90 int nopt = 0; |
92 int nopt = 0; |
92 if (_detail.is_set() && _detail.value()) { ++nopt; } |
94 if (_detail.is_set() && _detail.value()) { ++nopt; } |
93 if (_baseline.is_set() && _baseline.value()) { ++nopt; } |
95 if (_baseline.is_set() && _baseline.value()) { ++nopt; } |
94 if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; } |
96 if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; } |
95 if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; } |
97 if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; } |
96 if (_shutdown.is_set() && _shutdown.value()) { ++nopt; } |
98 if (_shutdown.is_set() && _shutdown.value()) { ++nopt; } |
97 if (_auto_shutdown.is_set()) { ++nopt; } |
99 if (_statistics.is_set() && _statistics.value()) { ++nopt; } |
98 |
|
99 #ifndef PRODUCT |
|
100 if (_debug.is_set() && _debug.value()) { ++nopt; } |
|
101 #endif |
|
102 |
100 |
103 if (nopt > 1) { |
101 if (nopt > 1) { |
104 output()->print_cr("At most one of the following option can be specified: " \ |
102 output()->print_cr("At most one of the following option can be specified: " \ |
105 "summary, detail, baseline, summary.diff, detail.diff, shutdown" |
103 "summary, detail, baseline, summary.diff, detail.diff, shutdown"); |
106 #ifndef PRODUCT |
|
107 ", debug" |
|
108 #endif |
|
109 ); |
|
110 return; |
104 return; |
111 } else if (nopt == 0) { |
105 } else if (nopt == 0) { |
112 if (_summary.is_set()) { |
106 if (_summary.is_set()) { |
113 output()->print_cr("No command to execute"); |
107 output()->print_cr("No command to execute"); |
114 return; |
108 return; |
115 } else { |
109 } else { |
116 _summary.set_value(true); |
110 _summary.set_value(true); |
117 } |
111 } |
118 } |
112 } |
119 |
113 |
120 #ifndef PRODUCT |
114 // Serialize NMT query |
121 if (_debug.value()) { |
115 MutexLocker locker(MemTracker::query_lock()); |
122 output()->print_cr("debug command is NOT thread-safe, may cause crash"); |
|
123 MemTracker::print_tracker_stats(output()); |
|
124 return; |
|
125 } |
|
126 #endif |
|
127 |
|
128 // native memory tracking has to be on |
|
129 if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { |
|
130 // if it is not on, what's the reason? |
|
131 output()->print_cr("%s", MemTracker::reason()); |
|
132 return; |
|
133 } |
|
134 |
116 |
135 if (_summary.value()) { |
117 if (_summary.value()) { |
136 BaselineTTYOutputer outputer(output()); |
118 report(true, scale_unit); |
137 MemTracker::print_memory_usage(outputer, scale_unit, true); |
|
138 } else if (_detail.value()) { |
119 } else if (_detail.value()) { |
139 BaselineTTYOutputer outputer(output()); |
120 if (!check_detail_tracking_level(output())) { |
140 MemTracker::print_memory_usage(outputer, scale_unit, false); |
121 return; |
|
122 } |
|
123 report(false, scale_unit); |
141 } else if (_baseline.value()) { |
124 } else if (_baseline.value()) { |
142 if (MemTracker::baseline()) { |
125 MemBaseline& baseline = MemTracker::get_baseline(); |
143 output()->print_cr("Successfully baselined."); |
126 if (!baseline.baseline(MemTracker::tracking_level() != NMT_detail)) { |
144 } else { |
127 output()->print_cr("Baseline failed"); |
145 output()->print_cr("Baseline failed."); |
128 } else { |
|
129 output()->print_cr("Baseline succeeded"); |
146 } |
130 } |
147 } else if (_summary_diff.value()) { |
131 } else if (_summary_diff.value()) { |
148 if (MemTracker::has_baseline()) { |
132 MemBaseline& baseline = MemTracker::get_baseline(); |
149 BaselineTTYOutputer outputer(output()); |
133 if (baseline.baseline_type() >= MemBaseline::Summary_baselined) { |
150 MemTracker::compare_memory_usage(outputer, scale_unit, true); |
134 report_diff(true, scale_unit); |
151 } else { |
135 } else { |
152 output()->print_cr("No baseline to compare, run 'baseline' command first"); |
136 output()->print_cr("No baseline for comparison"); |
153 } |
137 } |
154 } else if (_detail_diff.value()) { |
138 } else if (_detail_diff.value()) { |
155 if (MemTracker::has_baseline()) { |
139 if (!check_detail_tracking_level(output())) { |
156 BaselineTTYOutputer outputer(output()); |
140 return; |
157 MemTracker::compare_memory_usage(outputer, scale_unit, false); |
141 } |
158 } else { |
142 MemBaseline& baseline = MemTracker::get_baseline(); |
159 output()->print_cr("No baseline to compare to, run 'baseline' command first"); |
143 if (baseline.baseline_type() == MemBaseline::Detail_baselined) { |
|
144 report_diff(false, scale_unit); |
|
145 } else { |
|
146 output()->print_cr("No detail baseline for comparison"); |
160 } |
147 } |
161 } else if (_shutdown.value()) { |
148 } else if (_shutdown.value()) { |
162 MemTracker::shutdown(MemTracker::NMT_shutdown_user); |
149 MemTracker::shutdown(); |
163 output()->print_cr("Shutdown is in progress, it will take a few moments to " \ |
150 output()->print_cr("Native memory tracking has been turned off"); |
164 "completely shutdown"); |
151 } else if (_statistics.value()) { |
165 } else if (_auto_shutdown.is_set()) { |
152 if (check_detail_tracking_level(output())) { |
166 MemTracker::set_autoShutdown(_auto_shutdown.value()); |
153 MemTracker::tuning_statistics(output()); |
|
154 } |
167 } else { |
155 } else { |
168 ShouldNotReachHere(); |
156 ShouldNotReachHere(); |
169 output()->print_cr("Unknown command"); |
157 output()->print_cr("Unknown command"); |
170 } |
158 } |
171 } |
159 } |
179 } else { |
167 } else { |
180 return 0; |
168 return 0; |
181 } |
169 } |
182 } |
170 } |
183 |
171 |
|
172 void NMTDCmd::report(bool summaryOnly, size_t scale_unit) { |
|
173 MemBaseline baseline; |
|
174 if (baseline.baseline(summaryOnly)) { |
|
175 if (summaryOnly) { |
|
176 MemSummaryReporter rpt(baseline, output(), scale_unit); |
|
177 rpt.report(); |
|
178 } else { |
|
179 MemDetailReporter rpt(baseline, output(), scale_unit); |
|
180 rpt.report(); |
|
181 } |
|
182 } |
|
183 } |
|
184 |
|
185 void NMTDCmd::report_diff(bool summaryOnly, size_t scale_unit) { |
|
186 MemBaseline& early_baseline = MemTracker::get_baseline(); |
|
187 assert(early_baseline.baseline_type() != MemBaseline::Not_baselined, |
|
188 "Not yet baselined"); |
|
189 assert(summaryOnly || early_baseline.baseline_type() == MemBaseline::Detail_baselined, |
|
190 "Not a detail baseline"); |
|
191 |
|
192 MemBaseline baseline; |
|
193 if (baseline.baseline(summaryOnly)) { |
|
194 if (summaryOnly) { |
|
195 MemSummaryDiffReporter rpt(early_baseline, baseline, output(), scale_unit); |
|
196 rpt.report_diff(); |
|
197 } else { |
|
198 MemDetailDiffReporter rpt(early_baseline, baseline, output(), scale_unit); |
|
199 rpt.report_diff(); |
|
200 } |
|
201 } |
|
202 } |
|
203 |
|
204 bool NMTDCmd::check_detail_tracking_level(outputStream* out) { |
|
205 if (MemTracker::tracking_level() == NMT_detail) { |
|
206 return true; |
|
207 } else if (MemTracker::cmdline_tracking_level() == NMT_detail) { |
|
208 out->print_cr("Tracking level has been downgraded due to lack of resources"); |
|
209 return false; |
|
210 } else { |
|
211 out->print_cr("Detail tracking is not enabled"); |
|
212 return false; |
|
213 } |
|
214 } |