Ticket #187: profiler-memtracker.patch
File profiler-memtracker.patch, 7.7 KB (added by , 11 years ago) |
---|
-
trunk/source/ps/Profile.cpp
diff -Nur a/trunk/source/ps/Profile.cpp b/trunk/source/ps/Profile.cpp
a b 38 38 #endif 39 39 40 40 #include <numeric> 41 #include <map> 41 42 42 43 /////////////////////////////////////////////////////////////////////////////////////////////// 43 44 // CProfileNodeTable … … 83 84 columns.push_back(ProfileColumn("calls/turn", 80)); 84 85 columns.push_back(ProfileColumn("msec/turn", 80)); 85 86 columns.push_back(ProfileColumn("mallocs/turn", 80)); 87 columns.push_back(ProfileColumn("alloc'd mem", 80)); 86 88 } 87 89 }; 88 90 … … 160 162 double unlogged_time_turn = node->GetTurnTime(); 161 163 double unlogged_mallocs_frame = node->GetFrameMallocs(); 162 164 double unlogged_mallocs_turn = node->GetTurnMallocs(); 165 double unlogged_alloc_mem = node->GetAllocMem(); 163 166 CProfileNode::const_profile_iterator it; 164 167 165 168 for (it = node->GetChildren()->begin(); it != node->GetChildren()->end(); ++it) … … 168 171 unlogged_time_turn -= (*it)->GetTurnTime(); 169 172 unlogged_mallocs_frame -= (*it)->GetFrameMallocs(); 170 173 unlogged_mallocs_turn -= (*it)->GetTurnMallocs(); 174 unlogged_alloc_mem -= (*it)->GetAllocMem(); 171 175 } 172 176 for (it = node->GetScriptChildren()->begin(); it != node->GetScriptChildren()->end(); ++it) 173 177 { … … 175 179 unlogged_time_turn -= (*it)->GetTurnTime(); 176 180 unlogged_mallocs_frame -= (*it)->GetFrameMallocs(); 177 181 unlogged_mallocs_turn -= (*it)->GetTurnMallocs(); 182 unlogged_alloc_mem -= (*it)->GetAllocMem(); 178 183 } 179 184 180 185 // The root node can't easily count per-turn values (since Turn isn't called until … … 193 198 sprintf_s(buf, ARRAY_SIZE(buf), "%.3f", unlogged_time_turn * 1000.f); 194 199 else if (col == 6) 195 200 sprintf_s(buf, ARRAY_SIZE(buf), "%.1f", unlogged_mallocs_turn); 201 else if (col == 7) { 202 double d = unlogged_alloc_mem; 203 if (d >= 10.0 * 1024 * 1024) 204 sprintf_s(buf, ARRAY_SIZE(buf), "%.1f MiB", d / 1024.0 / 1024.0); 205 else if (d >= 10.0 * 1024) 206 sprintf_s(buf, ARRAY_SIZE(buf), "%.1f KiB", d / 1024.0); 207 else 208 sprintf_s(buf, ARRAY_SIZE(buf), "%.1f B", d); 209 } 196 210 197 211 return CStr(buf); 198 212 } … … 221 235 case 6: 222 236 sprintf_s(buf, ARRAY_SIZE(buf), "%.1f", child->GetTurnMallocs()); 223 237 break; 238 case 7: 239 { 240 double d = child->GetAllocMem(); 241 if (d >= 10.0 * 1024 * 1024) 242 sprintf_s(buf, ARRAY_SIZE(buf), "%.1f MiB", d / 1024.0 / 1024.0); 243 else if (d >= 10.0 * 1024) 244 sprintf_s(buf, ARRAY_SIZE(buf), "%.1f KiB", d / 1024.0); 245 else 246 sprintf_s(buf, ARRAY_SIZE(buf), "%.1f B", d); 247 break; 248 } 224 249 } 225 250 return CStr(buf); 226 251 } … … 264 289 name = _name; 265 290 recursion = 0; 266 291 292 pthread_mutex_init(&alloc_mem_mutex, NULL); 293 alloc_mem = 0; 294 267 295 Reset(); 268 296 269 297 parent = _parent; … … 280 308 delete( *it ); 281 309 282 310 delete display_table; 311 312 pthread_mutex_destroy(&alloc_mem_mutex); 283 313 } 284 314 285 315 template<typename T> … … 504 534 505 535 //#define ALLOC_DEBUG 506 536 537 std::map<void*, std::pair<CProfileNode*, size_t> > memtracker_map; 538 static pthread_mutex_t memtracker_map_mutex = PTHREAD_MUTEX_INITIALIZER; 539 540 static volatile pthread_t memtracker_access; 541 static volatile bool memtracker_access_valid = false; 542 static pthread_mutex_t memtracker_access_mutex = PTHREAD_MUTEX_INITIALIZER; 543 544 static volatile bool memtracker_enabled = false; 545 546 static void memtracker_enable(bool b) 547 { 548 memtracker_enabled = b; 549 if (!memtracker_enabled) { 550 debug_printf(L"Disabling breaks memory-tracking\n"); 551 pthread_mutex_lock(&memtracker_map_mutex); 552 memtracker_map.clear(); 553 pthread_mutex_unlock(&memtracker_map_mutex); 554 } 555 } 556 557 void memtracker_update(void *o, void *n, size_t s) 558 { 559 if (!memtracker_enabled) 560 return; 561 562 while (true) { 563 pthread_mutex_lock(&memtracker_access_mutex); 564 if (!memtracker_access_valid) { // noone here, register 565 memtracker_access = pthread_self(); 566 memtracker_access_valid = true; 567 pthread_mutex_unlock(&memtracker_access_mutex); 568 break; 569 } else if (pthread_equal(memtracker_access, pthread_self())) { // same thread, recursiv -> ignore 570 pthread_mutex_unlock(&memtracker_access_mutex); 571 return; 572 } else // other thread, spinlock 573 pthread_mutex_unlock(&memtracker_access_mutex); 574 } 575 576 pthread_mutex_lock(&memtracker_map_mutex); 577 if (o) { 578 if (memtracker_map.count(o)) { 579 memtracker_map[o].first->RemoveAllocMem(memtracker_map[o].second); 580 memtracker_map.erase(o); 581 } 582 } 583 if (n) { 584 if (CProfileManager::IsInitialised() && ThreadUtil::IsMainThread()) { 585 CProfileNode* node = CProfileManager::GetSingleton().GetCurrentWritable(); 586 if (node) { 587 memtracker_map[n] = std::pair<CProfileNode*, size_t>(node, s); 588 node->AddAllocMem(s); 589 } 590 } 591 } 592 pthread_mutex_unlock(&memtracker_map_mutex); 593 594 pthread_mutex_lock(&memtracker_access_mutex); 595 memtracker_access_valid = false; 596 pthread_mutex_unlock(&memtracker_access_mutex); 597 } 598 507 599 void* malloc(size_t sz) 508 600 { 509 601 cpu_AtomicAdd(&alloc_count, 1); … … 518 610 #ifdef ALLOC_DEBUG 519 611 printf("### malloc(%d) = %p\n", sz, ret); 520 612 #endif 613 614 memtracker_update(0, ret, sz); 615 521 616 return ret; 522 617 } 523 618 … … 535 630 #ifdef ALLOC_DEBUG 536 631 printf("### realloc(%p, %d) = %p\n", ptr, sz, ret); 537 632 #endif 633 634 memtracker_update(ptr, ret, sz); 635 538 636 return ret; 539 637 } 540 638 … … 561 659 #ifdef ALLOC_DEBUG 562 660 printf("### calloc(%d, %d) = %p\n", nm, sz, ret); 563 661 #endif 662 663 memtracker_update(0, ret, sz*nm); 664 564 665 return ret; 565 666 } 566 667 … … 577 678 #ifdef ALLOC_DEBUG 578 679 printf("### free(%p)\n", ptr); 579 680 #endif 681 682 memtracker_update(ptr, 0, 0); 580 683 } 581 684 582 685 static void alloc_hook_initialize() … … 626 729 return true; 627 730 } 628 731 732 double CProfileNode::GetAllocMem() 733 { 734 pthread_mutex_lock(&alloc_mem_mutex); 735 long tmp = alloc_mem; 736 pthread_mutex_unlock(&alloc_mem_mutex); 737 738 std::vector<CProfileNode*>::const_iterator it; 739 for (it = children.begin(); it != children.end(); ++it ) 740 tmp += (*it)->GetAllocMem(); 741 for (it = script_children.begin(); it != script_children.end(); ++it ) 742 tmp += (*it)->GetAllocMem(); 743 744 return tmp; 745 } 746 629 747 CProfileManager::CProfileManager() : 630 748 root(NULL), current(NULL), needs_structural_reset(false) 631 749 { … … 634 752 635 753 CProfileManager::~CProfileManager() 636 754 { 755 #if defined(USE_GLIBC_MALLOC_OVERRIDE) 756 memtracker_enable(false); 757 #endif 637 758 delete root; 638 759 } 639 760 … … 698 819 699 820 void CProfileManager::PerformStructuralReset() 700 821 { 822 #if defined(USE_GLIBC_MALLOC_OVERRIDE) 823 memtracker_enable(false); 824 #endif 701 825 delete root; 702 826 root = new CProfileNode("root", NULL); 703 827 root->Call(); 704 828 current = root; 705 829 g_ProfileViewer.AddRootTable(root->display_table, true); 830 #if defined(USE_GLIBC_MALLOC_OVERRIDE) 831 memtracker_enable(true); 832 #endif 706 833 } -
trunk/source/ps/Profile.h
diff -Nur a/trunk/source/ps/Profile.h b/trunk/source/ps/Profile.h
a b 65 65 double start; 66 66 long start_mallocs; 67 67 int recursion; 68 long alloc_mem; 69 70 pthread_mutex_t alloc_mem_mutex; 68 71 69 72 CProfileNode* parent; 70 73 std::vector<CProfileNode*> children; … … 86 89 double GetTurnTime() const; 87 90 double GetFrameMallocs() const; 88 91 double GetTurnMallocs() const; 92 double GetAllocMem(); 93 94 void RemoveAllocMem(size_t s) { pthread_mutex_lock(&alloc_mem_mutex); alloc_mem -= s; pthread_mutex_unlock(&alloc_mem_mutex); } 95 void AddAllocMem(size_t s) { pthread_mutex_lock(&alloc_mem_mutex); alloc_mem += s; pthread_mutex_unlock(&alloc_mem_mutex); } 89 96 90 97 const CProfileNode* GetChild( const char* name ) const; 91 98 const CProfileNode* GetScriptChild( const char* name ) const; … … 141 148 void StructuralReset(); 142 149 143 150 inline const CProfileNode* GetCurrent() { return( current ); } 151 inline CProfileNode* GetCurrentWritable() { return( current ); } 144 152 inline const CProfileNode* GetRoot() { return( root ); } 145 153 }; 146 154