< prev index next >

src/hotspot/share/code/codeHeapState.cpp

Print this page

        

*** 115,126 **** #define STRINGSTREAM_FLUSH_LOCKED(termString) \ _outbuf->print("%s", termString); #endif ! const char blobTypeChar[] = {' ', 'N', 'I', 'X', 'Z', 'U', 'R', '?', 'D', 'T', 'E', 'S', 'A', 'M', 'B', 'L' }; const char* blobTypeName[] = {"noType" , "nMethod (active)" , "nMethod (inactive)" , "nMethod (deopt)" , "nMethod (zombie)" , "nMethod (unloaded)" --- 115,127 ---- #define STRINGSTREAM_FLUSH_LOCKED(termString) \ _outbuf->print("%s", termString); #endif ! const char blobTypeChar[] = {' ', 'C', 'N', 'I', 'X', 'Z', 'U', 'R', '?', 'D', 'T', 'E', 'S', 'A', 'M', 'B', 'L' }; const char* blobTypeName[] = {"noType" + , "nMethod (under construction)" , "nMethod (active)" , "nMethod (inactive)" , "nMethod (deopt)" , "nMethod (zombie)" , "nMethod (unloaded)"
*** 154,164 **** static bool segment_granules = false; static unsigned int nBlocks_t1 = 0; // counting "in_use" nmethods only. static unsigned int nBlocks_t2 = 0; // counting "in_use" nmethods only. static unsigned int nBlocks_alive = 0; // counting "not_used" and "not_entrant" nmethods only. static unsigned int nBlocks_dead = 0; // counting "zombie" and "unloaded" methods only. ! static unsigned int nBlocks_unloaded = 0; // counting "unloaded" nmethods only. This is a transien state. static unsigned int nBlocks_stub = 0; static struct FreeBlk* FreeArray = NULL; static unsigned int alloc_freeBlocks = 0; --- 155,166 ---- static bool segment_granules = false; static unsigned int nBlocks_t1 = 0; // counting "in_use" nmethods only. static unsigned int nBlocks_t2 = 0; // counting "in_use" nmethods only. static unsigned int nBlocks_alive = 0; // counting "not_used" and "not_entrant" nmethods only. static unsigned int nBlocks_dead = 0; // counting "zombie" and "unloaded" methods only. ! static unsigned int nBlocks_inconstr = 0; // counting "inconstruction" nmethods only. This is a transient state. ! static unsigned int nBlocks_unloaded = 0; // counting "unloaded" nmethods only. This is a transient state. static unsigned int nBlocks_stub = 0; static struct FreeBlk* FreeArray = NULL; static unsigned int alloc_freeBlocks = 0;
*** 224,233 **** --- 226,236 ---- segment_granules = CodeHeapStatArray[ix].segment_granules; nBlocks_t1 = CodeHeapStatArray[ix].nBlocks_t1; nBlocks_t2 = CodeHeapStatArray[ix].nBlocks_t2; nBlocks_alive = CodeHeapStatArray[ix].nBlocks_alive; nBlocks_dead = CodeHeapStatArray[ix].nBlocks_dead; + nBlocks_inconstr = CodeHeapStatArray[ix].nBlocks_inconstr; nBlocks_unloaded = CodeHeapStatArray[ix].nBlocks_unloaded; nBlocks_stub = CodeHeapStatArray[ix].nBlocks_stub; FreeArray = CodeHeapStatArray[ix].FreeArray; alloc_freeBlocks = CodeHeapStatArray[ix].alloc_freeBlocks; TopSizeArray = CodeHeapStatArray[ix].TopSizeArray;
*** 246,255 **** --- 249,259 ---- segment_granules = false; nBlocks_t1 = 0; nBlocks_t2 = 0; nBlocks_alive = 0; nBlocks_dead = 0; + nBlocks_inconstr = 0; nBlocks_unloaded = 0; nBlocks_stub = 0; FreeArray = NULL; alloc_freeBlocks = 0; TopSizeArray = NULL;
*** 272,281 **** --- 276,286 ---- CodeHeapStatArray[ix].segment_granules = segment_granules; CodeHeapStatArray[ix].nBlocks_t1 = nBlocks_t1; CodeHeapStatArray[ix].nBlocks_t2 = nBlocks_t2; CodeHeapStatArray[ix].nBlocks_alive = nBlocks_alive; CodeHeapStatArray[ix].nBlocks_dead = nBlocks_dead; + CodeHeapStatArray[ix].nBlocks_inconstr = nBlocks_inconstr; CodeHeapStatArray[ix].nBlocks_unloaded = nBlocks_unloaded; CodeHeapStatArray[ix].nBlocks_stub = nBlocks_stub; CodeHeapStatArray[ix].FreeArray = FreeArray; CodeHeapStatArray[ix].alloc_freeBlocks = alloc_freeBlocks; CodeHeapStatArray[ix].TopSizeArray = TopSizeArray;
*** 552,561 **** --- 557,567 ---- //---< reset counters with every aggregation >--- nBlocks_t1 = 0; nBlocks_t2 = 0; nBlocks_alive = 0; nBlocks_dead = 0; + nBlocks_inconstr = 0; nBlocks_unloaded = 0; nBlocks_stub = 0; nBlocks_free = 0; nBlocks_used = 0;
*** 585,594 **** --- 591,601 ---- size_t t2Space = 0; size_t aliveSpace = 0; size_t disconnSpace = 0; size_t notentrSpace = 0; size_t deadSpace = 0; + size_t inconstrSpace = 0; size_t unloadedSpace = 0; size_t stubSpace = 0; size_t freeSpace = 0; size_t maxFreeSize = 0; HeapBlock* maxFreeBlock = NULL;
*** 690,699 **** --- 697,710 ---- break; case nMethod_dead: nBlocks_dead++; deadSpace += hb_bytelen; break; + case nMethod_inconstruction: + nBlocks_inconstr++; + inconstrSpace += hb_bytelen; + break; default: break; } }
*** 844,853 **** --- 855,865 ---- StatArray[ix_beg].t2_age = StatArray[ix_beg].t2_age < compile_id ? compile_id : StatArray[ix_beg].t2_age; } StatArray[ix_beg].level = comp_lvl; StatArray[ix_beg].compiler = cType; break; + case nMethod_inconstruction: // let's count "in construction" nmethods here. case nMethod_alive: StatArray[ix_beg].tx_count++; StatArray[ix_beg].tx_space += (unsigned short)hb_len; StatArray[ix_beg].tx_age = StatArray[ix_beg].tx_age < compile_id ? compile_id : StatArray[ix_beg].tx_age; StatArray[ix_beg].level = comp_lvl;
*** 900,909 **** --- 912,922 ---- StatArray[ix_beg].level = comp_lvl; StatArray[ix_beg].compiler = cType; StatArray[ix_end].level = comp_lvl; StatArray[ix_end].compiler = cType; break; + case nMethod_inconstruction: // let's count "in construction" nmethods here. case nMethod_alive: StatArray[ix_beg].tx_count++; StatArray[ix_beg].tx_space += (unsigned short)beg_space; StatArray[ix_beg].tx_age = StatArray[ix_beg].tx_age < compile_id ? compile_id : StatArray[ix_beg].tx_age;
*** 947,956 **** --- 960,970 ---- StatArray[ix].t2_age = StatArray[ix].t2_age < compile_id ? compile_id : StatArray[ix].t2_age; } StatArray[ix].level = comp_lvl; StatArray[ix].compiler = cType; break; + case nMethod_inconstruction: // let's count "in construction" nmethods here. case nMethod_alive: StatArray[ix].tx_count++; StatArray[ix].tx_space += (unsigned short)(granule_size>>log2_seg_size); StatArray[ix].tx_age = StatArray[ix].tx_age < compile_id ? compile_id : StatArray[ix].tx_age; StatArray[ix].level = comp_lvl;
*** 969,983 **** } } } } } - if (n_methods > 0) { - avgTemp = hotnessAccumulator/n_methods; - } else { - avgTemp = 0; - } done = true; if (!insane) { // There is a risk for this block (because it contains many print statements) to get // interspersed with print data from other threads. We take this risk intentionally. --- 983,992 ----
*** 988,997 **** --- 997,1007 ---- ast->print_cr(" Tier1 Space = " SIZE_FORMAT_W(8) "k, nBlocks_t1 = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", t1Space/(size_t)K, nBlocks_t1, (100.0*t1Space)/size, (100.0*t1Space)/res_size); ast->print_cr(" Tier2 Space = " SIZE_FORMAT_W(8) "k, nBlocks_t2 = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", t2Space/(size_t)K, nBlocks_t2, (100.0*t2Space)/size, (100.0*t2Space)/res_size); ast->print_cr(" Alive Space = " SIZE_FORMAT_W(8) "k, nBlocks_alive = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", aliveSpace/(size_t)K, nBlocks_alive, (100.0*aliveSpace)/size, (100.0*aliveSpace)/res_size); ast->print_cr(" disconnected = " SIZE_FORMAT_W(8) "k, nBlocks_disconn = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", disconnSpace/(size_t)K, nBlocks_disconn, (100.0*disconnSpace)/size, (100.0*disconnSpace)/res_size); ast->print_cr(" not entrant = " SIZE_FORMAT_W(8) "k, nBlocks_notentr = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", notentrSpace/(size_t)K, nBlocks_notentr, (100.0*notentrSpace)/size, (100.0*notentrSpace)/res_size); + ast->print_cr(" inconstrSpace = " SIZE_FORMAT_W(8) "k, nBlocks_inconstr = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", inconstrSpace/(size_t)K, nBlocks_inconstr, (100.0*inconstrSpace)/size, (100.0*inconstrSpace)/res_size); ast->print_cr(" unloadedSpace = " SIZE_FORMAT_W(8) "k, nBlocks_unloaded = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", unloadedSpace/(size_t)K, nBlocks_unloaded, (100.0*unloadedSpace)/size, (100.0*unloadedSpace)/res_size); ast->print_cr(" deadSpace = " SIZE_FORMAT_W(8) "k, nBlocks_dead = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", deadSpace/(size_t)K, nBlocks_dead, (100.0*deadSpace)/size, (100.0*deadSpace)/res_size); ast->print_cr(" stubSpace = " SIZE_FORMAT_W(8) "k, nBlocks_stub = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", stubSpace/(size_t)K, nBlocks_stub, (100.0*stubSpace)/size, (100.0*stubSpace)/res_size); ast->print_cr("ZombieBlocks = %8d. These are HeapBlocks which could not be identified as CodeBlobs.", nBlocks_zomb); ast->cr();
*** 1007,1019 **** --- 1017,1035 ---- int reset_val = NMethodSweeper::hotness_counter_reset_val(); double reverse_free_ratio = (res_size > size) ? (double)res_size/(double)(res_size-size) : (double)res_size; printBox(ast, '-', "Method hotness information at time of this analysis", NULL); ast->print_cr("Highest possible method temperature: %12d", reset_val); ast->print_cr("Threshold for method to be considered 'cold': %12.3f", -reset_val + reverse_free_ratio * NmethodSweepActivity); + if (n_methods > 0) { + avgTemp = hotnessAccumulator/n_methods; ast->print_cr("min. hotness = %6d", minTemp); ast->print_cr("avg. hotness = %6d", avgTemp); ast->print_cr("max. hotness = %6d", maxTemp); + } else { + avgTemp = 0; + ast->print_cr("No hotness data available"); + } STRINGSTREAM_FLUSH("\n") // This loop is intentionally printing directly to "out". out->print("Verifying collected data..."); size_t granule_segs = granule_size>>log2_seg_size;
*** 1022,1031 **** --- 1038,1050 ---- out->print_cr("t1_count[%d] = %d", ix, StatArray[ix].t1_count); } if (StatArray[ix].t2_count > granule_segs) { out->print_cr("t2_count[%d] = %d", ix, StatArray[ix].t2_count); } + if (StatArray[ix].tx_count > granule_segs) { + out->print_cr("tx_count[%d] = %d", ix, StatArray[ix].tx_count); + } if (StatArray[ix].stub_count > granule_segs) { out->print_cr("stub_count[%d] = %d", ix, StatArray[ix].stub_count); } if (StatArray[ix].dead_count > granule_segs) { out->print_cr("dead_count[%d] = %d", ix, StatArray[ix].dead_count);
*** 1034,1055 **** out->print_cr("t1_space[%d] = %d", ix, StatArray[ix].t1_space); } if (StatArray[ix].t2_space > granule_segs) { out->print_cr("t2_space[%d] = %d", ix, StatArray[ix].t2_space); } if (StatArray[ix].stub_space > granule_segs) { out->print_cr("stub_space[%d] = %d", ix, StatArray[ix].stub_space); } if (StatArray[ix].dead_space > granule_segs) { out->print_cr("dead_space[%d] = %d", ix, StatArray[ix].dead_space); } // this cast is awful! I need it because NT/Intel reports a signed/unsigned mismatch. ! if ((size_t)(StatArray[ix].t1_count+StatArray[ix].t2_count+StatArray[ix].stub_count+StatArray[ix].dead_count) > granule_segs) { ! out->print_cr("t1_count[%d] = %d, t2_count[%d] = %d, stub_count[%d] = %d", ix, StatArray[ix].t1_count, ix, StatArray[ix].t2_count, ix, StatArray[ix].stub_count); } ! if ((size_t)(StatArray[ix].t1_space+StatArray[ix].t2_space+StatArray[ix].stub_space+StatArray[ix].dead_space) > granule_segs) { ! out->print_cr("t1_space[%d] = %d, t2_space[%d] = %d, stub_space[%d] = %d", ix, StatArray[ix].t1_space, ix, StatArray[ix].t2_space, ix, StatArray[ix].stub_space); } } // This loop is intentionally printing directly to "out". if (used_topSizeBlocks > 0) { --- 1053,1077 ---- out->print_cr("t1_space[%d] = %d", ix, StatArray[ix].t1_space); } if (StatArray[ix].t2_space > granule_segs) { out->print_cr("t2_space[%d] = %d", ix, StatArray[ix].t2_space); } + if (StatArray[ix].tx_space > granule_segs) { + out->print_cr("tx_space[%d] = %d", ix, StatArray[ix].tx_space); + } if (StatArray[ix].stub_space > granule_segs) { out->print_cr("stub_space[%d] = %d", ix, StatArray[ix].stub_space); } if (StatArray[ix].dead_space > granule_segs) { out->print_cr("dead_space[%d] = %d", ix, StatArray[ix].dead_space); } // this cast is awful! I need it because NT/Intel reports a signed/unsigned mismatch. ! if ((size_t)(StatArray[ix].t1_count+StatArray[ix].t2_count+StatArray[ix].tx_count+StatArray[ix].stub_count+StatArray[ix].dead_count) > granule_segs) { ! out->print_cr("t1_count[%d] = %d, t2_count[%d] = %d, tx_count[%d] = %d, stub_count[%d] = %d", ix, StatArray[ix].t1_count, ix, StatArray[ix].t2_count, ix, StatArray[ix].tx_count, ix, StatArray[ix].stub_count); } ! if ((size_t)(StatArray[ix].t1_space+StatArray[ix].t2_space+StatArray[ix].tx_space+StatArray[ix].stub_space+StatArray[ix].dead_space) > granule_segs) { ! out->print_cr("t1_space[%d] = %d, t2_space[%d] = %d, tx_space[%d] = %d, stub_space[%d] = %d", ix, StatArray[ix].t1_space, ix, StatArray[ix].t2_space, ix, StatArray[ix].tx_space, ix, StatArray[ix].stub_space); } } // This loop is intentionally printing directly to "out". if (used_topSizeBlocks > 0) {
*** 1129,1139 **** done = true; } if (!done || (nBlocks_free == 0)) { if (nBlocks_free == 0) { ! printBox(ast, '-', "no free blocks found in", heapName); } else if (!done) { ast->print_cr("Free block count mismatch could not be resolved."); ast->print_cr("Try to run \"aggregate\" function to update counters"); } STRINGSTREAM_FLUSH("") --- 1151,1161 ---- done = true; } if (!done || (nBlocks_free == 0)) { if (nBlocks_free == 0) { ! printBox(ast, '-', "no free blocks found in ", heapName); } else if (!done) { ast->print_cr("Free block count mismatch could not be resolved."); ast->print_cr("Try to run \"aggregate\" function to update counters"); } STRINGSTREAM_FLUSH("")
*** 1261,1271 **** ast->print("%5d", nm->hotness_counter()); //---< name and signature >--- ast->fill_to(67+6); if (nm->is_in_use()) {blob_name = nm->method()->name_and_sig_as_C_string(); } if (nm->is_not_entrant()) {blob_name = nm->method()->name_and_sig_as_C_string(); } ! if (nm->is_zombie()) {ast->print("%14s", " zombie method"); } ast->print("%s", blob_name); } else { //---< block size in hex >--- ast->print(PTR32_FORMAT, (unsigned int)(TopSizeArray[i].len<<log2_seg_size)); ast->print("(" SIZE_FORMAT_W(4) "K)", (TopSizeArray[i].len<<log2_seg_size)/K); --- 1283,1294 ---- ast->print("%5d", nm->hotness_counter()); //---< name and signature >--- ast->fill_to(67+6); if (nm->is_in_use()) {blob_name = nm->method()->name_and_sig_as_C_string(); } if (nm->is_not_entrant()) {blob_name = nm->method()->name_and_sig_as_C_string(); } ! if (nm->is_not_installed()) {ast->print("%s", " not (yet) installed method "); } ! if (nm->is_zombie()) {ast->print("%s", " zombie method "); } ast->print("%s", blob_name); } else { //---< block size in hex >--- ast->print(PTR32_FORMAT, (unsigned int)(TopSizeArray[i].len<<log2_seg_size)); ast->print("(" SIZE_FORMAT_W(4) "K)", (TopSizeArray[i].len<<log2_seg_size)/K);
*** 1655,1665 **** } } { if (nBlocks_alive > 0) { ! printBox(ast, '-', "not_used/not_entrant nMethod count only, 0x1..0xf. '*' indicates >= 16 blocks, ' ' indicates empty", NULL); STRINGSTREAM_FLUSH_LOCKED("") granules_per_line = 128; for (unsigned int ix = 0; ix < alloc_granules; ix++) { print_line_delim(out, ast, low_bound, ix, granules_per_line); --- 1678,1688 ---- } } { if (nBlocks_alive > 0) { ! printBox(ast, '-', "not_used/not_entrant/not_installed nMethod count only, 0x1..0xf. '*' indicates >= 16 blocks, ' ' indicates empty", NULL); STRINGSTREAM_FLUSH_LOCKED("") granules_per_line = 128; for (unsigned int ix = 0; ix < alloc_granules; ix++) { print_line_delim(out, ast, low_bound, ix, granules_per_line);
*** 1844,1854 **** } } { if (nBlocks_alive > 0) { ! printBox(ast, '-', "not_used/not_entrant space consumption. ' ' indicates empty, '*' indicates full", NULL); granules_per_line = 128; for (unsigned int ix = 0; ix < alloc_granules; ix++) { print_line_delim(out, ast, low_bound, ix, granules_per_line); if (segment_granules && StatArray[ix].tx_space > 0) { --- 1867,1877 ---- } } { if (nBlocks_alive > 0) { ! printBox(ast, '-', "not_used/not_entrant/not_installed space consumption. ' ' indicates empty, '*' indicates full", NULL); granules_per_line = 128; for (unsigned int ix = 0; ix < alloc_granules; ix++) { print_line_delim(out, ast, low_bound, ix, granules_per_line); if (segment_granules && StatArray[ix].tx_space > 0) {
*** 2014,2024 **** } } { if (nBlocks_alive > 0) { ! printBox(ast, '-', "not_used/not_entrant age distribution. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL); STRINGSTREAM_FLUSH_LOCKED("") granules_per_line = 128; for (unsigned int ix = 0; ix < alloc_granules; ix++) { print_line_delim(out, ast, low_bound, ix, granules_per_line); --- 2037,2047 ---- } } { if (nBlocks_alive > 0) { ! printBox(ast, '-', "not_used/not_entrant/not_installed age distribution. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL); STRINGSTREAM_FLUSH_LOCKED("") granules_per_line = 128; for (unsigned int ix = 0; ix < alloc_granules; ix++) { print_line_delim(out, ast, low_bound, ix, granules_per_line);
*** 2144,2154 **** ast->fill_to(33); // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack. nmethod* nm = this_blob->as_nmethod_or_null(); Method* method = (nm == NULL) ? NULL : nm->method(); // may be uninitialized, i.e. != NULL, but invalid ! if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) && is_readable_pointer(method) && is_readable_pointer(method->constants())) { ResourceMark rm; //---< collect all data to locals as quickly as possible >--- unsigned int total_size = nm->total_size(); int hotness = nm->hotness_counter(); --- 2167,2177 ---- ast->fill_to(33); // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack. nmethod* nm = this_blob->as_nmethod_or_null(); Method* method = (nm == NULL) ? NULL : nm->method(); // may be uninitialized, i.e. != NULL, but invalid ! if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) && (cbType != nMethod_inconstruction) && is_readable_pointer(method) && is_readable_pointer(method->constants())) { ResourceMark rm; //---< collect all data to locals as quickly as possible >--- unsigned int total_size = nm->total_size(); int hotness = nm->hotness_counter();
*** 2356,2370 **** if (cb->is_method_handles_adapter_blob()) return mh_adapterBlob; if (cb->is_buffer_blob()) return bufferBlob; nmethod* nm = cb->as_nmethod_or_null(); if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb. if (nm->is_zombie()) return nMethod_dead; if (nm->is_unloaded()) return nMethod_unloaded; if (nm->is_alive() && !(nm->is_not_entrant())) return nMethod_notused; if (nm->is_alive()) return nMethod_alive; - if (nm->is_in_use()) return nMethod_inuse; return nMethod_dead; } } return noType; } --- 2379,2394 ---- if (cb->is_method_handles_adapter_blob()) return mh_adapterBlob; if (cb->is_buffer_blob()) return bufferBlob; nmethod* nm = cb->as_nmethod_or_null(); if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb. + if (nm->is_not_installed()) return nMethod_inconstruction; if (nm->is_zombie()) return nMethod_dead; if (nm->is_unloaded()) return nMethod_unloaded; + if (nm->is_in_use()) return nMethod_inuse; if (nm->is_alive() && !(nm->is_not_entrant())) return nMethod_notused; if (nm->is_alive()) return nMethod_alive; return nMethod_dead; } } return noType; }
< prev index next >