fprofiler.hpp revision 1472:c18cbe5936b8
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25// a simple flat profiler for Java
26
27
28// Forward declaration of classes defined in this header file
29class ThreadProfiler;
30class ThreadProfilerMark;
31class FlatProfiler;
32class IntervalData;
33
34// Declarations of classes defined only in the implementation.
35class ProfilerNode;
36class FlatProfilerTask;
37
38enum TickPosition {
39  tp_code,
40  tp_native
41};
42
43// One of these guys is constructed as we enter interesting regions
44// and destructed as we exit the region.  While we are in the region
45// ticks are allotted to the region.
46class ThreadProfilerMark: public StackObj {
47public:
48  // For now, the only thread-specific region is the class loader.
49  enum Region { noRegion, classLoaderRegion, extraRegion, maxRegion };
50
51  ThreadProfilerMark(Region)  KERNEL_RETURN;
52  ~ThreadProfilerMark()       KERNEL_RETURN;
53
54private:
55  ThreadProfiler* _pp;
56  Region _r;
57};
58
59#ifndef FPROF_KERNEL
60
61class IntervalData VALUE_OBJ_CLASS_SPEC {
62  // Just to keep these things all together
63private:
64  int _interpreted;
65  int _compiled;
66  int _native;
67  int _compiling;
68public:
69  int interpreted() {
70    return _interpreted;
71  }
72  int compiled() {
73    return _compiled;
74  }
75  int native() {
76    return _native;
77  }
78  int compiling() {
79    return _compiling;
80  }
81  int total() {
82    return (interpreted() + compiled() + native() + compiling());
83  }
84  void inc_interpreted() {
85    _interpreted += 1;
86  }
87  void inc_compiled() {
88    _compiled += 1;
89  }
90  void inc_native() {
91    _native += 1;
92  }
93  void inc_compiling() {
94    _compiling += 1;
95  }
96  void reset() {
97    _interpreted = 0;
98    _compiled = 0;
99    _native = 0;
100    _compiling = 0;
101  }
102  static void print_header(outputStream* st);
103  void print_data(outputStream* st);
104};
105#endif // FPROF_KERNEL
106
107class ThreadProfiler: public CHeapObj {
108public:
109  ThreadProfiler()    KERNEL_RETURN;
110  ~ThreadProfiler()   KERNEL_RETURN;
111
112  // Resets the profiler
113  void reset()        KERNEL_RETURN;
114
115  // Activates the profiler for a certain thread
116  void engage()       KERNEL_RETURN;
117
118  // Deactivates the profiler
119  void disengage()    KERNEL_RETURN;
120
121  // Prints the collected profiling information
122  void print(const char* thread_name) KERNEL_RETURN;
123
124  // Garbage Collection Support
125  void oops_do(OopClosure* f)         KERNEL_RETURN;
126
127#ifndef FPROF_KERNEL
128private:
129  // for recording ticks.
130  friend class ProfilerNode;
131  char* area_bottom; // preallocated area for pnodes
132  char* area_top;
133  char* area_limit;
134  static int            table_size;
135  ProfilerNode** table;
136
137private:
138  void record_interpreted_tick(JavaThread* thread, frame fr, TickPosition where, int* ticks);
139  void record_compiled_tick   (JavaThread* thread, frame fr, TickPosition where);
140  void interpreted_update(methodOop method, TickPosition where);
141  void compiled_update   (methodOop method, TickPosition where);
142  void stub_update       (methodOop method, const char* name, TickPosition where);
143  void adapter_update    (TickPosition where);
144
145  void runtime_stub_update(const CodeBlob* stub, const char* name, TickPosition where);
146  void unknown_compiled_update    (const CodeBlob* cb, TickPosition where);
147
148  void vm_update    (TickPosition where);
149  void vm_update    (const char* name, TickPosition where);
150
151  void record_tick_for_running_frame(JavaThread* thread, frame fr);
152  void record_tick_for_calling_frame(JavaThread* thread, frame fr);
153
154  void initialize();
155
156  static int  entry(int value);
157
158
159private:
160  friend class FlatProfiler;
161  void record_tick(JavaThread* thread);
162  bool engaged;
163  // so we can do percentages for this thread, and quick checks for activity
164  int thread_ticks;
165  int compiler_ticks;
166  int interpreter_ticks;
167
168public:
169  void inc_thread_ticks() { thread_ticks += 1; }
170
171private:
172  friend class ThreadProfilerMark;
173  // counters for thread-specific regions
174  bool region_flag[ThreadProfilerMark::maxRegion];
175  int class_loader_ticks;
176  int extra_ticks;
177
178private:
179  // other thread-specific regions
180  int blocked_ticks;
181  enum UnknownTickSites {
182      ut_null_method,
183      ut_vtable_stubs,
184      ut_running_frame,
185      ut_calling_frame,
186      ut_no_pc,
187      ut_no_last_Java_frame,
188      ut_unknown_thread_state,
189      ut_end
190  };
191  int unknown_ticks_array[ut_end];
192  int unknown_ticks() {
193    int result = 0;
194    for (int ut = 0; ut < ut_end; ut += 1) {
195      result += unknown_ticks_array[ut];
196    }
197    return result;
198  }
199
200  elapsedTimer timer;
201
202  // For interval timing
203private:
204  IntervalData _interval_data;
205  IntervalData interval_data() {
206    return _interval_data;
207  }
208  IntervalData* interval_data_ref() {
209    return &_interval_data;
210  }
211#endif // FPROF_KERNEL
212};
213
214class FlatProfiler: AllStatic {
215public:
216  static void reset() KERNEL_RETURN ;
217  static void engage(JavaThread* mainThread, bool fullProfile) KERNEL_RETURN ;
218  static void disengage() KERNEL_RETURN ;
219  static void print(int unused) KERNEL_RETURN ;
220  static bool is_active() KERNEL_RETURN_(return false;) ;
221
222  // This is NULL if each thread has its own thread profiler,
223  // else this is the single thread profiler used by all threads.
224  // In particular it makes a difference during garbage collection,
225  // where you only want to traverse each thread profiler once.
226  static ThreadProfiler* get_thread_profiler() KERNEL_RETURN_(return NULL;);
227
228  // Garbage Collection Support
229  static void oops_do(OopClosure* f) KERNEL_RETURN ;
230
231  // Support for disassembler to inspect the PCRecorder
232
233  // Returns the start address for a given pc
234  // NULL is returned if the PCRecorder is inactive
235  static address bucket_start_for(address pc) KERNEL_RETURN_(return NULL;);
236
237  enum { MillisecsPerTick = 10 };   // ms per profiling ticks
238
239  // Returns the number of ticks recorded for the bucket
240  // pc belongs to.
241  static int bucket_count_for(address pc) KERNEL_RETURN_(return 0;);
242
243#ifndef FPROF_KERNEL
244
245 private:
246  static bool full_profile() {
247    return full_profile_flag;
248  }
249
250  friend class ThreadProfiler;
251  // the following group of ticks cover everything that's not attributed to individual Java methods
252  static int  received_gc_ticks;      // ticks during which gc was active
253  static int vm_operation_ticks;      // total ticks in vm_operations other than GC
254  static int threads_lock_ticks;      // the number of times we couldn't get the Threads_lock without blocking
255  static int      blocked_ticks;      // ticks when the thread was blocked.
256  static int class_loader_ticks;      // total ticks in class loader
257  static int        extra_ticks;      // total ticks an extra temporary measuring
258  static int     compiler_ticks;      // total ticks in compilation
259  static int  interpreter_ticks;      // ticks in unknown interpreted method
260  static int        deopt_ticks;      // ticks in deoptimization
261  static int      unknown_ticks;      // ticks that cannot be categorized
262  static int     received_ticks;      // ticks that were received by task
263  static int    delivered_ticks;      // ticks that were delivered by task
264  static int non_method_ticks() {
265    return
266      ( received_gc_ticks
267      + vm_operation_ticks
268      + deopt_ticks
269      + threads_lock_ticks
270      + blocked_ticks
271      + compiler_ticks
272      + interpreter_ticks
273      + unknown_ticks );
274  }
275  static elapsedTimer timer;
276
277  // Counts of each of the byte codes
278  static int*           bytecode_ticks;
279  static int*           bytecode_ticks_stub;
280  static void print_byte_code_statistics();
281
282  // the ticks below are for continuous profiling (to adjust recompilation, etc.)
283  static int          all_ticks;      // total count of ticks received so far
284  static int      all_int_ticks;      // ticks in interpreter
285  static int     all_comp_ticks;      // ticks in compiled code (+ native)
286  static bool full_profile_flag;      // collecting full profile?
287
288  // to accumulate thread-specific data
289  // if we aren't profiling individual threads.
290  static ThreadProfiler* thread_profiler;
291  static ThreadProfiler* vm_thread_profiler;
292
293  static void allocate_table();
294
295  // The task that periodically interrupts things.
296  friend class FlatProfilerTask;
297  static FlatProfilerTask* task;
298  static void record_vm_operation();
299  static void record_vm_tick();
300  static void record_thread_ticks();
301
302  // For interval analysis
303 private:
304  static int interval_ticks_previous;  // delivered_ticks from the last interval
305  static void interval_record_thread(ThreadProfiler* tp); // extract ticks from ThreadProfiler.
306  static void interval_print();       // print interval data.
307  static void interval_reset();       // reset interval data.
308  enum {interval_print_size = 10};
309  static IntervalData* interval_data;
310#endif // FPROF_KERNEL
311};
312