fprofiler.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.28 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_fprofiler.cpp.incl"
00026 
00027 pnode** FlatProfiler::table = NULL;
00028 int     FlatProfiler::table_size = 1024;
00029 
00030 DeltaProcess*     FlatProfiler::proc = NULL;
00031 FlatProfilerTask* FlatProfiler::task = NULL;
00032 timer             FlatProfiler::time;
00033 
00034 int FlatProfiler::gc_ticks        = 0;
00035 int FlatProfiler::semaphore_ticks = 0;
00036 int FlatProfiler::stub_ticks      = 0;
00037 int FlatProfiler::unknown_ticks   = 0;
00038 int FlatProfiler::compiler_ticks  = 0;
00039 
00040 static const int col2 = 11;     // position of output column 2
00041 static const int col3 = 30;     // position of output column 3
00042 static const int col4 = 55;     // position of output column 4
00043 
00044 class tick_counter {
00045  public:
00046   int ticks_in_code;
00047   int ticks_in_primitives;
00048   int ticks_in_compiler;
00049   int ticks_in_pics;
00050   int ticks_in_other;
00051 
00052   tick_counter() { 
00053     ticks_in_code       = 0;
00054     ticks_in_primitives = 0;
00055     ticks_in_compiler   = 0;
00056     ticks_in_pics       = 0;
00057     ticks_in_other      = 0;
00058   }
00059 
00060 
00061   int total() const {
00062     return ticks_in_code
00063          + ticks_in_primitives
00064          + ticks_in_compiler
00065          + ticks_in_pics
00066          + ticks_in_other;
00067   }
00068 
00069   void add(tick_counter* a) {
00070     ticks_in_code       += a->ticks_in_code;
00071     ticks_in_primitives += a->ticks_in_primitives;
00072     ticks_in_compiler   += a->ticks_in_compiler;
00073     ticks_in_pics       += a->ticks_in_pics;
00074     ticks_in_other      += a->ticks_in_other;
00075   }
00076 
00077   void update(TickPosition where) {
00078     switch(where) {
00079       case in_code:      ticks_in_code++;       break;
00080       case in_primitive: ticks_in_primitives++; break;
00081       case in_compiler:  ticks_in_compiler++;   break;
00082       case in_pic:       ticks_in_pics++;       break;
00083       case other:        ticks_in_other++;      break;
00084     }
00085   }
00086 
00087   void print_code(outputStream* st, int total_ticks) {
00088     st->print("%5.1f%% %3d ", total() * 100.0 / total_ticks, ticks_in_code);
00089   }
00090 
00091   void print_other(outputStream* st) {    
00092     if (ticks_in_primitives > 0) st->print("prim=%d ",  ticks_in_primitives);
00093     if (ticks_in_compiler > 0)   st->print("comp=%d ",  ticks_in_compiler);
00094     if (ticks_in_pics > 0)       st->print("pics=%d ",  ticks_in_pics);
00095     if (ticks_in_other > 0)      st->print("other=%d ", ticks_in_other);
00096   }
00097 };
00098 
00099 class pnode : public CHeapObj {
00100  private:
00101   pnode* _next;
00102  public:
00103   tick_counter ticks;
00104 
00105  public:
00106   pnode() {
00107     _next = NULL;
00108   }
00109 
00110   ~pnode() {
00111     if (_next)
00112       delete _next;
00113   }
00114 
00115   void set_next(pnode* n) { _next = n; }
00116   pnode* next()           { return _next; }
00117 
00118   void update(TickPosition where) { ticks.update(where);}
00119   int total_ticks() { return ticks.total(); }
00120 
00121   virtual bool is_interpreted() const { return false; }
00122   virtual bool is_compiled()    const { return false; }
00123 
00124   virtual bool match(methodOop m, klassOop k) { return false; }
00125   virtual bool match(nmethod* nm)             { return false; }
00126 
00127 
00128   static void print_title(outputStream* st) {
00129     st->fill_to(col2);
00130     st->print("Receiver");
00131     st->fill_to(col3);
00132     st->print("Method");
00133     st->fill_to(col4);
00134     st->print_cr("Leaf ticks");
00135   }
00136 
00137   static void print_total(outputStream* st, tick_counter* t, int total, char* msg) {
00138     t->print_code(st, total);
00139     st->print(msg);
00140     st->fill_to(col4);
00141     t->print_other(st);
00142     st->cr();
00143   }
00144 
00145   virtual methodOop method()         = 0;
00146   virtual klassOop  receiver_klass() = 0;
00147   
00148   void print_receiver_klass_on(outputStream* st) {
00149     receiver_klass()->klass_part()->print_name_on(st);
00150   }
00151 
00152   virtual void print_method_on(outputStream* st) {
00153     methodOop m = method();
00154     if (m->is_blockMethod()) {
00155       st->print("[] ");
00156       m->enclosing_method_selector()->print_symbol_on(st);
00157     } else {
00158       m->selector()->print_symbol_on(st);
00159     }
00160 
00161     if (ProfilerShowMethodHolder) {
00162       klassOop method_holder = receiver_klass()->klass_part()->lookup_method_holder_for(m);
00163       if (method_holder && (method_holder != receiver_klass())) {
00164         std->print(", in ");
00165         method_holder->klass_part()->print_name_on(std);
00166       }
00167     }
00168   }
00169 
00170   virtual void print(outputStream* st, int total_ticks) {
00171     ticks.print_code(st, total_ticks);
00172     st->fill_to(col2);
00173     print_receiver_klass_on(st);
00174     st->fill_to(col3);
00175 
00176     print_method_on(st);
00177     st->fill_to(col4);
00178 
00179     ticks.print_other(st);
00180     st->cr();
00181   }
00182 
00183   // for sorting
00184   static int compare(pnode** a, pnode** b) { return (*b)->total_ticks() - (*a)->total_ticks(); }
00185 };
00186 
00187 class interpretedNode : public pnode {
00188  private:
00189    methodOop _method;
00190    klassOop  _receiver_klass;
00191  public:
00192    interpretedNode(methodOop method, klassOop receiver_klass, TickPosition where) : pnode() {
00193      _method         = method;
00194      _receiver_klass = receiver_klass;
00195      update(where);
00196    }
00197 
00198    bool is_interpreted() const { return true; }
00199 
00200    bool match(methodOop m, klassOop k) {
00201       return   _method         == m 
00202             && _receiver_klass == k;
00203    }
00204 
00205    methodOop method()         { return _method;         }
00206    klassOop  receiver_klass() { return _receiver_klass; }
00207 
00208    static void print_title(outputStream* st) {
00209      st->print("       Int");
00210      pnode::print_title(st);
00211    }
00212 
00213    void print(outputStream* st, int total_ticks) {
00214      pnode::print(st, total_ticks);
00215    }
00216 };
00217 
00218 class compiledNode : public pnode {
00219  private:
00220    nmethod* nm;
00221  public:
00222    compiledNode(nmethod* nm, TickPosition where) : pnode() {
00223      this->nm = nm;
00224      update(where);
00225   }
00226   bool is_compiled()    const { return true; }
00227 
00228   bool match(nmethod* m) { return nm == m; }
00229 
00230   methodOop method()         { return nm->method();         }
00231   klassOop  receiver_klass() { return nm->receiver_klass(); }
00232 
00233   static void print_title(outputStream* st) {
00234     st->print("       Opt");
00235     pnode::print_title(st);
00236   }
00237 
00238   void print(outputStream* st, int total_ticks) {
00239     pnode::print(st, total_ticks);
00240   }
00241 
00242   void print_method_on(outputStream* st) {
00243     if (nm->isUncommonRecompiled()) {
00244       st->print("Uncommom recompiled ");
00245     }
00246     pnode::print_method_on(st);
00247     if (CompilerDebug) {
00248       st->print(" %#x ", nm);
00249     }
00250   }
00251 };
00252 
00253 int FlatProfiler::entry(int  value) {
00254   return value % table_size;
00255 }
00256 
00257 void FlatProfiler::interpreted_update(methodOop method, klassOop klass, TickPosition where) {
00258   int index = entry(method->selector_or_method()->identity_hash());
00259   if (!table[index]) {
00260     table[index] = new interpretedNode(method, klass, where);
00261   } else {
00262     for(pnode* node = table[index]; node; node = node->next()) {
00263       if (node->match(method, klass)) {
00264         node->update(where);
00265         return;
00266       }
00267       if (!node->next())
00268         node->set_next(new interpretedNode(method, klass, where));
00269     }
00270   }
00271 }
00272 
00273 void FlatProfiler::compiled_update(nmethod* nm, TickPosition where) {
00274   int index = entry(nm->main_id.major());
00275   if (!table[index]) {
00276     table[index] = new compiledNode(nm, where);
00277   } else {
00278     for(pnode* node = table[index]; node; node = node->next()) {
00279       if (node->match(nm)) {
00280         node->update(where);
00281         return;
00282       }
00283       if (!node->next())
00284         node->set_next(new compiledNode(nm, where));
00285     }
00286   }
00287 }
00288 
00289 class FlatProfilerTask : public PeriodicTask {
00290  public:
00291   FlatProfilerTask(int interval_time) : PeriodicTask(interval_time) {}
00292   void task();
00293 };
00294 
00295 void FlatProfilerTask::task() {
00296   // ignore of we're not in the right process
00297   if (FlatProfiler::proc == NULL) return; // profiler not active
00298   if (DeltaProcess::active() == FlatProfiler::proc || UseGlobalFlatProfiling) {
00299     FlatProfiler::record_tick();
00300   }
00301 }
00302 
00303 void FlatProfiler::record_tick_for_running_frame(frame fr) {
00304   // The tick happend in real code -> non VM code
00305   if (fr.is_interpreted_frame()) {
00306     methodOop method = fr.method();
00307     if (method == NULL) return;
00308     assert(method->is_method(), "must be method");
00309     FlatProfiler::interpreted_update(method, fr.receiver()->klass(), in_code);
00310 
00311   } else if (fr.is_compiled_frame()) {
00312     FlatProfiler::compiled_update(findNMethod(fr.pc()), in_code);
00313 
00314   } else if (PIC::in_heap(fr.pc())) {
00315     PIC* pic = PIC::find(fr.pc());
00316     FlatProfiler::compiled_update(findNMethod((char*) pic->compiled_ic()), in_pic);
00317 
00318   } else if (StubRoutines::contains(fr.pc())) {
00319     FlatProfiler::stub_ticks++;
00320   }
00321 }
00322 
00323 void FlatProfiler::record_tick_for_calling_frame(frame fr) {
00324   // The tick happend in VM code
00325 
00326   TickPosition where = other;
00327   if (theCompiler) { 
00328     where = in_compiler;
00329   }
00330   if (fr.is_interpreted_frame()) {
00331     methodOop method = fr.method();
00332     if (method == NULL) return;
00333     assert(method->is_method(), "must be method");
00334     int bci = method->bci_from(fr.hp());
00335     if (Bytecodes::code_type((Bytecodes::Code) *method->codes(bci)) == Bytecodes::primitive_call) {
00336       where = in_primitive;
00337     }
00338     FlatProfiler::interpreted_update(method, fr.receiver()->klass(), where);
00339 
00340   } else if (fr.is_compiled_frame()) {
00341     nmethod* nm = findNMethod(fr.pc());
00342     relocIterator iter(nm);
00343     while (iter.next()) {
00344       if (iter.is_call() && iter.call_end() == fr.pc()) {
00345         if (iter.type() == relocInfo::prim_type)
00346           where = in_primitive;
00347       }
00348     }
00349     FlatProfiler::compiled_update(nm, where);
00350 
00351   } else {
00352     if (StubRoutines::contains(fr.pc())) {
00353       FlatProfiler::stub_ticks++;
00354     } else {
00355       FlatProfiler::unknown_ticks++;
00356     }
00357   }
00358 }
00359 
00360 void FlatProfiler::record_tick() {
00361   // If we're idle forget about the tick.
00362   if (DeltaProcess::is_idle()) return;
00363 
00364   // check for special vm flags
00365   if (theCompiler)      { FlatProfiler::compiler_ticks++; }
00366   if (GCInProgress)     { FlatProfiler::gc_ticks++;        return; }
00367   if (processSemaphore) { FlatProfiler::semaphore_ticks++; return; }
00368  
00369   { FlagSetting(processSemaphore, true);
00370     DeltaProcess* p = DeltaProcess::active();
00371     if (p->last_Delta_fp()) {
00372       record_tick_for_calling_frame(p->last_frame());
00373     } else {
00374       record_tick_for_running_frame(p->profile_top_frame());
00375     }
00376   }
00377 }
00378 
00379 void FlatProfiler::allocate_table() {
00380   table = NEW_C_HEAP_ARRAY(pnode*, table_size);
00381   for(int index = 0; index < table_size; index++) 
00382     table[index] = NULL;
00383 }
00384 
00385 void FlatProfiler::reset() {
00386   proc = NULL;
00387   task = NULL;
00388 
00389   for(int index = 0; index < table_size; index++) {
00390     pnode* n = table[index];
00391     if (n) { 
00392       delete n;
00393       table[index] = NULL;
00394     }
00395   }
00396 
00397   gc_ticks           = 0;
00398   unknown_ticks      = 0;
00399   semaphore_ticks    = 0;
00400   compiler_ticks     = 0;
00401   stub_ticks         = 0;
00402 }
00403 
00404 void FlatProfiler::engage(DeltaProcess* p) {
00405   proc = p;
00406   if (task == NULL) {
00407     task = new FlatProfilerTask(10);
00408     task->enroll();
00409     time.start();
00410   }
00411 }
00412 
00413 DeltaProcess* FlatProfiler::disengage() {
00414   if (!task) return NULL;
00415   task->deroll();
00416   delete task;
00417   task = NULL;
00418   time.stop();
00419   DeltaProcess* p = process();
00420   proc = NULL;
00421   return proc;
00422 }
00423 
00424 bool FlatProfiler::is_active() {
00425   return task != NULL;
00426 }
00427 
00428 static int compare_nodes(const void* p1,  const void* p2) {
00429   pnode** pn1 = (pnode**)p1;
00430   pnode** pn2 = (pnode**)p2;
00431   return (*pn2)->total_ticks() - (*pn1)->total_ticks();
00432 }
00433 
00434 
00435 void print_ticks(char* title, int ticks, int total) {
00436  if (ticks>0)
00437     std->print_cr("%5.1f%%  %3d %s", ticks * 100.0 / total, ticks, title);
00438 }
00439 
00440 void FlatProfiler::print(int cutoff) {
00441 #ifdef PRODUCT
00442   // disable profiler
00443 #else
00444   FlagSetting f(PrintObjectID, false);
00445   ResourceMark rm;
00446   double secs = time.seconds();
00447 
00448   GrowableArray <pnode*>* array = new GrowableArray<pnode*>(200);
00449 
00450   for(int index = 0; index < table_size; index++) {
00451     for(pnode* node = table[index]; node; node = node->next())
00452       array->append(node);
00453   }
00454 
00455   array->sort(&pnode::compare);
00456 
00457   // compute total
00458   int total = total_ticks();
00459   for (index = 0; index < array->length(); index++) {
00460     total += array->at(index)->ticks.total();
00461   }
00462 
00463   std->cr();
00464   std->print_cr("Flatprofile %3.2f secs (%d ticks):", secs, total);
00465   std->cr();
00466 
00467   // print interpreted methods
00468   tick_counter interpreted_ticks;
00469   bool has_interpreted_ticks = false;
00470   int print_count = 0;
00471   for (index = 0; index < array->length(); index++) {
00472     pnode* n = array->at(index);
00473     if (n->is_interpreted()) {
00474       interpreted_ticks.add(&n->ticks);
00475       if (!has_interpreted_ticks) {
00476         interpretedNode::print_title(std);
00477         has_interpreted_ticks = true;
00478       }
00479       if (print_count++ < ProfilerNumberOfInterpreterMethods) {
00480         n->print(std, total);
00481       }
00482     }
00483   }
00484   if (has_interpreted_ticks) {
00485     tick_counter others;
00486     for ( ; index < array->length(); index++) others.add(&array->at(index)->ticks);
00487     if (others.total() > 0) {
00488       interpretedNode::print_total(std, &interpreted_ticks, total, "(all above)");
00489       interpretedNode::print_total(std, &others, total, "(all others)");
00490     }
00491     interpreted_ticks.add(&others);
00492     interpretedNode::print_total(std, &interpreted_ticks, total, "Total interpreted");
00493     std->cr();
00494   }
00495 
00496   // print compiled methods
00497   print_count = 0;
00498   bool has_compiled_ticks = false;
00499   tick_counter compiled_ticks;
00500   for (index = 0; index < array->length(); index++) {
00501     pnode* n = array->at(index);
00502     if (n->is_compiled()) {
00503       compiled_ticks.add(&n->ticks);
00504       if (!has_compiled_ticks) {
00505         compiledNode::print_title(std);
00506         has_compiled_ticks = true;
00507       }
00508       if (print_count++ < ProfilerNumberOfCompiledMethods) {
00509         n->print(std, total);
00510       }
00511     }
00512   }
00513 
00514   if (has_compiled_ticks) {
00515     tick_counter others;
00516     for ( ; index < array->length(); index++) others.add(&array->at(index)->ticks);
00517     if (others.total() > 0) {
00518       compiledNode::print_total(std, &compiled_ticks, total, "(all above)");
00519       compiledNode::print_total(std, &others, total, "(all others)");
00520     }
00521     compiled_ticks.add(&others);
00522     compiledNode::print_total(std, &compiled_ticks, total, "Total compiled");
00523     std->cr();
00524   }
00525 
00526   std->cr();
00527 
00528   if (total_ticks() > 0) {
00529     std->print_cr(" Additional ticks:");
00530     print_ticks("Garbage collector", gc_ticks,        total);
00531     print_ticks("Process semaphore", semaphore_ticks, total);
00532     print_ticks("Unknown code",      unknown_ticks,   total);
00533     print_ticks("Stub routines",     stub_ticks,      total);
00534     print_ticks("Total compilation (already included above)", compiler_ticks, total);
00535   }
00536 #endif
00537 }
00538 
00539 void fprofiler_init() {
00540   FlatProfiler::allocate_table();
00541 }

Generated on Mon Oct 9 13:37:10 2006 for Strongtalk VM by  doxygen 1.4.7