diff --git a/matrix-wechat.podspec b/matrix-wechat.podspec index 20104e529..133471935 100644 --- a/matrix-wechat.podspec +++ b/matrix-wechat.podspec @@ -7,7 +7,7 @@ Pod::Spec.new do |matrix| matrix.name = 'matrix-wechat' - matrix.version = '0.6.7' + matrix.version = '1.0.1' matrix.summary = 'Matrix for iOS/macOS is a performance probe tool developed and used by WeChat.' matrix.description = <<-DESC Matrix for iOS/macOS is a performance probe tool developed and used by WeChat. @@ -21,10 +21,10 @@ Pod::Spec.new do |matrix| matrix.homepage = 'https://github.com/Tencent/matrix' matrix.license = { :type => 'BSD', :file => 'LICENSE' } matrix.author = { 'johnzjchen' => 'johnzjchen@tencent.com' } - matrix.source = { :git => 'https://github.com/Tencent/matrix.git', :branch => "feature/ios-matrix-cocopods-0.6.7" } + matrix.source = { :git => 'https://github.com/Tencent/matrix.git', :branch => "feature/ios-matrix-cocopods-1.0.1" } matrix.module_name = "Matrix" - matrix.ios.deployment_target = '10.0' + matrix.ios.deployment_target = '9.0' matrix.osx.deployment_target = "10.10" matrix.libraries = "z", "c++" matrix.frameworks = "CoreFoundation", "Foundation" diff --git a/matrix/matrix-iOS/Matrix/Matrix.xcodeproj/project.pbxproj b/matrix/matrix-iOS/Matrix/Matrix.xcodeproj/project.pbxproj index 78223639f..c6749163a 100644 --- a/matrix/matrix-iOS/Matrix/Matrix.xcodeproj/project.pbxproj +++ b/matrix/matrix-iOS/Matrix/Matrix.xcodeproj/project.pbxproj @@ -206,7 +206,6 @@ B9620E0825F238F900CD8AD7 /* splay_map.h in Headers */ = {isa = PBXBuildFile; fileRef = B9620E0425F238F900CD8AD7 /* splay_map.h */; }; B9620E0925F238F900CD8AD7 /* buffer_source.h in Headers */ = {isa = PBXBuildFile; fileRef = B9620E0525F238F900CD8AD7 /* buffer_source.h */; }; B9620E1825F2393A00CD8AD7 /* allocation_event_db_old.h in Headers */ = {isa = PBXBuildFile; fileRef = B9620E0D25F2393A00CD8AD7 /* allocation_event_db_old.h */; }; - B9620E1925F2393A00CD8AD7 /* memory_logging_event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B9620E0E25F2393A00CD8AD7 /* memory_logging_event.cpp */; }; B9620E1A25F2393A00CD8AD7 /* memory_logging_event_buffer_pool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B9620E0F25F2393A00CD8AD7 /* memory_logging_event_buffer_pool.cpp */; }; B9620E1B25F2393A00CD8AD7 /* memory_logging_event_buffer_list.h in Headers */ = {isa = PBXBuildFile; fileRef = B9620E1025F2393A00CD8AD7 /* memory_logging_event_buffer_list.h */; }; B9620E1C25F2393A00CD8AD7 /* memory_logging_event_buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B9620E1125F2393A00CD8AD7 /* memory_logging_event_buffer.cpp */; }; @@ -492,7 +491,6 @@ B9620E0425F238F900CD8AD7 /* splay_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = splay_map.h; sourceTree = ""; }; B9620E0525F238F900CD8AD7 /* buffer_source.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffer_source.h; sourceTree = ""; }; B9620E0D25F2393A00CD8AD7 /* allocation_event_db_old.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = allocation_event_db_old.h; sourceTree = ""; }; - B9620E0E25F2393A00CD8AD7 /* memory_logging_event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memory_logging_event.cpp; sourceTree = ""; }; B9620E0F25F2393A00CD8AD7 /* memory_logging_event_buffer_pool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memory_logging_event_buffer_pool.cpp; sourceTree = ""; }; B9620E1025F2393A00CD8AD7 /* memory_logging_event_buffer_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_logging_event_buffer_list.h; sourceTree = ""; }; B9620E1125F2393A00CD8AD7 /* memory_logging_event_buffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memory_logging_event_buffer.cpp; sourceTree = ""; }; @@ -1134,7 +1132,6 @@ B9620E1325F2393A00CD8AD7 /* memory_logging_event_buffer_pool.h */, B9620E0F25F2393A00CD8AD7 /* memory_logging_event_buffer_pool.cpp */, B9620E1525F2393A00CD8AD7 /* memory_logging_event.h */, - B9620E0E25F2393A00CD8AD7 /* memory_logging_event.cpp */, 116834C722538BB500D6ED61 /* nsobject_hook_method.h */, 116834C822538BB500D6ED61 /* nsobject_hook_method.mm */, BB77ACC722368582008C67D9 /* nsobject_hook.h */, @@ -1475,7 +1472,6 @@ 1127770325ECD92E00F7A6E4 /* KSCrash_BinaryImageHandler.mm in Sources */, BB77AD1E22368582008C67D9 /* nsobject_hook.mm in Sources */, 116460B82111AF190069B5DE /* KSStackCursor_MachineContext.c in Sources */, - B9620E1925F2393A00CD8AD7 /* memory_logging_event.cpp in Sources */, 116460B92111AF190069B5DE /* KSCrashMonitor_Zombie.c in Sources */, 116460BA2111AF190069B5DE /* KSDynamicLinker.c in Sources */, B9620E2225F2393A00CD8AD7 /* allocation_event_db_old.cpp in Sources */, @@ -1613,7 +1609,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -1672,7 +1668,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = NO; VALIDATE_PRODUCT = YES; diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event.h index d6ce3aecd..bf5f0e124 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event.h @@ -20,19 +20,16 @@ #include struct allocation_event { - //uint64_t address; // top 8 bits are actually the flags - uint16_t alloca_type; // allocation type, such as memory_logging_type_alloc or memory_logging_type_vm_allocate - uint16_t object_type; // object type, such as NSObject, NSData, CFString, etc... uint32_t stack_identifier; uint32_t size; - uint32_t t_id; + uint32_t object_type; // object type, such as NSObject, NSData, CFString, etc... + uint32_t alloca_type; // allocation type, such as memory_logging_type_alloc or memory_logging_type_vm_allocate - allocation_event(uint16_t _at = 0, uint16_t _ot = 0, uint32_t _si = 0, uint32_t _sz = 0, uint32_t _id = 0) { + allocation_event(uint32_t _at = 0, uint32_t _ot = 0, uint32_t _si = 0, uint32_t _sz = 0) { alloca_type = _at; object_type = _ot; stack_identifier = _si; size = _sz; - t_id = _id; } }; diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db.cpp index 6b5967038..8abe04a3f 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db.cpp @@ -16,79 +16,83 @@ #include "allocation_event_db.h" #include "buffer_source.h" +#include "splay_map_simple_key.h" + +#ifdef ADDRESS_64 #pragma mark - #pragma mark Types -#define ADDRESS_HASH16_LV0_BITS 20 -#define ADDRESS_HASH16_LV1_BITS 12 +#define ADDRESS_HASH_LV0_BITS 20 +#define ADDRESS_HASH_LV1_BITS 12 -#define ADDRESS_HASH16_LV0_SIZE (1 << ADDRESS_HASH16_LV0_BITS) -#define ADDRESS_HASH16_LV1_SIZE (1 << ADDRESS_HASH16_LV1_BITS) +#define ADDRESS_HASH_LV0_SIZE (1 << ADDRESS_HASH_LV0_BITS) +#define ADDRESS_HASH_LV1_SIZE (1 << ADDRESS_HASH_LV1_BITS) -struct address_hash16 { +// memory address is range of 0 ~ 2^36 +struct address_hash { union { uint64_t address; struct { uint64_t reserve : 4; - uint64_t lv1 : ADDRESS_HASH16_LV1_BITS; - uint64_t lv0 : ADDRESS_HASH16_LV0_BITS; - uint64_t space : 28; - } detail; - }; -}; - -#define ADDRESS_HASH32_LV0_BITS 19 -#define ADDRESS_HASH32_LV1_BITS 12 - -#define ADDRESS_HASH32_LV0_SIZE (1 << ADDRESS_HASH32_LV0_BITS) -#define ADDRESS_HASH32_LV1_SIZE (1 << ADDRESS_HASH32_LV1_BITS) - -struct address_hash32 { - union { - uint64_t address; - - struct { - uint64_t reserve : 5; - uint64_t lv1 : ADDRESS_HASH32_LV1_BITS; - uint64_t lv0 : ADDRESS_HASH32_LV0_BITS; + uint64_t lv1 : ADDRESS_HASH_LV1_BITS; + uint64_t lv0 : ADDRESS_HASH_LV0_BITS; uint64_t space : 28; } detail; }; }; struct allocation_event_db { - uint32_t *key_hash16[ADDRESS_HASH16_LV0_SIZE]; - uint32_t *key_hash32[ADDRESS_HASH32_LV0_SIZE]; - memory_pool_file *key_buffer_source; + // tiny size(<= 512) event + uint32_t key_hash[ADDRESS_HASH_LV0_SIZE]; + memory_pool_file *key_buffer_source0; - uint32_t val_free_index; +#ifdef DEBUG uint32_t val_count; - uint32_t val_max_count; - allocation_event *val_buffer; - buffer_source *val_buffer_source; +#endif + allocation_event *val_free_ptr; + allocation_event *val_page_curr; + allocation_event *val_page_end; + memory_pool_file *val_buffer_source0; + + // other size event + buffer_source *key_buffer_source1; + buffer_source *val_buffer_source1; + splay_map_simple_key *allocation_event_list; }; -static_assert(sizeof(address_hash16) == sizeof(uint64_t), "Not aligned!"); -static_assert(sizeof(address_hash32) == sizeof(uint64_t), "Not aligned!"); +#define EXPAND_KEY_POINTER(p) ((uint32_t *)((uintptr_t)p << 14)) +#define EXPAND_VAL_POINTER(p) ((allocation_event *)((uintptr_t)p << 4)) +#define VAL_ALLOC_COUNT (1 << 16) + +static_assert(sizeof(address_hash) == sizeof(uint64_t), "Not aligned!"); +static_assert(sizeof(allocation_event) == (1 << 4), "Not aligned!"); #pragma mark - #pragma mark Public Interface allocation_event_db *allocation_event_db_open_or_create(const char *event_dir) { allocation_event_db *db_context = (allocation_event_db *)inter_calloc(1, sizeof(allocation_event_db)); - db_context->key_buffer_source = new memory_pool_file(event_dir, "allocation_events_key.dat"); - db_context->val_buffer_source = new buffer_source_file(event_dir, "allocation_events_val.dat"); + db_context->key_buffer_source0 = new memory_pool_file(event_dir, "allocation_events_key0.dat"); + db_context->val_buffer_source0 = new memory_pool_file(event_dir, "allocation_events_val0.dat"); - if (db_context->key_buffer_source->init_fail() || db_context->val_buffer_source->init_fail()) { + if (db_context->key_buffer_source0->init_fail() || db_context->val_buffer_source0->init_fail()) { // should not be happened err_code = MS_ERRC_AE_FILE_OPEN_FAIL; goto init_fail; } - db_context->val_buffer = (allocation_event *)db_context->val_buffer_source->buffer(); - db_context->val_max_count = (uint32_t)(db_context->val_buffer_source->buffer_size() / sizeof(allocation_event)); + db_context->key_buffer_source1 = new buffer_source_file(event_dir, "allocation_events_key1.dat"); + db_context->val_buffer_source1 = new buffer_source_file(event_dir, "allocation_events_val1.dat"); + if (db_context->key_buffer_source1->init_fail() || db_context->val_buffer_source1->init_fail()) { + // should not be happened + err_code = MS_ERRC_AE_FILE_OPEN_FAIL; + goto init_fail; + } + + db_context->allocation_event_list = + new splay_map_simple_key(VAL_ALLOC_COUNT, db_context->key_buffer_source1, db_context->val_buffer_source1); return db_context; @@ -102,195 +106,539 @@ void allocation_event_db_close(allocation_event_db *db_context) { return; } - for (int i = 0; i < ADDRESS_HASH16_LV0_SIZE; ++i) { - db_context->key_buffer_source->free(db_context->key_hash16[i], ADDRESS_HASH16_LV1_SIZE * sizeof(uint32_t)); + for (int i = 0; i < ADDRESS_HASH_LV0_SIZE; ++i) { + db_context->key_buffer_source0->free(EXPAND_KEY_POINTER(db_context->key_hash[i]), ADDRESS_HASH_LV1_SIZE * sizeof(uint32_t)); } - for (int i = 0; i < ADDRESS_HASH32_LV0_SIZE; ++i) { - db_context->key_buffer_source->free(db_context->key_hash32[i], ADDRESS_HASH32_LV1_SIZE * sizeof(uint32_t)); - } + delete db_context->key_buffer_source0; + delete db_context->val_buffer_source0; + + delete db_context->allocation_event_list; + delete db_context->key_buffer_source1; + delete db_context->val_buffer_source1; - delete db_context->key_buffer_source; - delete db_context->val_buffer_source; inter_free(db_context); } -void allocation_event_db_realloc_val(allocation_event_db *db_context) { - uint32_t malloc_size = (db_context->val_max_count + 102400) * sizeof(allocation_event); - void *new_buff = db_context->val_buffer_source->realloc(malloc_size); +bool allocation_event_db_realloc_val(allocation_event_db *db_context) { + uint32_t malloc_size = VAL_ALLOC_COUNT * sizeof(allocation_event); + void *new_buff = db_context->val_buffer_source0->malloc(malloc_size); if (new_buff) { - memset((char *)new_buff + db_context->val_max_count * sizeof(allocation_event), 0, 102400 * sizeof(allocation_event)); - db_context->val_buffer = (allocation_event *)new_buff; - db_context->val_max_count += 102400; + memset(new_buff, 0, malloc_size); + db_context->val_page_curr = (allocation_event *)new_buff; + db_context->val_page_end = (allocation_event *)((uintptr_t)new_buff + malloc_size); + return true; + } else { + return false; } } -void allocation_event_db_free_val(allocation_event_db *db_context, uint32_t index) { - db_context->val_buffer[index].size = db_context->val_free_index; - db_context->val_buffer[index].alloca_type = memory_logging_type_free; - db_context->val_free_index = index; +void allocation_event_db_free_val(allocation_event_db *db_context, allocation_event *free_ptr) { +#ifdef DEBUG + db_context->val_count--; +#endif + free_ptr->alloca_type = memory_logging_type_free; + *((allocation_event **)free_ptr) = db_context->val_free_ptr; + db_context->val_free_ptr = free_ptr; } -uint32_t allocation_event_db_new_val(allocation_event_db *db_context) { - uint32_t next_index = db_context->val_free_index; - if (next_index == 0) { - next_index = ++db_context->val_count; - if (next_index >= db_context->val_max_count) { - allocation_event_db_realloc_val(db_context); +allocation_event *allocation_event_db_new_val(allocation_event_db *db_context) { +#ifdef DEBUG + db_context->val_count++; +#endif + allocation_event *new_ptr = db_context->val_free_ptr; + if (new_ptr == NULL) { + new_ptr = db_context->val_page_curr; + if (new_ptr == db_context->val_page_end) { + if (allocation_event_db_realloc_val(db_context) == false) { + static allocation_event s_empty; +#ifdef DEBUG + --db_context->val_count; +#endif + return &s_empty; + } + new_ptr = db_context->val_page_curr; } + db_context->val_page_curr++; } else { - db_context->val_free_index = db_context->val_buffer[next_index].size; + db_context->val_free_ptr = *((allocation_event **)db_context->val_free_ptr); } - return next_index; + return new_ptr; } -void allocation_event_db_add16(allocation_event_db *db_context, - uint64_t address, - uint32_t type_flags, - uint32_t object_type, - uint32_t size, - uint32_t stack_identifier, - uint32_t t_id) { - address_hash16 ai = { .address = address }; +void __allocation_event_db_add( +allocation_event_db *db_context, uint64_t address, uint32_t type_flags, uint32_t object_type, uint32_t size, uint32_t stack_identifier) { + address_hash ai = { .address = address }; uint32_t lv0 = ai.detail.lv0; uint32_t lv1 = ai.detail.lv1; - if (db_context->key_hash16[lv0] == NULL) { - uint32_t *new_buffer = (uint32_t *)db_context->key_buffer_source->malloc(ADDRESS_HASH16_LV1_SIZE * sizeof(uint32_t)); - memset(new_buffer, 0, ADDRESS_HASH16_LV1_SIZE * sizeof(uint32_t)); - db_context->key_hash16[lv0] = new_buffer; + uint32_t lv0_index = db_context->key_hash[lv0]; + if (lv0_index == 0) { + uint32_t *new_buffer = (uint32_t *)db_context->key_buffer_source0->malloc(ADDRESS_HASH_LV1_SIZE * sizeof(uint32_t)); + if (new_buffer == NULL) { + return; + } + memset(new_buffer, 0, ADDRESS_HASH_LV1_SIZE * sizeof(uint32_t)); + // Note: Large memory allocations are guaranteed to be page-aligned + lv0_index = (uint32_t)((uintptr_t)new_buffer >> 14); + db_context->key_hash[lv0] = lv0_index; } - uint32_t old_index = db_context->key_hash16[lv0][lv1]; - if (old_index == 0) { - uint32_t new_val_index = allocation_event_db_new_val(db_context); - db_context->key_hash16[lv0][lv1] = new_val_index; - db_context->val_buffer[new_val_index] = allocation_event(type_flags, object_type, stack_identifier, size, t_id); + uint32_t *lv0_ptr = EXPAND_KEY_POINTER(lv0_index); + uint32_t val_index = lv0_ptr[lv1]; + if (val_index == 0) { + allocation_event *new_val = allocation_event_db_new_val(db_context); + *new_val = allocation_event(type_flags, object_type, stack_identifier, size); + lv0_ptr[lv1] = (uint32_t)((uintptr_t)new_val >> 4); } else { - db_context->val_buffer[old_index] = allocation_event(type_flags, object_type, stack_identifier, size, t_id); + allocation_event *old_val = EXPAND_VAL_POINTER(val_index); + *old_val = allocation_event(type_flags, object_type, stack_identifier, size); } } -void allocation_event_db_add32(allocation_event_db *db_context, - uint64_t address, - uint32_t type_flags, - uint32_t object_type, - uint32_t size, - uint32_t stack_identifier, - uint32_t t_id) { - address_hash32 ai = { .address = address }; +void allocation_event_db_add( +allocation_event_db *db_context, uint64_t address, uint32_t type_flags, uint32_t object_type, uint32_t size, uint32_t stack_identifier) { + if ((type_flags & memory_logging_type_alloc) && /*(address & 0x1f) == 0 && */ size <= 128) { + __allocation_event_db_add(db_context, address, type_flags, object_type, size, stack_identifier); + } else { + db_context->allocation_event_list->insert(address, allocation_event(type_flags, object_type, stack_identifier, size)); + } +} + +bool __allocation_event_db_del(allocation_event_db *db_context, uint64_t address) { + address_hash ai = { .address = address }; uint32_t lv0 = ai.detail.lv0; - uint32_t lv1 = ai.detail.lv1; + uint32_t lv0_index = db_context->key_hash[lv0]; + + if (lv0_index) { + uint32_t lv1 = ai.detail.lv1; + uint32_t *lv0_ptr = EXPAND_KEY_POINTER(lv0_index); + uint32_t val_index = lv0_ptr[lv1]; + if (val_index) { + allocation_event_db_free_val(db_context, EXPAND_VAL_POINTER(val_index)); + lv0_ptr[lv1] = 0; + return true; + } + } + return false; +} + +void allocation_event_db_del(allocation_event_db *db_context, uint64_t address, uint32_t type_flags) { + if ((type_flags & memory_logging_type_dealloc) /* && (address & 0x1f) == 0*/) { + if (__allocation_event_db_del(db_context, address)) { + return; + } + } + db_context->allocation_event_list->remove(address); +} + +bool __allocation_event_db_update_object_type(allocation_event_db *db_context, uint64_t address, uint32_t new_type) { + address_hash ai = { .address = address }; + uint32_t lv0 = ai.detail.lv0; + uint32_t lv0_index = db_context->key_hash[lv0]; + + if (lv0_index) { + uint32_t lv1 = ai.detail.lv1; + uint32_t *lv0_ptr = EXPAND_KEY_POINTER(lv0_index); + uint32_t val_index = lv0_ptr[lv1]; + if (val_index) { + allocation_event *old_val = EXPAND_VAL_POINTER(val_index); + old_val->object_type = new_type; + return true; + } + } + return false; +} + +void allocation_event_db_update_object_type(allocation_event_db *db_context, uint64_t address, uint32_t new_type) { + if (__allocation_event_db_update_object_type(db_context, address, new_type)) { + return; + } + if (db_context->allocation_event_list->exist(address)) { + db_context->allocation_event_list->find().object_type = new_type; + } +} + +bool __allocation_event_db_update_object_type_and_stack_identifier(allocation_event_db *db_context, + uint64_t address, + uint32_t new_type, + uint32_t stack_identifier) { + address_hash ai = { .address = address }; + uint32_t lv0 = ai.detail.lv0; + uint32_t lv0_index = db_context->key_hash[lv0]; + + if (lv0_index) { + uint32_t lv1 = ai.detail.lv1; + uint32_t *lv0_ptr = EXPAND_KEY_POINTER(lv0_index); + uint32_t val_index = lv0_ptr[lv1]; + if (val_index) { + allocation_event *old_val = EXPAND_VAL_POINTER(val_index); + old_val->object_type = new_type; + old_val->stack_identifier = stack_identifier; + return true; + } + } + return false; +} + +void allocation_event_db_update_object_type_and_stack_identifier(allocation_event_db *db_context, + uint64_t address, + uint32_t new_type, + uint32_t stack_identifier) { + if (__allocation_event_db_update_object_type_and_stack_identifier(db_context, address, new_type, stack_identifier)) { + return; + } + if (db_context->allocation_event_list->exist(address)) { + db_context->allocation_event_list->find().object_type = new_type; + db_context->allocation_event_list->find().stack_identifier = stack_identifier; + } +} + +void allocation_event_db_enumerate(allocation_event_db *db_context, void (^callback)(const uint64_t &address, const allocation_event &event)) { + if (db_context == NULL) { + return; + } + + size_t offset = 0; + while (offset < db_context->val_buffer_source0->fs()) { + size_t read_size = VAL_ALLOC_COUNT * sizeof(allocation_event); + + void *map_mem = inter_mmap(NULL, read_size, PROT_READ, MAP_SHARED, db_context->val_buffer_source0->fd(), offset); + if (map_mem == MAP_FAILED) { + continue; + } + + allocation_event *val_buffer = (allocation_event *)map_mem; + for (int i = 0; i < VAL_ALLOC_COUNT; ++i) { + const allocation_event &event = val_buffer[i]; + if (event.alloca_type != memory_logging_type_free) { + callback(1, event); + } + } + + inter_munmap(map_mem, read_size); + + offset += read_size; + } + + db_context->allocation_event_list->enumerate(callback); +} + +#else + +#pragma mark - +#pragma mark Types + +#define ADDRESS_HASH_LV0_BITS 20 +#define ADDRESS_HASH_LV1_BITS 12 + +#define ADDRESS_HASH_LV0_SIZE (1 << ADDRESS_HASH_LV0_BITS) +#define ADDRESS_HASH_LV1_SIZE (1 << ADDRESS_HASH_LV1_BITS) + +// memory address is range of 0 ~ 2^36 +struct address_hash { + union { + uint32_t address; - if (db_context->key_hash32[lv0] == NULL) { - uint32_t *new_buffer = (uint32_t *)db_context->key_buffer_source->malloc(ADDRESS_HASH32_LV1_SIZE * sizeof(uint32_t)); - memset(new_buffer, 0, ADDRESS_HASH32_LV1_SIZE * sizeof(uint32_t)); - db_context->key_hash32[lv0] = new_buffer; + struct { + //uint64_t reserve : 4; + uint32_t lv1 : ADDRESS_HASH_LV1_BITS; + uint32_t lv0 : ADDRESS_HASH_LV0_BITS; + //uint64_t space : 28; + } detail; + }; +}; + +struct allocation_event_db { + // tiny size(<= 512) event + uint32_t key_hash[ADDRESS_HASH_LV0_SIZE]; + memory_pool_file *key_buffer_source0; + +#ifdef DEBUG + uint32_t val_count; +#endif + allocation_event *val_free_ptr; + allocation_event *val_page_curr; + allocation_event *val_page_end; + memory_pool_file *val_buffer_source0; + + // other size event + buffer_source *key_buffer_source1; + buffer_source *val_buffer_source1; + splay_map_simple_key *allocation_event_list; +}; + +#define EXPAND_KEY_POINTER(p) ((uint32_t *)((uintptr_t)p << 14)) +#define EXPAND_VAL_POINTER(p) ((allocation_event *)((uintptr_t)p << 4)) +#define VAL_ALLOC_COUNT (1 << 16) + +static_assert(sizeof(address_hash) == sizeof(uint32_t), "Not aligned!"); +static_assert(sizeof(allocation_event) == (1 << 4), "Not aligned!"); + +#pragma mark - +#pragma mark Public Interface + +allocation_event_db *allocation_event_db_open_or_create(const char *event_dir) { + allocation_event_db *db_context = (allocation_event_db *)inter_calloc(1, sizeof(allocation_event_db)); + db_context->key_buffer_source0 = new memory_pool_file(event_dir, "allocation_events_key220.dat"); + db_context->val_buffer_source0 = new memory_pool_file(event_dir, "allocation_events_val220.dat"); + + if (db_context->key_buffer_source0->init_fail() || db_context->val_buffer_source0->init_fail()) { + // should not be happened + err_code = MS_ERRC_AE_FILE_OPEN_FAIL; + goto init_fail; } - uint32_t old_index = db_context->key_hash32[lv0][lv1]; - if (old_index == 0) { - uint32_t new_val_index = allocation_event_db_new_val(db_context); - db_context->key_hash32[lv0][lv1] = new_val_index; - db_context->val_buffer[new_val_index] = allocation_event(type_flags, object_type, stack_identifier, size, t_id); + db_context->key_buffer_source1 = new buffer_source_file(event_dir, "allocation_events_key221.dat"); + db_context->val_buffer_source1 = new buffer_source_file(event_dir, "allocation_events_val221.dat"); + if (db_context->key_buffer_source1->init_fail() || db_context->val_buffer_source1->init_fail()) { + // should not be happened + err_code = MS_ERRC_AE_FILE_OPEN_FAIL; + goto init_fail; + } + + db_context->allocation_event_list = + new splay_map_simple_key(VAL_ALLOC_COUNT, db_context->key_buffer_source1, db_context->val_buffer_source1); + + return db_context; + +init_fail: + allocation_event_db_close(db_context); + return NULL; +} + +void allocation_event_db_close(allocation_event_db *db_context) { + if (db_context == NULL) { + return; + } + + for (int i = 0; i < ADDRESS_HASH_LV0_SIZE; ++i) { + db_context->key_buffer_source0->free(EXPAND_KEY_POINTER(db_context->key_hash[i]), ADDRESS_HASH_LV1_SIZE * sizeof(uint32_t)); + } + + delete db_context->key_buffer_source0; + delete db_context->val_buffer_source0; + + delete db_context->allocation_event_list; + delete db_context->key_buffer_source1; + delete db_context->val_buffer_source1; + + inter_free(db_context); +} + +bool allocation_event_db_realloc_val(allocation_event_db *db_context) { + uint32_t malloc_size = VAL_ALLOC_COUNT * sizeof(allocation_event); + void *new_buff = db_context->val_buffer_source0->malloc(malloc_size); + if (new_buff) { + memset(new_buff, 0, malloc_size); + db_context->val_page_curr = (allocation_event *)new_buff; + db_context->val_page_end = (allocation_event *)((uintptr_t)new_buff + malloc_size); + return true; } else { - db_context->val_buffer[old_index] = allocation_event(type_flags, object_type, stack_identifier, size, t_id); + return false; } } -void allocation_event_db_add(allocation_event_db *db_context, - uint64_t address, - uint32_t type_flags, - uint32_t object_type, - uint32_t size, - uint32_t stack_identifier, - uint32_t t_id) { - if ((address & 0x1f) == 0) { - allocation_event_db_add32(db_context, address, type_flags, object_type, size, stack_identifier, t_id); +void allocation_event_db_free_val(allocation_event_db *db_context, allocation_event *free_ptr) { +#ifdef DEBUG + db_context->val_count--; +#endif + free_ptr->alloca_type = memory_logging_type_free; + *((allocation_event **)free_ptr) = db_context->val_free_ptr; + db_context->val_free_ptr = free_ptr; +} + +allocation_event *allocation_event_db_new_val(allocation_event_db *db_context) { +#ifdef DEBUG + db_context->val_count++; +#endif + allocation_event *new_ptr = db_context->val_free_ptr; + if (new_ptr == NULL) { + new_ptr = db_context->val_page_curr; + if (new_ptr == db_context->val_page_end) { + if (allocation_event_db_realloc_val(db_context) == false) { + static allocation_event s_empty; +#ifdef DEBUG + --db_context->val_count; +#endif + return &s_empty; + } + new_ptr = db_context->val_page_curr; + } + db_context->val_page_curr++; } else { - allocation_event_db_add16(db_context, address, type_flags, object_type, size, stack_identifier, t_id); + db_context->val_free_ptr = *((allocation_event **)db_context->val_free_ptr); } + return new_ptr; } -void allocation_event_db_del16(allocation_event_db *db_context, uint64_t address, uint32_t type_flags) { - address_hash16 ai = { .address = address }; +void __allocation_event_db_add( +allocation_event_db *db_context, uint32_t address, uint32_t type_flags, uint32_t object_type, uint32_t size, uint32_t stack_identifier) { + address_hash ai = { .address = address }; uint32_t lv0 = ai.detail.lv0; uint32_t lv1 = ai.detail.lv1; - if (db_context->key_hash16[lv0]) { - uint32_t val_index = db_context->key_hash16[lv0][lv1]; - if (val_index) { - allocation_event_db_free_val(db_context, val_index); - db_context->key_hash16[lv0][lv1] = 0; + uint32_t lv0_index = db_context->key_hash[lv0]; + if (lv0_index == 0) { + uint32_t *new_buffer = (uint32_t *)db_context->key_buffer_source0->malloc(ADDRESS_HASH_LV1_SIZE * sizeof(uint32_t)); + if (new_buffer == NULL) { + return; } + memset(new_buffer, 0, ADDRESS_HASH_LV1_SIZE * sizeof(uint32_t)); + // Note: Large memory allocations are guaranteed to be page-aligned + lv0_index = (uint32_t)((uintptr_t)new_buffer >> 14); + db_context->key_hash[lv0] = lv0_index; + } + + uint32_t *lv0_ptr = EXPAND_KEY_POINTER(lv0_index); + uint32_t val_index = lv0_ptr[lv1]; + if (val_index == 0) { + allocation_event *new_val = allocation_event_db_new_val(db_context); + *new_val = allocation_event(type_flags, object_type, stack_identifier, size); + lv0_ptr[lv1] = (uint32_t)((uintptr_t)new_val >> 4); + } else { + allocation_event *old_val = EXPAND_VAL_POINTER(val_index); + *old_val = allocation_event(type_flags, object_type, stack_identifier, size); } } -void allocation_event_db_del32(allocation_event_db *db_context, uint64_t address, uint32_t type_flags) { - address_hash32 ai = { .address = address }; +void allocation_event_db_add( +allocation_event_db *db_context, uint64_t address, uint32_t type_flags, uint32_t object_type, uint32_t size, uint32_t stack_identifier) { + uint32_t new_address = (uint32_t)(address >> 4); + + if ((type_flags & memory_logging_type_alloc) && /*(address & 0x1f) == 0 && */ size <= 128) { + __allocation_event_db_add(db_context, new_address, type_flags, object_type, size, stack_identifier); + } else { + db_context->allocation_event_list->insert(new_address, allocation_event(type_flags, object_type, stack_identifier, size)); + } +} + +bool __allocation_event_db_del(allocation_event_db *db_context, uint32_t address) { + address_hash ai = { .address = address }; uint32_t lv0 = ai.detail.lv0; - uint32_t lv1 = ai.detail.lv1; + uint32_t lv0_index = db_context->key_hash[lv0]; - if (db_context->key_hash32[lv0]) { - uint32_t val_index = db_context->key_hash32[lv0][lv1]; + if (lv0_index) { + uint32_t lv1 = ai.detail.lv1; + uint32_t *lv0_ptr = EXPAND_KEY_POINTER(lv0_index); + uint32_t val_index = lv0_ptr[lv1]; if (val_index) { - allocation_event_db_free_val(db_context, val_index); - db_context->key_hash32[lv0][lv1] = 0; + allocation_event_db_free_val(db_context, EXPAND_VAL_POINTER(val_index)); + lv0_ptr[lv1] = 0; + return true; } } + return false; } void allocation_event_db_del(allocation_event_db *db_context, uint64_t address, uint32_t type_flags) { - if ((address & 0x1f) == 0) { - allocation_event_db_del32(db_context, address, type_flags); - } else { - allocation_event_db_del16(db_context, address, type_flags); + uint32_t new_address = (uint32_t)(address >> 4); + + if ((type_flags & memory_logging_type_dealloc) /* && (address & 0x1f) == 0*/) { + if (__allocation_event_db_del(db_context, new_address)) { + return; + } } + db_context->allocation_event_list->remove(new_address); } -void allocation_event_db_update_object_type16(allocation_event_db *db_context, uint64_t address, uint32_t new_type) { - address_hash16 ai = { .address = address }; +bool __allocation_event_db_update_object_type(allocation_event_db *db_context, uint32_t address, uint32_t new_type) { + address_hash ai = { .address = address }; uint32_t lv0 = ai.detail.lv0; - uint32_t lv1 = ai.detail.lv1; + uint32_t lv0_index = db_context->key_hash[lv0]; - if (db_context->key_hash16[lv0]) { - uint32_t val_index = db_context->key_hash16[lv0][lv1]; + if (lv0_index) { + uint32_t lv1 = ai.detail.lv1; + uint32_t *lv0_ptr = EXPAND_KEY_POINTER(lv0_index); + uint32_t val_index = lv0_ptr[lv1]; if (val_index) { - db_context->val_buffer[val_index].object_type = new_type; + allocation_event *old_val = EXPAND_VAL_POINTER(val_index); + old_val->object_type = new_type; + return true; } } + return false; } -void allocation_event_db_update_object_type32(allocation_event_db *db_context, uint64_t address, uint32_t new_type) { - address_hash32 ai = { .address = address }; +void allocation_event_db_update_object_type(allocation_event_db *db_context, uint64_t address, uint32_t new_type) { + uint32_t new_address = (uint32_t)(address >> 4); + + if (__allocation_event_db_update_object_type(db_context, new_address, new_type)) { + return; + } + if (db_context->allocation_event_list->exist(new_address)) { + db_context->allocation_event_list->find().object_type = new_type; + } +} + +bool __allocation_event_db_update_object_type_and_stack_identifier(allocation_event_db *db_context, + uint32_t address, + uint32_t new_type, + uint32_t stack_identifier) { + address_hash ai = { .address = address }; uint32_t lv0 = ai.detail.lv0; - uint32_t lv1 = ai.detail.lv1; + uint32_t lv0_index = db_context->key_hash[lv0]; - if (db_context->key_hash32[lv0]) { - uint32_t val_index = db_context->key_hash32[lv0][lv1]; + if (lv0_index) { + uint32_t lv1 = ai.detail.lv1; + uint32_t *lv0_ptr = EXPAND_KEY_POINTER(lv0_index); + uint32_t val_index = lv0_ptr[lv1]; if (val_index) { - db_context->val_buffer[val_index].object_type = new_type; + allocation_event *old_val = EXPAND_VAL_POINTER(val_index); + old_val->object_type = new_type; + old_val->stack_identifier = stack_identifier; + return true; } } + return false; } -void allocation_event_db_update_object_type(allocation_event_db *db_context, uint64_t address, uint32_t new_type) { - if ((address & 0x1f) == 0) { - allocation_event_db_update_object_type32(db_context, address, new_type); - } else { - allocation_event_db_update_object_type16(db_context, address, new_type); +void allocation_event_db_update_object_type_and_stack_identifier(allocation_event_db *db_context, + uint64_t address, + uint32_t new_type, + uint32_t stack_identifier) { + uint32_t new_address = (uint32_t)(address >> 4); + + if (__allocation_event_db_update_object_type_and_stack_identifier(db_context, new_address, new_type, stack_identifier)) { + return; + } + if (db_context->allocation_event_list->exist(new_address)) { + db_context->allocation_event_list->find().object_type = new_type; + db_context->allocation_event_list->find().stack_identifier = stack_identifier; } } void allocation_event_db_enumerate(allocation_event_db *db_context, void (^callback)(const uint64_t &address, const allocation_event &event)) { - if (db_context == NULL || db_context->val_buffer == NULL) { + if (db_context == NULL) { return; } - for (int i = 0; i < db_context->val_max_count; ++i) { - const allocation_event &event = db_context->val_buffer[i]; - if (event.alloca_type != memory_logging_type_free) { - callback(1, event); + size_t offset = 0; + while (offset < db_context->val_buffer_source0->fs()) { + size_t read_size = VAL_ALLOC_COUNT * sizeof(allocation_event); + + void *map_mem = inter_mmap(NULL, read_size, PROT_READ, MAP_SHARED, db_context->val_buffer_source0->fd(), offset); + if (map_mem == MAP_FAILED) { + continue; + } + + allocation_event *val_buffer = (allocation_event *)map_mem; + for (int i = 0; i < VAL_ALLOC_COUNT; ++i) { + const allocation_event &event = val_buffer[i]; + if (event.alloca_type != memory_logging_type_free) { + callback(1, event); + } } + + inter_munmap(map_mem, read_size); + + offset += read_size; } + + //db_context->allocation_event_list->enumerate(callback); + db_context->allocation_event_list->enumerate(^(const unsigned int &key, const allocation_event &val) { + callback((uint64_t)key << 4, val); + }); } + +#endif diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db.h index a28c65098..01817dbd7 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db.h @@ -24,15 +24,14 @@ struct allocation_event_db; allocation_event_db *allocation_event_db_open_or_create(const char *event_dir); void allocation_event_db_close(allocation_event_db *db_context); -void allocation_event_db_add(allocation_event_db *db_context, - uint64_t address, - uint32_t type_flags, - uint32_t object_type, - uint32_t size, - uint32_t stack_identifier, - uint32_t t_id); +void allocation_event_db_add( +allocation_event_db *db_context, uint64_t address, uint32_t type_flags, uint32_t object_type, uint32_t size, uint32_t stack_identifier); void allocation_event_db_del(allocation_event_db *db_context, uint64_t address, uint32_t type_flags); void allocation_event_db_update_object_type(allocation_event_db *db_context, uint64_t address, uint32_t new_type); +void allocation_event_db_update_object_type_and_stack_identifier(allocation_event_db *db_context, + uint64_t address, + uint32_t new_type, + uint32_t stack_identifier); void allocation_event_db_enumerate(allocation_event_db *db_context, void (^callback)(const uint64_t &address, const allocation_event &event)); diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db_old.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db_old.cpp index 8d6f26f1c..1d36e3190 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db_old.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db_old.cpp @@ -20,7 +20,7 @@ #pragma mark - #pragma mark Types -// Implememt by splay_map +// Implememt by splay_map_simple_key struct allocation_event_db_old { buffer_source *key_buffer; buffer_source *val_buffer; @@ -62,14 +62,9 @@ void allocation_event_db_old_close(allocation_event_db_old *db_context) { inter_free(db_context); } -void allocation_event_db_old_add(allocation_event_db_old *db_context, - uint64_t address, - uint32_t type_flags, - uint32_t object_type, - uint32_t size, - uint32_t stack_identifier, - uint32_t t_id) { - db_context->allocation_event_list->insert(address, allocation_event(type_flags, object_type, stack_identifier, size, t_id)); +void allocation_event_db_old_add( +allocation_event_db_old *db_context, uint64_t address, uint32_t type_flags, uint32_t object_type, uint32_t size, uint32_t stack_identifier) { + db_context->allocation_event_list->insert(address, allocation_event(type_flags, object_type, stack_identifier, size)); } void allocation_event_db_old_del(allocation_event_db_old *db_context, uint64_t address, uint32_t type_flags) { diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db_old.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db_old.h index 82536fb2b..44d669855 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db_old.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/allocation_event_db_old.h @@ -24,13 +24,8 @@ struct allocation_event_db_old; allocation_event_db_old *allocation_event_db_old_open_or_create(const char *event_dir); void allocation_event_db_old_close(allocation_event_db_old *db_context); -void allocation_event_db_old_add(allocation_event_db_old *db_context, - uint64_t address, - uint32_t type_flags, - uint32_t object_type, - uint32_t size, - uint32_t stack_identifier, - uint32_t t_id); +void allocation_event_db_old_add( +allocation_event_db_old *db_context, uint64_t address, uint32_t type_flags, uint32_t object_type, uint32_t size, uint32_t stack_identifier); void allocation_event_db_old_del(allocation_event_db_old *db_context, uint64_t address, uint32_t type_flags); void allocation_event_db_old_update_object_type(allocation_event_db_old *db_context, uint64_t address, uint32_t new_type); diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event.cpp deleted file mode 100644 index 37e58989b..000000000 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making wechat-matrix available. - * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. - * Licensed under the BSD 3-Clause License (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "memory_logging_event.h" - -#pragma mark - -#pragma mark Functions - -FORCE_INLINE size_t write_size_by_event(memory_logging_event *event) { - return MEMORY_LOGGING_EVENT_SIMPLE_SIZE + (event->stack_size << 3); // event->stack_size * sizeof(uintptr_t); -} diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event.h index ed24aed70..373ef49ba 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event.h @@ -26,9 +26,8 @@ typedef struct { uint64_t address; uint32_t size; uint32_t object_type; - uint32_t t_id; uint32_t type_flags; - uint32_t event_size; + uint16_t event_size; uint8_t event_type; uint8_t stack_size; uintptr_t stacks[STACK_LOGGING_MAX_STACK_SIZE]; @@ -36,6 +35,8 @@ typedef struct { #define MEMORY_LOGGING_EVENT_SIMPLE_SIZE offsetof(memory_logging_event, stacks) -FORCE_INLINE size_t write_size_by_event(memory_logging_event *event); +inline size_t write_size_by_event(memory_logging_event *event) { + return MEMORY_LOGGING_EVENT_SIMPLE_SIZE + (event->stack_size << 3); // event->stack_size * sizeof(uintptr_t); +} #endif /* memory_logging_event_h */ diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer.cpp index acf51c80f..11ef05e0f 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer.cpp @@ -31,7 +31,6 @@ void memory_logging_event_buffer_compress(memory_logging_event_buffer *event_buf while (curr_event < event_buffer_end) { if (curr_event->event_type == EventType_Alloc) { alloc_events[alloc_event_count++] = curr_event; - curr_event = (memory_logging_event *)((uint8_t *)curr_event + curr_event->event_size); } else { uint64_t address = curr_event->address; @@ -43,50 +42,64 @@ void memory_logging_event_buffer_compress(memory_logging_event_buffer *event_buf // *waves hand* current allocation never occurred last_alloc_event->event_type = EventType_Invalid; curr_event->event_type = EventType_Invalid; - alloc_events[i] = alloc_events[end]; + + for (int j = i; j < end; ++j) { + alloc_events[j] = alloc_events[j + 1]; + } --alloc_event_count; break; } else if (curr_event->event_type == EventType_Update) { - last_alloc_event->object_type = curr_event->object_type; - curr_event->event_type = EventType_Invalid; + if (curr_event->stack_size == 0) { + last_alloc_event->object_type = curr_event->object_type; + curr_event->event_type = EventType_Invalid; + } else { + curr_event->size = last_alloc_event->size; + curr_event->type_flags = last_alloc_event->type_flags; + curr_event->event_type = EventType_Alloc; + last_alloc_event->event_type = EventType_Invalid; + alloc_events[i] = curr_event; + } + break; } } else if (curr_event->type_flags & memory_logging_type_vm_deallocate) { // *waves hand* current allocation never occurred last_alloc_event->event_type = EventType_Invalid; curr_event->event_type = EventType_Invalid; - alloc_events[i] = alloc_events[end]; + + for (int j = i; j < end; ++j) { + alloc_events[j] = alloc_events[j + 1]; + } --alloc_event_count; break; } } } - - curr_event = (memory_logging_event *)((uint8_t *)curr_event + MEMORY_LOGGING_EVENT_SIMPLE_SIZE); } + curr_event = (memory_logging_event *)((uint8_t *)curr_event + curr_event->event_size); } } -FORCE_INLINE void memory_logging_event_buffer_lock(memory_logging_event_buffer *event_buffer) { +void memory_logging_event_buffer_lock(memory_logging_event_buffer *event_buffer) { __malloc_lock_lock(&event_buffer->lock); } -FORCE_INLINE void memory_logging_event_buffer_unlock(memory_logging_event_buffer *event_buffer) { +void memory_logging_event_buffer_unlock(memory_logging_event_buffer *event_buffer) { __malloc_lock_unlock(&event_buffer->lock); } -FORCE_INLINE bool memory_logging_event_buffer_is_full(memory_logging_event_buffer *event_buffer, bool is_alloc) { - if (is_alloc) { +bool memory_logging_event_buffer_is_full(memory_logging_event_buffer *event_buffer, bool is_dump_call_stacks) { + if (is_dump_call_stacks) { return event_buffer->write_index > event_buffer->buffer_size - sizeof(memory_logging_event); } else { return event_buffer->write_index > event_buffer->buffer_size - MEMORY_LOGGING_EVENT_SIMPLE_SIZE; } } -FORCE_INLINE memory_logging_event *memory_logging_event_buffer_new_event(memory_logging_event_buffer *event_buffer) { +memory_logging_event *memory_logging_event_buffer_new_event(memory_logging_event_buffer *event_buffer) { return (memory_logging_event *)(event_buffer->buffer + event_buffer->write_index); } -FORCE_INLINE memory_logging_event *memory_logging_event_buffer_last_event(memory_logging_event_buffer *event_buffer) { +memory_logging_event *memory_logging_event_buffer_last_event(memory_logging_event_buffer *event_buffer) { if (event_buffer->last_write_index < event_buffer->write_index) { return (memory_logging_event *)(event_buffer->buffer + event_buffer->last_write_index); } else { @@ -94,40 +107,40 @@ FORCE_INLINE memory_logging_event *memory_logging_event_buffer_last_event(memory } } -FORCE_INLINE memory_logging_event *memory_logging_event_buffer_begin(memory_logging_event_buffer *event_buffer) { +memory_logging_event *memory_logging_event_buffer_begin(memory_logging_event_buffer *event_buffer) { if (event_buffer->write_index == 0) { return NULL; } - event_buffer->read_index = 0; return (memory_logging_event *)event_buffer->buffer; } -FORCE_INLINE memory_logging_event *memory_logging_event_buffer_next(memory_logging_event_buffer *event_buffer) { - memory_logging_event *curr_event = (memory_logging_event *)(event_buffer->buffer + event_buffer->read_index); - event_buffer->read_index += curr_event->event_size; +memory_logging_event *memory_logging_event_buffer_next(memory_logging_event_buffer *event_buffer, memory_logging_event *curr_event) { + void *event_buffer_end = event_buffer->buffer + event_buffer->write_index; + memory_logging_event *next_event = (memory_logging_event *)((uint8_t *)curr_event + curr_event->event_size); - if (event_buffer->read_index < event_buffer->write_index) { - return (memory_logging_event *)(event_buffer->buffer + event_buffer->read_index); - } else if (event_buffer->read_index == event_buffer->write_index) { + if (next_event < event_buffer_end) { + return next_event; + } else if (next_event == event_buffer_end) { return NULL; } else { disable_memory_logging(); - __malloc_printf("read: %d, write: %d, buffer_size: %u, self: %p, self->buffer: %p", - event_buffer->read_index, + __malloc_printf("curr_event: %p, next_event: %p, write_index: %d, buffer_size: %u, self: %p, self->buffer: %p", + curr_event, + next_event, event_buffer->write_index, event_buffer->buffer_size, event_buffer, event_buffer->buffer); - abort(); + return NULL; } } -FORCE_INLINE void memory_logging_event_buffer_update_write_index_with_size(memory_logging_event_buffer *event_buffer, size_t write_size) { +void memory_logging_event_buffer_update_write_index_with_size(memory_logging_event_buffer *event_buffer, size_t write_size) { event_buffer->last_write_index = event_buffer->write_index; event_buffer->write_index += write_size; } -FORCE_INLINE void memory_logging_event_buffer_update_to_last_write_index(memory_logging_event_buffer *event_buffer) { +void memory_logging_event_buffer_update_to_last_write_index(memory_logging_event_buffer *event_buffer) { event_buffer->write_index = event_buffer->last_write_index; } diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer.h index 749000976..20b8c9309 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer.h @@ -21,31 +21,33 @@ #include "memory_logging_event.h" struct memory_logging_event_buffer { - int32_t write_index; - int32_t last_write_index; - int32_t read_index; - int32_t buffer_size; - uint8_t *buffer; + int16_t write_index; + int16_t last_write_index; + int16_t buffer_size; - malloc_lock_s lock; + bool is_from_buffer_pool; + malloc_lock_s lock; volatile thread_id t_id; + + uint8_t *buffer; memory_logging_event_buffer *next_event_buffer; }; +void memory_logging_event_buffer_init(memory_logging_event_buffer *event_buffer); void memory_logging_event_buffer_compress(memory_logging_event_buffer *event_buffer); -FORCE_INLINE void memory_logging_event_buffer_lock(memory_logging_event_buffer *event_buffer); -FORCE_INLINE void memory_logging_event_buffer_unlock(memory_logging_event_buffer *event_buffer); +void memory_logging_event_buffer_lock(memory_logging_event_buffer *event_buffer); +void memory_logging_event_buffer_unlock(memory_logging_event_buffer *event_buffer); -FORCE_INLINE bool memory_logging_event_buffer_is_full(memory_logging_event_buffer *event_buffer, bool is_alloc = false); -FORCE_INLINE memory_logging_event *memory_logging_event_buffer_new_event(memory_logging_event_buffer *event_buffer); -FORCE_INLINE memory_logging_event *memory_logging_event_buffer_last_event(memory_logging_event_buffer *event_buffer); +bool memory_logging_event_buffer_is_full(memory_logging_event_buffer *event_buffer, bool is_dump_call_stacks = false); +memory_logging_event *memory_logging_event_buffer_new_event(memory_logging_event_buffer *event_buffer); +memory_logging_event *memory_logging_event_buffer_last_event(memory_logging_event_buffer *event_buffer); -FORCE_INLINE memory_logging_event *memory_logging_event_buffer_begin(memory_logging_event_buffer *event_buffer); -FORCE_INLINE memory_logging_event *memory_logging_event_buffer_next(memory_logging_event_buffer *event_buffer); +memory_logging_event *memory_logging_event_buffer_begin(memory_logging_event_buffer *event_buffer); +memory_logging_event *memory_logging_event_buffer_next(memory_logging_event_buffer *event_buffer, memory_logging_event *curr_event); -FORCE_INLINE void memory_logging_event_buffer_update_write_index_with_size(memory_logging_event_buffer *event_buffer, size_t write_size); -FORCE_INLINE void memory_logging_event_buffer_update_to_last_write_index(memory_logging_event_buffer *event_buffer); +void memory_logging_event_buffer_update_write_index_with_size(memory_logging_event_buffer *event_buffer, size_t write_size); +void memory_logging_event_buffer_update_to_last_write_index(memory_logging_event_buffer *event_buffer); #endif /* memory_logging_event_buffer_h */ diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_list.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_list.cpp index 60426337d..f1aac59e1 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_list.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_list.cpp @@ -21,6 +21,7 @@ struct memory_logging_event_buffer_list { malloc_lock_s lock; + memory_logging_event_buffer *curr_buffer; memory_logging_event_buffer *tail_buffer; }; @@ -62,20 +63,7 @@ void memory_logging_event_buffer_list_push_back(memory_logging_event_buffer_list __malloc_lock_unlock(&buffer_list->lock); } -memory_logging_event_buffer *memory_logging_event_buffer_list_pop_front(memory_logging_event_buffer_list *buffer_list) { - __malloc_lock_lock(&buffer_list->lock); - - memory_logging_event_buffer *curr_buffer = buffer_list->curr_buffer; - if (curr_buffer) { - buffer_list->curr_buffer = curr_buffer->next_event_buffer; - } - - __malloc_lock_unlock(&buffer_list->lock); - - return curr_buffer; -} - -memory_logging_event_buffer *memory_logging_event_buffer_list_reset(memory_logging_event_buffer_list *buffer_list) { +memory_logging_event_buffer *memory_logging_event_buffer_list_pop_all(memory_logging_event_buffer_list *buffer_list) { __malloc_lock_lock(&buffer_list->lock); memory_logging_event_buffer *curr_buffer = buffer_list->curr_buffer; diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_list.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_list.h index 8be96b1f7..636a5c94a 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_list.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_list.h @@ -25,8 +25,6 @@ memory_logging_event_buffer_list *memory_logging_event_buffer_list_create(); void memory_logging_event_buffer_list_free(memory_logging_event_buffer_list *buffer_list); void memory_logging_event_buffer_list_push_back(memory_logging_event_buffer_list *buffer_list, memory_logging_event_buffer *event_buffer); -memory_logging_event_buffer *memory_logging_event_buffer_list_pop_front(memory_logging_event_buffer_list *buffer_list); - -memory_logging_event_buffer *memory_logging_event_buffer_list_reset(memory_logging_event_buffer_list *buffer_list); +memory_logging_event_buffer *memory_logging_event_buffer_list_pop_all(memory_logging_event_buffer_list *buffer_list); #endif /* memory_logging_event_buffer_list_h */ diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_pool.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_pool.cpp index 20a210d87..8a215721f 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_pool.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_pool.cpp @@ -18,8 +18,8 @@ #include -#define BUFFER_SIZE (4 << 10) -#define MAX_BUFFER_COUNT (512) +#define BUFFER_SIZE (2 << 10) +#define MAX_BUFFER_COUNT (4 << 10) #pragma mark - #pragma mark Types @@ -28,11 +28,19 @@ struct memory_logging_event_buffer_pool { malloc_lock_s lock; dispatch_semaphore_t pool_semaphore; + int max_buffer_count; + int buffer_size; + void *pool_memory; memory_logging_event_buffer *curr_buffer; memory_logging_event_buffer *tail_buffer; }; +extern int dump_call_stacks; +extern thread_id s_main_thread_id; + +static_assert(sizeof(memory_logging_event_buffer) % 8 == 0, "Not aligned!"); + #pragma mark - #pragma mark Functions @@ -42,20 +50,24 @@ memory_logging_event_buffer_pool *memory_logging_event_buffer_pool_create() { return NULL; } + buffer_pool->max_buffer_count = MAX_BUFFER_COUNT; + buffer_pool->buffer_size = (dump_call_stacks == 0 ? (BUFFER_SIZE / 4) : BUFFER_SIZE); + buffer_pool->lock = __malloc_lock_init(); - buffer_pool->pool_semaphore = dispatch_semaphore_create(MAX_BUFFER_COUNT); - buffer_pool->pool_memory = inter_malloc(MAX_BUFFER_COUNT * BUFFER_SIZE); + buffer_pool->pool_semaphore = dispatch_semaphore_create(buffer_pool->max_buffer_count); + buffer_pool->pool_memory = inter_malloc(buffer_pool->max_buffer_count * buffer_pool->buffer_size); if (buffer_pool->pool_memory == NULL) { memory_logging_event_buffer_pool_free(buffer_pool); return NULL; } memory_logging_event_buffer *last_buffer = NULL; - for (int i = 0; i < MAX_BUFFER_COUNT; ++i) { - memory_logging_event_buffer *curr_buffer = (memory_logging_event_buffer *)((char *)buffer_pool->pool_memory + i * BUFFER_SIZE); + for (int i = 0; i < buffer_pool->max_buffer_count; ++i) { + memory_logging_event_buffer *curr_buffer = (memory_logging_event_buffer *)((char *)buffer_pool->pool_memory + i * buffer_pool->buffer_size); + curr_buffer->is_from_buffer_pool = true; curr_buffer->lock = __malloc_lock_init(); - curr_buffer->buffer_size = BUFFER_SIZE - sizeof(memory_logging_event_buffer); curr_buffer->buffer = (uint8_t *)curr_buffer + sizeof(memory_logging_event_buffer); // % 8 = 0 + curr_buffer->buffer_size = buffer_pool->buffer_size - sizeof(memory_logging_event_buffer); if (last_buffer) { last_buffer->next_event_buffer = curr_buffer; @@ -75,28 +87,59 @@ void memory_logging_event_buffer_pool_free(memory_logging_event_buffer_pool *buf return; } + // avoid that after the memory monitoring stops, there are still some events being written + while (dispatch_semaphore_wait(buffer_pool->pool_semaphore, DISPATCH_TIME_NOW) != 0) { + buffer_pool->curr_buffer = (memory_logging_event_buffer *)buffer_pool->pool_memory; + dispatch_semaphore_signal(buffer_pool->pool_semaphore); + } + inter_free(buffer_pool->pool_memory); inter_free(buffer_pool); } -memory_logging_event_buffer *memory_logging_event_buffer_pool_new_buffer(memory_logging_event_buffer_pool *buffer_pool) { - dispatch_semaphore_wait(buffer_pool->pool_semaphore, DISPATCH_TIME_FOREVER); +memory_logging_event_buffer *memory_logging_event_buffer_pool_new_buffer(memory_logging_event_buffer_pool *buffer_pool, thread_id t_id) { + memory_logging_event_buffer *event_buffer; - __malloc_lock_lock(&buffer_pool->lock); + if (t_id == s_main_thread_id) { + if (dispatch_semaphore_wait(buffer_pool->pool_semaphore, DISPATCH_TIME_NOW) != 0) { + event_buffer = (memory_logging_event_buffer *)inter_malloc(buffer_pool->buffer_size); + event_buffer->is_from_buffer_pool = false; + event_buffer->lock = __malloc_lock_init(); + event_buffer->buffer = (uint8_t *)event_buffer + sizeof(memory_logging_event_buffer); // % 8 = 0 + event_buffer->buffer_size = buffer_pool->buffer_size - sizeof(memory_logging_event_buffer); + } else { + __malloc_lock_lock(&buffer_pool->lock); - memory_logging_event_buffer *event_buffer = buffer_pool->curr_buffer; - buffer_pool->curr_buffer = event_buffer->next_event_buffer; + event_buffer = buffer_pool->curr_buffer; + buffer_pool->curr_buffer = event_buffer->next_event_buffer; - __malloc_lock_unlock(&buffer_pool->lock); + __malloc_lock_unlock(&buffer_pool->lock); + } + } else { + dispatch_semaphore_wait(buffer_pool->pool_semaphore, DISPATCH_TIME_FOREVER); + + __malloc_lock_lock(&buffer_pool->lock); + + event_buffer = buffer_pool->curr_buffer; + buffer_pool->curr_buffer = event_buffer->next_event_buffer; + + __malloc_lock_unlock(&buffer_pool->lock); + } - event_buffer->next_event_buffer = NULL; event_buffer->write_index = 0; event_buffer->last_write_index = 0; + event_buffer->t_id = t_id; + event_buffer->next_event_buffer = NULL; return event_buffer; } bool memory_logging_event_buffer_pool_free_buffer(memory_logging_event_buffer_pool *buffer_pool, memory_logging_event_buffer *event_buffer) { + if (event_buffer->is_from_buffer_pool == false) { + inter_free(event_buffer); + return false; + } + __malloc_lock_lock(&buffer_pool->lock); if (buffer_pool->curr_buffer == NULL) { diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_pool.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_pool.h index ccd0746b2..5a4c054c0 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_pool.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/memory_logging_event_buffer_pool.h @@ -24,7 +24,7 @@ struct memory_logging_event_buffer_pool; memory_logging_event_buffer_pool *memory_logging_event_buffer_pool_create(); void memory_logging_event_buffer_pool_free(memory_logging_event_buffer_pool *buffer_pool); -memory_logging_event_buffer *memory_logging_event_buffer_pool_new_buffer(memory_logging_event_buffer_pool *buffer_pool); +memory_logging_event_buffer *memory_logging_event_buffer_pool_new_buffer(memory_logging_event_buffer_pool *buffer_pool, thread_id t_id); bool memory_logging_event_buffer_pool_free_buffer(memory_logging_event_buffer_pool *buffer_pool, memory_logging_event_buffer *event_buffer); #endif /* memory_logging_event_buffer_pool_h */ diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/object_event_handler.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/object_event_handler.cpp index f014287cb..08fe1eff4 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/object_event_handler.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/ObjectEvent/object_event_handler.cpp @@ -207,10 +207,13 @@ inline size_t __string_hash(const char *str) { } void object_set_last_allocation_event_name(void *ptr, const char *classname) { - if (!ptr) + if (!ptr) { return; - if (!classname) + } + + if (!classname) { classname = "(no class)"; + } uint32_t type = 0; uintptr_t str_hash = __string_hash(classname); @@ -231,10 +234,13 @@ void object_set_last_allocation_event_name(void *ptr, const char *classname) { } void nsobject_set_last_allocation_event_name(void *ptr, const char *classname) { - if (!ptr) + if (!ptr) { return; - if (!classname) + } + + if (!classname) { classname = "(no class)"; + } uint32_t type = 0; diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.cpp index c52d8c3d2..fd2be28fd 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.cpp @@ -253,35 +253,17 @@ dyld_image_info_db *prepare_dyld_image_logger(const char *event_dir) { } } -bool is_stack_frames_should_skip(uintptr_t *frames, int32_t count, uint64_t malloc_size, uint32_t type_flags) { - if (count < 3) { +bool is_stack_frames_should_skip(uintptr_t *frames, int32_t count, uint64_t malloc_size) { + if (count < 2) { return true; } - // skip allocation events from mapped_file - if (type_flags & memory_logging_type_mapped_file_or_shared_mem) { - if (mmap_func_info.vm_str == 0) { - Dl_info info = { 0 }; - dladdr((const void *)frames[0], &info); - if (info.dli_sname && strcmp(info.dli_sname, "mmap") == 0) { - mmap_func_info.vm_str = frames[0]; - } - } - if (mmap_func_info.vm_str == frames[0]) { - if (frames[1] >= app_image_info.vm_str && frames[1] < app_image_info.vm_end) { - return false; - } else { - return true; - } - } - } - if (malloc_size >= skip_min_malloc_size) { return false; } // check whether there's any symbol not in this APP - for (int i = MIN(count - 3, skip_max_stack_depth); i >= 1; --i) { + for (int i = MIN(count - 1, skip_max_stack_depth); i >= 1; --i) { if (frames[i] >= app_image_info.vm_str && frames[i] < app_image_info.vm_end) { return false; } diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.h index a5be1a775..cafa42a61 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/dyld_image_info.h @@ -32,7 +32,7 @@ extern int skip_min_malloc_size; struct dyld_image_info_db; dyld_image_info_db *prepare_dyld_image_logger(const char *event_dir); -bool is_stack_frames_should_skip(uintptr_t *frames, int32_t count, uint64_t malloc_size, uint32_t type_flags); +bool is_stack_frames_should_skip(uintptr_t *frames, int32_t count, uint64_t malloc_size); const char *app_uuid(); dyld_image_info_db *dyld_image_info_db_open_or_create(const char *event_dir); diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/stack_frames_db.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/stack_frames_db.cpp index 8ebb2f2c9..1758149ba 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/stack_frames_db.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/StackFrames/stack_frames_db.cpp @@ -39,9 +39,8 @@ #define STACK_FRAMES_MAX_LEVEL STACK_LOGGING_MAX_STACK_SIZE -#define STACK_FRAMES_DB_DIR "db" -#define STACK_FRAMES_DB_FILE "stack_frames.db" -#define STACK_FRAMES_DB_INDEX_FILE "stack_frames.db.index" +#define STACK_FRAMES_DB_FILE "stack_frames_entry.dat" +#define STACK_FRAMES_DB_INDEX_FILE "stack_frames_index.dat" #pragma mark - #pragma mark Types @@ -187,7 +186,6 @@ static bool __expand_uniquing_table(backtrace_uniquing_table *uniquing_table) { strerror(errno), (uint64_t)uniquing_table->fs + DEFAULT_UNIQUING_BAND_SIZE, errno); - abort(); return false; } @@ -196,7 +194,6 @@ static bool __expand_uniquing_table(backtrace_uniquing_table *uniquing_table) { if (newBand == MAP_FAILED) { disable_memory_logging(); __malloc_printf("fail to mmap, %s, new_size: %llu, errno: %d", strerror(errno), (uint64_t)DEFAULT_UNIQUING_BAND_SIZE, errno); - abort(); return false; } @@ -263,9 +260,6 @@ uint32_t __enter_frames_in_table(backtrace_uniquing_table *uniquing_table, uintp while (true) { hash_index_t bandIndex = __enter_address_in_band(uniquing_table, thisPC, uParent); - if (bandIndex >= (1 << 28)) { - abort(); - } if (bandIndex != 0) { uParent = bandIndex + baseIndex; break; @@ -423,9 +417,6 @@ uint32_t add_stack_frames_in_table(stack_frames_db *db_context, uintptr_t *frame } #endif - if (!stack_identifier) - abort(); - return stack_identifier; } diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/buffer_source.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/buffer_source.h index ca2a35a64..9258d7e80 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/buffer_source.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/buffer_source.h @@ -53,9 +53,12 @@ class buffer_source_memory : public buffer_source { virtual bool init_fail() { return false; } virtual void *realloc(size_t new_size) { - _buffer = inter_realloc(_buffer, new_size); - _buffer_size = new_size; - return _buffer; + void *ptr = inter_realloc(_buffer, new_size); + if (ptr != NULL) { + _buffer = ptr; + _buffer_size = new_size; + } + return ptr; } virtual void free() { @@ -70,29 +73,27 @@ class buffer_source_memory : public buffer_source { class buffer_source_file : public buffer_source { public: buffer_source_file(const char *dir, const char *file_name) { - int fd = open_file(dir, file_name); + _fd = open_file(dir, file_name); _file_name = file_name; - if (fd < 0) { + if (_fd < 0) { goto init_fail; } else { struct stat st = { 0 }; - if (fstat(fd, &st) == -1) { + if (fstat(_fd, &st) == -1) { goto init_fail; } else { if (st.st_size > 0) { - void *buff = inter_mmap(NULL, (size_t)st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + void *buff = inter_mmap(NULL, (size_t)st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0); if (buff == MAP_FAILED) { __malloc_printf("fail to mmap, %s", strerror(errno)); goto init_fail; } else { - _fd = fd; - _fs = st.st_size; + _fs = (size_t)st.st_size; _buffer = buff; _buffer_size = _fs; } } else { - _fd = fd; _fs = 0; _buffer = NULL; _buffer_size = 0; @@ -102,8 +103,8 @@ class buffer_source_file : public buffer_source { return; init_fail: - if (fd >= 0) { - close(fd); + if (_fd >= 0) { + close(_fd); _fd = -1; } } @@ -118,13 +119,10 @@ class buffer_source_file : public buffer_source { virtual bool init_fail() { return _fd < 0; } virtual void *realloc(size_t new_size) { - free(); - new_size = round_page(new_size); if (ftruncate(_fd, new_size) != 0) { disable_memory_logging(); __malloc_printf("%s fail to ftruncate, %s, new_size: %llu, errno: %d", _file_name, strerror(errno), (uint64_t)new_size, errno); - abort(); return NULL; } @@ -132,10 +130,11 @@ class buffer_source_file : public buffer_source { if (new_mem == MAP_FAILED) { disable_memory_logging(); __malloc_printf("%s fail to mmap, %s, new_size: %llu, errno: %d", _file_name, strerror(errno), (uint64_t)new_size, errno); - abort(); return NULL; } + free(); + _fs = new_size; _buffer = new_mem; _buffer_size = new_size; @@ -161,17 +160,19 @@ class buffer_source_file : public buffer_source { class memory_pool_file { public: memory_pool_file(const char *dir, const char *file_name) { + _fs = 0; _fd = open_file(dir, file_name); _file_name = file_name; if (_fd < 0) { goto init_fail; } else { - if (ftruncate(_fd, 0) != 0) { + struct stat st = { 0 }; + if (fstat(_fd, &st) == -1) { goto init_fail; + } else { + _fs = (size_t)st.st_size; } - - _fs = 0; } return; @@ -188,6 +189,9 @@ class memory_pool_file { } } + inline int fd() { return _fd; } + inline size_t fs() { return _fs; } + bool init_fail() { return _fd < 0; } void *malloc(size_t size) { @@ -195,7 +199,6 @@ class memory_pool_file { if (ftruncate(_fd, _fs + new_size) != 0) { disable_memory_logging(); __malloc_printf("%s fail to ftruncate, %s, new_size: %llu, errno: %d", _file_name, strerror(errno), (uint64_t)_fs + new_size, errno); - abort(); return NULL; } @@ -208,7 +211,6 @@ class memory_pool_file { (uint64_t)new_size, (uint64_t)_fs, errno); - abort(); return NULL; } diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/sb_tree.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/sb_tree.h index 71faed239..f16974801 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/sb_tree.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/sb_tree.h @@ -326,7 +326,7 @@ template class sb_tree { bool exist(const T &key) { return (last_ptr = inter_find(t_info->root_ptr, key)) != 0; } void insert(const T &key) { - if ((!t_info->b_size || t_info->t_size == t_info->b_size - 1) && reallocate_memory(false) == false) { + if ((!t_info->b_size || t_info->t_size + 1 == t_info->b_size) && reallocate_memory(false) == false) { return; // malloc fail } ++t_info->t_size; diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map.h index ee47e8596..fee9068f0 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map.h @@ -131,7 +131,7 @@ template class splay_map { while (root != 0) { s.push(root); if (s.size() > t_info->t_size) { - abort(); + return; } root = get_node_lc(root); } @@ -140,7 +140,7 @@ template class splay_map { root = s.top(); callback(get_node_key(root), get_val(root)); if (++count > t_info->t_size) { - abort(); + return; } s.pop(); root = get_node_rc(root); @@ -173,7 +173,6 @@ template class splay_map { if (new_buff) { memset(new_buff, 0, malloc_size); t_info = (tree_info *)new_buff; - t_info->b_size = i_size; k_buff = (node *)((char *)new_buff + sizeof(tree_info)); } else { return false; @@ -184,6 +183,7 @@ template class splay_map { new_buff = val_buffer_source->realloc(malloc_size); if (new_buff) { memset(new_buff, 0, malloc_size); + t_info->b_size = i_size; v_buff = (TVal *)new_buff; return true; } else { @@ -245,7 +245,7 @@ template class splay_map { ~splay_map() {} void insert(const TKey &key, const TVal &val) { - if (t_info->t_size == t_info->b_size - 1 && reallocate_memory(false) == false) { + if (t_info->t_size + 1 == t_info->b_size && reallocate_memory(false) == false) { return; // malloc fail } diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map_ptr.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map_ptr.h index 6de17d4b2..01bff7dc9 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map_ptr.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map_ptr.h @@ -44,8 +44,10 @@ template class splay_map_ptr { bool splay(TKey key, node_ptr &root) { /* Simple top down splay, not requiring i to be in the tree t. */ /* What it does is described above. */ - if (root == NULL) + if (root == NULL) { return false; + } + node N; node_ptr l, r, t; N.left = N.right = NULL; @@ -56,28 +58,32 @@ template class splay_map_ptr { for (;;) { if (t->key > key) { node_ptr tlc = t->left; - if (tlc == NULL) + if (tlc == NULL) { break; + } if (tlc->key > key) { t->left = tlc->right; /* rotate right */ tlc->right = t; t = tlc; - if (t->left == NULL) + if (t->left == NULL) { break; + } } r->left = t; /* link right */ r = t; t = t->left; } else if (t->key < key) { node_ptr trc = t->right; - if (trc == NULL) + if (trc == NULL) { break; + } if (trc->key < key) { t->right = trc->left; /* rotate left */ trc->left = t; t = trc; - if (t->right == NULL) + if (t->right == NULL) { break; + } } l->right = t; /* link left */ l = t; @@ -104,8 +110,9 @@ template class splay_map_ptr { } void inter_enumerate(node_ptr root, void (^callback)(const TKey &key, const TVal &val)) { - if (root == NULL) + if (root == NULL) { return; + } // not support } @@ -120,6 +127,10 @@ template class splay_map_ptr { if (new_ptr == NULL) { int new_count = (4 << 10); node_ptr new_buffer = (node_ptr)memory_pool->malloc(new_count * sizeof(node)); + if (new_buffer == NULL) { + return NULL; + } + for (int i = 1; i < new_count; ++i) { new_buffer[i - 1].left = &new_buffer[i]; } @@ -138,45 +149,58 @@ template class splay_map_ptr { ~splay_map_ptr() {} void insert(TKey key, const TVal &val) { - ++t_size; - /* Insert i into the tree t, unless it's already there. */ - /* Return a pointer to the resulting tree. */ - node_ptr n = next_free_node(); - n->left = n->right = NULL; - n->key = key; - n->val = val; - if (root_ptr == NULL) { - root_ptr = n; + root_ptr = next_free_node(); + if (root_ptr == NULL) { + return; + } + + t_size = 1; + root_ptr->left = root_ptr->right = NULL; + root_ptr->key = key; + root_ptr->val = val; return; } - splay(key, root_ptr); - if (root_ptr->key > key) { + if (splay(key, root_ptr)) { + /* We get here if it's already in the tree */ + /* Don't add it again */ + root_ptr->val = val; + } else if (root_ptr->key > key) { + node_ptr n = next_free_node(); + if (n == NULL) { + return; + } + + ++t_size; + n->key = key; + n->val = val; n->left = root_ptr->left; n->right = root_ptr; root_ptr->left = NULL; root_ptr = n; - } else if (root_ptr->key < key) { + } else { + node_ptr n = next_free_node(); + if (n == NULL) { + return; + } + + ++t_size; + n->key = key; + n->val = val; n->right = root_ptr->right; n->left = root_ptr; root_ptr->right = NULL; root_ptr = n; - } else { /* We get here if it's already in the tree */ - /* Don't add it again */ - root_ptr->val = val; - free_node(n); - --t_size; } } void remove(TKey key) { /* Deletes i from the tree if it's there. */ /* Return a pointer to the resulting tree. */ - node_ptr x; - if (root_ptr == NULL) - return; if (splay(key, root_ptr)) { /* found it */ + node_ptr x; + if (root_ptr->left == NULL) { x = root_ptr->right; } else { diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map_simple_key.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map_simple_key.h index 75935fde7..67c08ef71 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map_simple_key.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_map_simple_key.h @@ -62,8 +62,9 @@ template class splay_map_simple_key { bool splay(TKey key, node_ptr &root) { /* Simple top down splay, not requiring i to be in the tree t. */ /* What it does is described above. */ - if (root == 0) + if (root == 0) { return false; + } node_ptr l = 0, r = 0, t = root; bool ret = false; @@ -72,28 +73,32 @@ template class splay_map_simple_key { TKey tkey = get_node_key(t); if (tkey > key) { node_ptr tlc = get_node_lc(t); - if (tlc == 0) + if (tlc == 0) { break; + } if (get_node_key(tlc) > key) { get_node_lc(t) = get_node_rc(tlc); /* rotate right */ get_node_rc(tlc) = t; t = tlc; - if (get_node_lc(t) == 0) + if (get_node_lc(t) == 0) { break; + } } get_node_lc(r) = t; /* link right */ r = t; t = get_node_lc(t); } else if (tkey < key) { node_ptr trc = get_node_rc(t); - if (trc == 0) + if (trc == 0) { break; + } if (get_node_key(trc) < key) { get_node_rc(t) = get_node_lc(trc); /* rotate left */ get_node_lc(trc) = t; t = trc; - if (get_node_rc(t) == 0) + if (get_node_rc(t) == 0) { break; + } } get_node_rc(l) = t; /* link left */ l = t; @@ -122,8 +127,9 @@ template class splay_map_simple_key { } void inter_enumerate(node_ptr root, void (^callback)(const TKey &key, const TVal &val)) { - if (root == 0) + if (root == 0) { return; + } std::stack s; uint32_t count = 0; @@ -131,7 +137,7 @@ template class splay_map_simple_key { while (root != 0) { s.push(root); if (s.size() > t_info->t_size) { - abort(); + return; } root = get_node_lc(root); } @@ -140,7 +146,7 @@ template class splay_map_simple_key { root = s.top(); callback(get_node_key(root), get_val(root)); if (++count > t_info->t_size) { - abort(); + return; } s.pop(); root = get_node_rc(root); @@ -149,8 +155,9 @@ template class splay_map_simple_key { } void free_node(node_ptr ptr) { - if (ptr == 0) + if (ptr == 0) { return; + } get_node(ptr).left = t_info->free_ptr; // ticky t_info->free_ptr = ptr; } @@ -173,7 +180,6 @@ template class splay_map_simple_key { if (new_buff) { memset(new_buff, 0, malloc_size); t_info = (tree_info *)new_buff; - t_info->b_size = i_size; k_buff = (node *)((char *)new_buff + sizeof(tree_info)); } else { return false; @@ -184,6 +190,7 @@ template class splay_map_simple_key { new_buff = val_buffer_source->realloc(malloc_size); if (new_buff) { memset(new_buff, 0, malloc_size); + t_info->b_size = i_size; v_buff = (TVal *)new_buff; return true; } else { @@ -245,43 +252,12 @@ template class splay_map_simple_key { ~splay_map_simple_key() {} void insert(TKey key, const TVal &val) { - if (t_info->t_size == t_info->b_size - 1 && reallocate_memory(false) == false) { + if (t_info->t_size + 1 == t_info->b_size && reallocate_memory(false) == false) { return; // malloc fail } - if (t_info->root_ptr != 0) { - splay(key, t_info->root_ptr); - - node_ptr root_ptr = t_info->root_ptr; - TKey rkey = get_node_key(root_ptr); - if (rkey > key) { - ++t_info->t_size; - - node_ptr n = next_free_node(); - get_node_key(n) = key; - get_node_lc(n) = get_node_lc(root_ptr); - get_node_rc(n) = root_ptr; - get_val(n) = val; - - get_node_lc(root_ptr) = 0; - t_info->root_ptr = n; - } else if (rkey < key) { - ++t_info->t_size; - - node_ptr n = next_free_node(); - get_node_key(n) = key; - get_node_rc(n) = get_node_rc(root_ptr); - get_node_lc(n) = root_ptr; - get_val(n) = val; - - get_node_rc(root_ptr) = 0; - t_info->root_ptr = n; - } else { /* We get here if it's already in the tree */ - /* Don't add it again */ - get_val(t_info->root_ptr) = val; - } - } else { - ++t_info->t_size; + if (t_info->root_ptr == 0) { + t_info->t_size = 1; node_ptr n = next_free_node(); get_node_key(n) = key; @@ -289,16 +265,48 @@ template class splay_map_simple_key { get_node_rc(n) = 0; get_val(n) = val; t_info->root_ptr = n; + return; + } + + if (splay(key, t_info->root_ptr)) { + /* We get here if it's already in the tree */ + /* Don't add it again */ + get_val(t_info->root_ptr) = val; + return; + } + + node_ptr root_ptr = t_info->root_ptr; + if (get_node_key(root_ptr) > key) { + ++t_info->t_size; + + node_ptr n = next_free_node(); + get_node_key(n) = key; + get_node_lc(n) = get_node_lc(root_ptr); + get_node_rc(n) = root_ptr; + get_val(n) = val; + + get_node_lc(root_ptr) = 0; + t_info->root_ptr = n; + } else { + ++t_info->t_size; + + node_ptr n = next_free_node(); + get_node_key(n) = key; + get_node_rc(n) = get_node_rc(root_ptr); + get_node_lc(n) = root_ptr; + get_val(n) = val; + + get_node_rc(root_ptr) = 0; + t_info->root_ptr = n; } } void remove(TKey key) { /* Deletes i from the tree if it's there. */ /* Return a pointer to the resulting tree. */ - node_ptr x; - if (t_info->root_ptr == 0) - return; if (splay(key, t_info->root_ptr)) { /* found it */ + node_ptr x; + if (get_node_lc(t_info->root_ptr) == 0) { x = get_node_rc(t_info->root_ptr); } else { diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_tree.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_tree.h index b33d4c428..43b584ca0 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_tree.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/Tree/splay_tree.h @@ -126,7 +126,7 @@ template class splay_tree { while (root != 0) { s.push(root); if (s.size() > t_info->t_size) { - abort(); + return; } root = get_node_lc(root); } @@ -135,7 +135,7 @@ template class splay_tree { root = s.top(); callback(get_node_key(root)); if (++count > t_info->t_size) { - abort(); + return; } s.pop(); root = get_node_rc(root); @@ -213,7 +213,7 @@ template class splay_tree { } void insert(const T &key) { - if (t_info->t_size == t_info->b_size - 1 && reallocate_memory(false) == false) { + if (t_info->t_size + 1 == t_info->b_size && reallocate_memory(false) == false) { return; // malloc fail } diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/logger_internal.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/logger_internal.cpp index 7972ca15a..d9d608e25 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/logger_internal.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/logger_internal.cpp @@ -30,8 +30,7 @@ int err_code = MS_ERRC_SUCCESS; -static pthread_key_t s_ignore_logging_key = 0; -static pthread_key_t s_thread_id_key = 0; +static pthread_key_t s_thread_info_key = 0; static malloc_lock_s shared_lock = __malloc_lock_init(); static malloc_zone_t *inter_zone = malloc_create_zone(1 << 20, 0); @@ -41,73 +40,46 @@ static size_t mapped_size[32] = { 0 }; static bool app_is_in_backgound = false; #pragma mark - -#pragma mark Lock Function +#pragma mark Thread Info -#ifdef USE_SPIN_LOCK +uint64_t current_thread_info_for_logging() { + uint64_t value = (uintptr_t)pthread_getspecific(s_thread_info_key); -FORCE_INLINE malloc_lock_s __malloc_lock_init() { - return OS_SPINLOCK_INIT; -} - -FORCE_INLINE void __malloc_lock_lock(malloc_lock_s *lock) { - OSSpinLockLock(lock); -} - -FORCE_INLINE bool __malloc_lock_trylock(malloc_lock_s *lock) { - return OSSpinLockTry(lock); -} - -FORCE_INLINE void __malloc_lock_unlock(malloc_lock_s *lock) { - OSSpinLockUnlock(lock); -} - -#else - -FORCE_INLINE malloc_lock_s __malloc_lock_init() { - return OS_UNFAIR_LOCK_INIT; -} - -FORCE_INLINE void __malloc_lock_lock(malloc_lock_s *lock) { - os_unfair_lock_lock(lock); -} - -FORCE_INLINE bool __malloc_lock_trylock(malloc_lock_s *lock) { - return os_unfair_lock_trylock(lock); -} + if (value == 0) { + thread_info_for_logging_t thread_info; + thread_info.detail.is_ignore = false; + thread_info.detail.t_id = pthread_mach_thread_np(pthread_self()); + pthread_setspecific(s_thread_info_key, (void *)(uintptr_t)thread_info.value); + return thread_info.value; + } -FORCE_INLINE void __malloc_lock_unlock(malloc_lock_s *lock) { - os_unfair_lock_unlock(lock); + return value; } -#endif - -#pragma mark - -#pragma mark Thread ID - -FORCE_INLINE thread_id current_thread_id() { - thread_id t_id = (thread_id)(uintptr_t)pthread_getspecific(s_thread_id_key); - if (t_id == 0) { - t_id = pthread_mach_thread_np(pthread_self()); - pthread_setspecific(s_thread_id_key, (void *)(uintptr_t)t_id); - } - - return t_id; +thread_id current_thread_id() { + thread_info_for_logging_t thread_info; + thread_info.value = current_thread_info_for_logging(); + return thread_info.detail.t_id; } -FORCE_INLINE void set_curr_thread_ignore_logging(bool ignore) { - pthread_setspecific(s_ignore_logging_key, (void *)ignore); +void set_curr_thread_ignore_logging(bool ignore) { + thread_info_for_logging_t thread_info; + thread_info.value = current_thread_info_for_logging(); + thread_info.detail.is_ignore = ignore; + pthread_setspecific(s_thread_info_key, (void *)(uintptr_t)thread_info.value); } -FORCE_INLINE bool is_thread_ignoring_logging() { - return pthread_getspecific(s_ignore_logging_key); +bool is_thread_ignoring_logging() { + thread_info_for_logging_t thread_info; + thread_info.value = current_thread_info_for_logging(); + return thread_info.detail.is_ignore; } #pragma mark - #pragma mark Allocation/Deallocation Function without Logging -void logger_internal_init(void) { - pthread_key_create(&s_ignore_logging_key, NULL); - pthread_key_create(&s_thread_id_key, NULL); +bool logger_internal_init(void) { + return pthread_key_create(&s_thread_info_key, NULL) == 0; } void *inter_malloc(size_t size) { @@ -210,7 +182,6 @@ int inter_munmap(void *start, size_t length) { int ret = munmap(start, length); if (ret != 0) { __malloc_printf("munmap fail, %s, errno: %d", strerror(errno), errno); - abort(); } return ret; } else { @@ -218,7 +189,6 @@ int inter_munmap(void *start, size_t length) { int ret = munmap(start, length); if (ret != 0) { __malloc_printf("munmap fail, %s, errno: %d", strerror(errno), errno); - abort(); } set_curr_thread_ignore_logging(false); diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/logger_internal.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/logger_internal.h index bc48bd509..cb28c5ef4 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/logger_internal.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/logger_internal.h @@ -43,7 +43,7 @@ (memory_logging_type_generic | memory_logging_type_alloc | memory_logging_type_dealloc | memory_logging_type_vm_allocate \ | memory_logging_type_vm_deallocate | memory_logging_type_mapped_file_or_shared_mem | VM_FLAGS_ALIAS_MASK) -#define STACK_LOGGING_MAX_STACK_SIZE 60 +#define STACK_LOGGING_MAX_STACK_SIZE 48 #ifndef __FILE_NAME__ #define __FILE_NAME__ (strrchr(__FILE__, '/') + 1) @@ -56,12 +56,10 @@ log_internal(__FILE_NAME__, __LINE__, __FUNCTION__, msg); \ } while (0) -#define FORCE_INLINE __attribute__((always_inline)) - extern int err_code; // Lock Function -//#define USE_SPIN_LOCK +#define USE_SPIN_LOCK #ifdef USE_SPIN_LOCK @@ -69,11 +67,21 @@ extern int err_code; typedef OSSpinLock malloc_lock_s; -FORCE_INLINE malloc_lock_s __malloc_lock_init(); +__attribute__((always_inline)) inline malloc_lock_s __malloc_lock_init() { + return OS_SPINLOCK_INIT; +} + +__attribute__((always_inline)) inline void __malloc_lock_lock(malloc_lock_s *lock) { + OSSpinLockLock(lock); +} -FORCE_INLINE void __malloc_lock_lock(malloc_lock_s *lock); -FORCE_INLINE bool __malloc_lock_trylock(malloc_lock_s *lock); -FORCE_INLINE void __malloc_lock_unlock(malloc_lock_s *lock); +__attribute__((always_inline)) inline bool __malloc_lock_trylock(malloc_lock_s *lock) { + return OSSpinLockTry(lock); +} + +__attribute__((always_inline)) inline void __malloc_lock_unlock(malloc_lock_s *lock) { + OSSpinLockUnlock(lock); +} #else @@ -81,22 +89,43 @@ FORCE_INLINE void __malloc_lock_unlock(malloc_lock_s *lock); typedef os_unfair_lock malloc_lock_s; -FORCE_INLINE malloc_lock_s __malloc_lock_init(); +__attribute__((always_inline)) inline malloc_lock_s __malloc_lock_init() { + return OS_UNFAIR_LOCK_INIT; +} + +__attribute__((always_inline)) inline void __malloc_lock_lock(malloc_lock_s *lock) { + os_unfair_lock_lock(lock); +} -FORCE_INLINE void __malloc_lock_lock(malloc_lock_s *lock); -FORCE_INLINE bool __malloc_lock_trylock(malloc_lock_s *lock); -FORCE_INLINE void __malloc_lock_unlock(malloc_lock_s *lock); +__attribute__((always_inline)) inline bool __malloc_lock_trylock(malloc_lock_s *lock) { + return os_unfair_lock_trylock(lock); +} + +__attribute__((always_inline)) inline void __malloc_lock_unlock(malloc_lock_s *lock) { + os_unfair_lock_unlock(lock); +} #endif -// +// Thread Info for Logging typedef mach_port_t thread_id; -void logger_internal_init(void); +typedef union { + uint64_t value; + + struct { + uint32_t t_id; + bool is_ignore; + } detail; +} thread_info_for_logging_t; + +bool logger_internal_init(void); + +uint64_t current_thread_info_for_logging(); -FORCE_INLINE thread_id current_thread_id(); -FORCE_INLINE void set_curr_thread_ignore_logging(bool ignore); -FORCE_INLINE bool is_thread_ignoring_logging(); +thread_id current_thread_id(); +void set_curr_thread_ignore_logging(bool ignore); +bool is_thread_ignoring_logging(); // Allocation/Deallocation Function without Logging void *inter_malloc(size_t size); diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_logging.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_logging.cpp index 0cfa7357a..2c3992966 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_logging.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_logging.cpp @@ -33,8 +33,6 @@ #include #include -#include - #include "logger_internal.h" #include "memory_logging.h" #include "object_event_handler.h" @@ -56,11 +54,11 @@ static object_type_db *s_object_type_writer = NULL; static memory_logging_event_buffer_list *s_buffer_list = NULL; static memory_logging_event_buffer_pool *s_buffer_pool = NULL; -static pthread_key_t s_event_buffer_key = 0; - // activation variables static bool s_logging_is_enable = false; // set this to zero to stop logging memory ativities +int dump_call_stacks = 1; // 0 = not dump, 1 = dump all objects' call stacks, 2 = dump only objc objects' + // We set malloc_logger to NULL to disable logging, if we encounter errors // during file writing typedef void(malloc_logger_t)(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t result, uint32_t num_hot_frames_to_skip); @@ -71,18 +69,21 @@ extern malloc_logger_t *malloc_logger; static malloc_logger_t **syscall_logger; // use this to set up syscall logging (e.g., vm_allocate, vm_deallocate, mmap, munmap) #endif -thread_id s_main_thread_id = 0; static pthread_t s_working_thread = 0; static thread_id s_working_thread_id = 0; -//extern thread_id g_matrix_block_monitor_dumping_thread_id; +thread_id s_main_thread_id = 0; -static std::atomic_int s_working_thread_lock(0); // 1 is require for locking, 2 is should lock +static pthread_key_t s_event_buffer_key = 0; // Some callback in memory logging thread -static void (*s_dump_memory_callback)(void *, void *, void *, void *, void *, void *) = NULL; +static pthread_t s_dumping_thread = 0; +static std::shared_ptr s_memory_dump_data = NULL; +static summary_report_param s_memory_dump_param; +static void (*s_memory_dump_callback)(const char *, size_t) = NULL; // pre-declarations void *__memory_event_writing_thread(void *param); +void *__memory_event_dumping_thread(void *param); #pragma mark - #pragma mark Memory Logging @@ -112,6 +113,31 @@ bool __prepare_working_thread() { } } +bool __prepare_dumping_thread() { + int ret; + pthread_attr_t tattr; + sched_param param; + + /* initialized with default attributes */ + ret = pthread_attr_init(&tattr); + + /* safe to get existing scheduling param */ + ret = pthread_attr_getschedparam(&tattr, ¶m); + + /* set the highest priority; others are unchanged */ + param.sched_priority = MAX(sched_get_priority_max(SCHED_RR), param.sched_priority); + + /* setting the new scheduling param */ + ret = pthread_attr_setschedparam(&tattr, ¶m); + + if (pthread_create(&s_dumping_thread, &tattr, __memory_event_dumping_thread, (void *)s_memory_dump_callback) == KERN_SUCCESS) { + pthread_detach(s_dumping_thread); + return true; + } else { + return false; + } +} + #if __has_feature(ptrauth_calls) #include #endif @@ -182,8 +208,7 @@ __attribute__((noinline, not_tail_called)) static unsigned __thread_stack_pcs(ui } memory_logging_event_buffer *__new_event_buffer_and_lock(thread_id t_id) { - memory_logging_event_buffer *event_buffer = memory_logging_event_buffer_pool_new_buffer(s_buffer_pool); - event_buffer->t_id = t_id; + memory_logging_event_buffer *event_buffer = memory_logging_event_buffer_pool_new_buffer(s_buffer_pool, t_id); memory_logging_event_buffer_lock(event_buffer); memory_logging_event_buffer_list_push_back(s_buffer_list, event_buffer); pthread_setspecific(s_event_buffer_key, event_buffer); @@ -200,12 +225,6 @@ uint32_t type_flags, uintptr_t zone_ptr, uintptr_t arg2, uintptr_t arg3, uintptr return; } - if (is_thread_ignoring_logging()) { - // Prevent a thread from deadlocking against itself if vm_allocate() or malloc() - // is called below here, from woking thread or dumping thread - return; - } - uint32_t alias = 0; VM_GET_FLAGS_ALIAS(type_flags, alias); // skip all VM allocation events from malloc_zone @@ -213,6 +232,20 @@ uint32_t type_flags, uintptr_t zone_ptr, uintptr_t arg2, uintptr_t arg3, uintptr return; } + // skip allocation events from mapped_file + if (type_flags & memory_logging_type_mapped_file_or_shared_mem) { + return; + } + + thread_info_for_logging_t thread_info; + thread_info.value = current_thread_info_for_logging(); + + if (thread_info.detail.is_ignore) { + // Prevent a thread from deadlocking against itself if vm_allocate() or malloc() + // is called below here, from woking thread or dumping thread + return; + } + // check incoming data if ((type_flags & memory_logging_type_alloc) && (type_flags & memory_logging_type_dealloc)) { size = arg3; @@ -244,42 +277,46 @@ uint32_t type_flags, uintptr_t zone_ptr, uintptr_t arg2, uintptr_t arg3, uintptr is_alloc = true; } - type_flags &= memory_logging_valid_type_flags; + //type_flags &= memory_logging_valid_type_flags; - thread_id t_id = current_thread_id(); + thread_id t_id = thread_info.detail.t_id; memory_logging_event_buffer *event_buffer = (memory_logging_event_buffer *)pthread_getspecific(s_event_buffer_key); if (event_buffer == NULL || event_buffer->t_id != t_id) { event_buffer = __new_event_buffer_and_lock(t_id); } else { memory_logging_event_buffer_lock(event_buffer); - } - if (event_buffer->t_id != t_id) { - memory_logging_event_buffer_unlock(event_buffer); + // check t_id again + if (event_buffer->t_id != t_id) { + memory_logging_event_buffer_unlock(event_buffer); - event_buffer = __new_event_buffer_and_lock(t_id); + event_buffer = __new_event_buffer_and_lock(t_id); + } } // gather stack, only alloc type if (is_alloc) { - if (memory_logging_event_buffer_is_full(event_buffer, true)) { + if (memory_logging_event_buffer_is_full(event_buffer, dump_call_stacks == 1)) { memory_logging_event_buffer_unlock(event_buffer); event_buffer = __new_event_buffer_and_lock(t_id); } memory_logging_event *new_event = memory_logging_event_buffer_new_event(event_buffer); - new_event->stack_size = __thread_stack_pcs(new_event->stacks, STACK_LOGGING_MAX_STACK_SIZE, num_hot_to_skip); - //new_event->stack_size = backtrace((void **)new_event->stacks, STACK_LOGGING_MAX_STACK_SIZE); new_event->address = return_val; new_event->size = (uint32_t)size; new_event->object_type = 0; - new_event->t_id = t_id; new_event->type_flags = type_flags; - new_event->event_size = (uint32_t)write_size_by_event(new_event); new_event->event_type = EventType_Alloc; - - memory_logging_event_buffer_update_write_index_with_size(event_buffer, new_event->event_size); + if (dump_call_stacks == 1) { + new_event->stack_size = __thread_stack_pcs(new_event->stacks, STACK_LOGGING_MAX_STACK_SIZE, num_hot_to_skip); + new_event->event_size = (uint16_t)write_size_by_event(new_event); + memory_logging_event_buffer_update_write_index_with_size(event_buffer, new_event->event_size); + } else { + new_event->stack_size = 0; + new_event->event_size = MEMORY_LOGGING_EVENT_SIMPLE_SIZE; + memory_logging_event_buffer_update_write_index_with_size(event_buffer, MEMORY_LOGGING_EVENT_SIMPLE_SIZE); + } } else { // compaction memory_logging_event *last_event = memory_logging_event_buffer_last_event(event_buffer); @@ -305,12 +342,11 @@ uint32_t type_flags, uintptr_t zone_ptr, uintptr_t arg2, uintptr_t arg3, uintptr memory_logging_event *new_event = memory_logging_event_buffer_new_event(event_buffer); new_event->address = ptr_arg; - new_event->size = (uint32_t)size; new_event->type_flags = type_flags; new_event->event_size = MEMORY_LOGGING_EVENT_SIMPLE_SIZE; new_event->event_type = EventType_Free; - memory_logging_event_buffer_update_write_index_with_size(event_buffer, new_event->event_size); + memory_logging_event_buffer_update_write_index_with_size(event_buffer, MEMORY_LOGGING_EVENT_SIMPLE_SIZE); } memory_logging_event_buffer_unlock(event_buffer); @@ -321,50 +357,104 @@ void __memory_event_update_object(uint64_t address, uint32_t new_type) { return; } - if (is_thread_ignoring_logging()) { + thread_info_for_logging_t thread_info; + thread_info.value = current_thread_info_for_logging(); + + if (thread_info.detail.is_ignore) { return; } - thread_id t_id = current_thread_id(); + thread_id t_id = thread_info.detail.t_id; memory_logging_event_buffer *event_buffer = (memory_logging_event_buffer *)pthread_getspecific(s_event_buffer_key); if (event_buffer == NULL || event_buffer->t_id != t_id) { event_buffer = __new_event_buffer_and_lock(t_id); } else { memory_logging_event_buffer_lock(event_buffer); - } - if (event_buffer->t_id != t_id) { - memory_logging_event_buffer_unlock(event_buffer); + // check t_id again + if (event_buffer->t_id != t_id) { + memory_logging_event_buffer_unlock(event_buffer); - event_buffer = __new_event_buffer_and_lock(t_id); + event_buffer = __new_event_buffer_and_lock(t_id); + } } - // compaction - memory_logging_event *last_event = memory_logging_event_buffer_last_event(event_buffer); - if (last_event != NULL && last_event->address == address) { - if (last_event->type_flags & memory_logging_type_alloc) { - // skip events - last_event->object_type = new_type; + if (dump_call_stacks == 2) { + // compaction + memory_logging_event *last_event = memory_logging_event_buffer_last_event(event_buffer); + if (last_event != NULL && last_event->address == address) { + if (last_event->type_flags & memory_logging_type_alloc) { + // skip events + uint32_t size = last_event->size; + uint32_t type_flags = last_event->type_flags; + memory_logging_event_buffer_update_to_last_write_index(event_buffer); + + if (memory_logging_event_buffer_is_full(event_buffer, true)) { + memory_logging_event_buffer_unlock(event_buffer); + + event_buffer = __new_event_buffer_and_lock(t_id); + } + + memory_logging_event *new_event = memory_logging_event_buffer_new_event(event_buffer); + new_event->address = address; + new_event->size = size; + new_event->object_type = new_type; + new_event->type_flags = type_flags; + new_event->stack_size = __thread_stack_pcs(new_event->stacks, STACK_LOGGING_MAX_STACK_SIZE, 1); + new_event->event_size = (uint16_t)write_size_by_event(new_event); + new_event->event_type = EventType_Alloc; + memory_logging_event_buffer_update_write_index_with_size(event_buffer, new_event->event_size); + + memory_logging_event_buffer_unlock(event_buffer); + return; + } + } + + if (memory_logging_event_buffer_is_full(event_buffer, true)) { memory_logging_event_buffer_unlock(event_buffer); - return; + + event_buffer = __new_event_buffer_and_lock(t_id); } - } - if (memory_logging_event_buffer_is_full(event_buffer)) { + memory_logging_event *new_event = memory_logging_event_buffer_new_event(event_buffer); + new_event->address = address; + new_event->object_type = new_type; + new_event->type_flags = 0; + new_event->stack_size = __thread_stack_pcs(new_event->stacks, STACK_LOGGING_MAX_STACK_SIZE, 1); + new_event->event_size = (uint16_t)write_size_by_event(new_event); + new_event->event_type = EventType_Update; + memory_logging_event_buffer_update_write_index_with_size(event_buffer, new_event->event_size); + memory_logging_event_buffer_unlock(event_buffer); + } else { + // compaction + memory_logging_event *last_event = memory_logging_event_buffer_last_event(event_buffer); + if (last_event != NULL && last_event->address == address) { + if (last_event->type_flags & memory_logging_type_alloc) { + // skip events + last_event->object_type = new_type; + memory_logging_event_buffer_unlock(event_buffer); + return; + } + } - event_buffer = __new_event_buffer_and_lock(t_id); - } + if (memory_logging_event_buffer_is_full(event_buffer)) { + memory_logging_event_buffer_unlock(event_buffer); - memory_logging_event *new_event = memory_logging_event_buffer_new_event(event_buffer); - new_event->address = address; - new_event->object_type = new_type; - new_event->event_size = MEMORY_LOGGING_EVENT_SIMPLE_SIZE; - new_event->event_type = EventType_Update; + event_buffer = __new_event_buffer_and_lock(t_id); + } - memory_logging_event_buffer_update_write_index_with_size(event_buffer, new_event->event_size); + memory_logging_event *new_event = memory_logging_event_buffer_new_event(event_buffer); + new_event->address = address; + new_event->object_type = new_type; + new_event->type_flags = 0; + new_event->stack_size = 0; + new_event->event_size = MEMORY_LOGGING_EVENT_SIMPLE_SIZE; + new_event->event_type = EventType_Update; + memory_logging_event_buffer_update_write_index_with_size(event_buffer, MEMORY_LOGGING_EVENT_SIMPLE_SIZE); - memory_logging_event_buffer_unlock(event_buffer); + memory_logging_event_buffer_unlock(event_buffer); + } } #pragma mark - Writing Process @@ -376,23 +466,18 @@ void *__memory_event_writing_thread(void *param) { s_working_thread_id = current_thread_id(); log_internal_without_this_thread(s_working_thread_id); - + int usleep_time = 0; // Wait for enable_memory_logging finished - usleep(30000); + while (s_logging_is_enable == false) { + usleep(10000); + } while (s_logging_is_enable) { bool thread_is_woken = false; - - // Can't lock like this without brain, or affect performance - if (s_working_thread_lock == 1) { - s_working_thread_lock = 2; - while (s_working_thread_lock == 2) - ; - } - memory_logging_event_buffer *event_buffer = memory_logging_event_buffer_list_reset(s_buffer_list); + memory_logging_event_buffer *event_buffer = memory_logging_event_buffer_list_pop_all(s_buffer_list); while (event_buffer != NULL) { memory_logging_event_buffer_lock(event_buffer); event_buffer->t_id = 0; @@ -403,9 +488,24 @@ void *__memory_event_writing_thread(void *param) { while (curr_event != NULL) { if (curr_event->event_type == EventType_Alloc) { - if (is_stack_frames_should_skip(curr_event->stacks, curr_event->stack_size, curr_event->size, curr_event->type_flags) == false) { - uint32_t stack_identifier = - add_stack_frames_in_table(s_stack_frames_writer, curr_event->stacks, curr_event->stack_size); // unique stack in memory + if (curr_event->stack_size > 0) { + if (is_stack_frames_should_skip(curr_event->stacks, curr_event->stack_size, curr_event->size) == false) { + // unique stack in memory + uint32_t stack_identifier = add_stack_frames_in_table(s_stack_frames_writer, curr_event->stacks, curr_event->stack_size); + + // Try to get vm memory type from type_flags + uint32_t object_type = curr_event->object_type; + if (object_type == 0) { + VM_GET_FLAGS_ALIAS(curr_event->type_flags, object_type); + } + allocation_event_db_add(s_allocation_event_writer, + curr_event->address, + curr_event->type_flags, + object_type, + curr_event->size, + stack_identifier); + } + } else { // Try to get vm memory type from type_flags uint32_t object_type = curr_event->object_type; if (object_type == 0) { @@ -416,23 +516,44 @@ void *__memory_event_writing_thread(void *param) { curr_event->type_flags, object_type, curr_event->size, - stack_identifier, - curr_event->t_id); + 0); } } else if (curr_event->event_type == EventType_Free) { allocation_event_db_del(s_allocation_event_writer, curr_event->address, curr_event->type_flags); } else if (curr_event->event_type == EventType_Update) { - allocation_event_db_update_object_type(s_allocation_event_writer, curr_event->address, curr_event->object_type); + if (curr_event->stack_size > 0) { + if (is_stack_frames_should_skip(curr_event->stacks, curr_event->stack_size, curr_event->size) == false) { + // unique stack in memory + uint32_t stack_identifier = add_stack_frames_in_table(s_stack_frames_writer, curr_event->stacks, curr_event->stack_size); + + allocation_event_db_update_object_type_and_stack_identifier(s_allocation_event_writer, + curr_event->address, + curr_event->object_type, + stack_identifier); + } else { + allocation_event_db_update_object_type(s_allocation_event_writer, curr_event->address, curr_event->object_type); + } + } else { + allocation_event_db_update_object_type(s_allocation_event_writer, curr_event->address, curr_event->object_type); + } } else if (curr_event->event_type != EventType_Invalid) { disable_memory_logging(); report_error(MS_ERRC_DATA_CORRUPTED); __malloc_printf("Data corrupted?!"); - return NULL; + break; // Restore abort()? } - curr_event = memory_logging_event_buffer_next(event_buffer); + if (s_logging_is_enable == false) { + break; + } + + curr_event = memory_logging_event_buffer_next(event_buffer, curr_event); + } + + if (s_logging_is_enable == false) { + break; } memory_logging_event_buffer *next_event_buffer = event_buffer->next_event_buffer; @@ -442,20 +563,66 @@ void *__memory_event_writing_thread(void *param) { event_buffer = next_event_buffer; } - if (s_dump_memory_callback) { - s_dump_memory_callback(NULL, NULL, s_allocation_event_writer, s_stack_frames_writer, s_dyld_image_info_writer, s_object_type_writer); - s_dump_memory_callback = NULL; + if (s_logging_is_enable == false) { + break; + } + + if (s_memory_dump_callback && s_memory_dump_data == NULL) { + s_memory_dump_data = generate_summary_report_i(s_allocation_event_writer, + s_stack_frames_writer, + s_dyld_image_info_writer, + s_object_type_writer, + s_memory_dump_param); + __prepare_dumping_thread(); } if (thread_is_woken == false) { - if (usleep_time < 20000) { - usleep_time += 10000; + if (usleep_time < 15000) { + usleep_time += 5000; } usleep(usleep_time); } else { usleep_time = 0; } } + + log_internal_without_this_thread(0); + + usleep(100000); + + stack_frames_db_close(s_stack_frames_writer); + s_stack_frames_writer = NULL; + + allocation_event_db_close(s_allocation_event_writer); + s_allocation_event_writer = NULL; + + dyld_image_info_db_close(s_dyld_image_info_writer); + s_dyld_image_info_writer = NULL; + + object_type_db_close(s_object_type_writer); + s_object_type_writer = NULL; + + memory_logging_event_buffer_pool_free(s_buffer_pool); + s_buffer_pool = NULL; + + memory_logging_event_buffer_list_free(s_buffer_list); + s_buffer_list = NULL; + + __malloc_printf("memory logging cleanup finished\n"); + + return NULL; +} + +void *__memory_event_dumping_thread(void *param) { + pthread_setname_np("Memory Dumping"); + + set_curr_thread_ignore_logging(true); // for preventing deadlock'ing on memory logging on a single thread + + void (*memory_dump_callback)(const char *, size_t) = (void (*)(const char *, size_t))param; + memory_dump_callback(s_memory_dump_data->c_str(), s_memory_dump_data->size()); + s_memory_dump_data = NULL; + s_memory_dump_callback = NULL; + return NULL; } @@ -504,6 +671,10 @@ bool is_analysis_tool_running(void) { int enable_memory_logging(const char *log_dir) { err_code = MS_ERRC_SUCCESS; + if (logger_internal_init() == false) { + return MS_ERRC_WORKING_THREAD_CREATE_FAIL; + } + // Check whether there's any analysis tool process logging memory. if (is_analysis_tool_running()) { return MS_ERRC_ANALYSIS_TOOL_RUNNING; @@ -514,9 +685,11 @@ int enable_memory_logging(const char *log_dir) { return err_code; } - s_stack_frames_writer = stack_frames_db_open_or_create(log_dir); - if (s_stack_frames_writer == NULL) { - return err_code; + if (dump_call_stacks != 0) { + s_stack_frames_writer = stack_frames_db_open_or_create(log_dir); + if (s_stack_frames_writer == NULL) { + return err_code; + } } s_dyld_image_info_writer = prepare_dyld_image_logger(log_dir); @@ -539,13 +712,16 @@ int enable_memory_logging(const char *log_dir) { return err_code; } + if (pthread_key_create(&s_event_buffer_key, NULL) != 0) { + __malloc_printf("pthread_key_create fail"); + return MS_ERRC_WORKING_THREAD_CREATE_FAIL; + } + if (__prepare_working_thread() == false) { __malloc_printf("create writing thread fail"); return MS_ERRC_WORKING_THREAD_CREATE_FAIL; } - pthread_key_create(&s_event_buffer_key, NULL); - malloc_logger = __memory_event_callback; #ifdef USE_PRIVATE_API @@ -556,13 +732,13 @@ int enable_memory_logging(const char *log_dir) { } #endif - if (pthread_main_np()) { - s_main_thread_id = current_thread_id(); - } else { + if (pthread_main_np() == 0) { // memory logging shoule be enable in main thread abort(); + } else { + s_main_thread_id = current_thread_id(); } - logger_internal_init(); + s_logging_is_enable = true; return MS_ERRC_SUCCESS; @@ -577,9 +753,6 @@ void disable_memory_logging(void) { return; } - log_internal_without_this_thread(0); - __malloc_printf("memory logging disabled due to previous errors.\n"); - s_logging_is_enable = false; disable_object_event_logger(); @@ -590,48 +763,26 @@ void disable_memory_logging(void) { } #endif - // avoid that after the memory monitoring stops, there are still some events being written. - //memory_logging_event_buffer_pool_free(s_buffer_pool); - //allocation_event_db_close(s_allocation_event_writer); - //stack_frames_db_close(s_stack_frames_writer); // make current logging invalid - set_memory_logging_invalid(); -} - -uint32_t get_current_thread_memory_usage() { - if (!s_logging_is_enable || !s_allocation_event_writer) { - return 0; - } - - __block uint32_t total = 0; - __block thread_id curr_thread = current_thread_id(); + //set_memory_logging_invalid(); - s_working_thread_lock = 1; - while (s_working_thread_lock != 2) - ; - - allocation_event_db_enumerate(s_allocation_event_writer, ^(const uint64_t &address, const allocation_event &event) { - if (event.t_id == curr_thread) { - total += event.size; - } - }); - - s_working_thread_lock = 0; - - return total; + log_internal_without_this_thread(0); + __malloc_printf("memory logging disabled due to previous errors\n"); } -bool dump_memory(void (*callback)(void *, void *, void *, void *, void *, void *)) { +bool memory_dump(void (*callback)(const char *, size_t), summary_report_param param) { if (!s_logging_is_enable) { - __malloc_printf("memory logging is disabled.\n"); + __malloc_printf("memory logging is disabled\n"); return false; } - if (s_dump_memory_callback) { - __malloc_printf("s_dump_memory_callback is not null.\n"); + if (s_memory_dump_callback) { + __malloc_printf("memory_dump_callback is not NULL\n"); return false; } - s_dump_memory_callback = callback; + s_memory_dump_param = param; + s_memory_dump_callback = callback; + return true; } diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_logging.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_logging.h index 22121e025..b6c494dd9 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_logging.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_logging.h @@ -17,11 +17,12 @@ #import #import +#include "memory_report_generator.h" #include "memory_stat_err_code.h" +extern int dump_call_stacks; + int enable_memory_logging(const char *log_dir); void disable_memory_logging(void); -uint32_t get_current_thread_memory_usage(void); - -bool dump_memory(void (*callback)(void *, void *, void *, void *, void *, void *)); +bool memory_dump(void (*callback)(const char *, size_t), summary_report_param param); diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_report_generator.cpp b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_report_generator.cpp index 9cab39446..21ded6084 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_report_generator.cpp +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_report_generator.cpp @@ -36,14 +36,20 @@ struct allocation_stack { template void Serialize(Writer &writer, stack_frames_db *stack_frames_reader, dyld_image_info_db *dyld_image_info_reader) { // Parse the stack first uint32_t fcount = 0; - uint64_t frames[64]; - char const *uuids[64]; - char const *image_names[64]; - bool is_app_image[64]; + uint64_t frames[STACK_LOGGING_MAX_STACK_SIZE]; + char const *uuids[STACK_LOGGING_MAX_STACK_SIZE]; + char const *image_names[STACK_LOGGING_MAX_STACK_SIZE]; + bool is_app_image[STACK_LOGGING_MAX_STACK_SIZE]; - unwind_stack_from_table_index(stack_frames_reader, stack_identifier, frames, &fcount, 64); - if (fcount <= 0) + if (stack_frames_reader == NULL) { return; + } + + unwind_stack_from_table_index(stack_frames_reader, stack_identifier, frames, &fcount, STACK_LOGGING_MAX_STACK_SIZE); + if (fcount <= 0) { + return; + } + dyld_image_info_db_transform_frames(dyld_image_info_reader, frames, frames, uuids, image_names, is_app_image, fcount); // Find Responsible Caller, priority app symbol, if not found, have to find the first stack symbol; skip the main symbol @@ -153,6 +159,11 @@ struct allocation_category { writer.String("count"); writer.Uint64(count); + if (stacks.size() == 0) { + writer.EndObject(); + return; + } + // Take top N or assign a size larger than 1M or UI category if (size >= 1024 * 1024 || index < 15) { std::sort(stacks.begin(), stacks.end(), comparison_allocation_stack); @@ -225,7 +236,7 @@ std::shared_ptr generate_summary_report(const char *event_dir, cons dyld_image_info_db *dyld_image_info_reader = dyld_image_info_db_open_or_create(event_dir); object_type_db *object_type_reader = object_type_db_open_or_create(event_dir); - if (!allocation_event_reader || !stack_frames_reader || !dyld_image_info_reader || !object_type_reader) { + if (!allocation_event_reader || !dyld_image_info_reader || !object_type_reader) { allocation_event_db_close(allocation_event_reader); stack_frames_db_close(stack_frames_reader); dyld_image_info_db_close(dyld_image_info_reader); @@ -252,13 +263,10 @@ std::shared_ptr generate_summary_report_i(allocation_event_db *allo // Classify alloc events first std::unordered_map *category_map = new std::unordered_map(); // key=object_type allocation_event_db_enumerate(allocation_event_reader, ^(const uint64_t &address, const allocation_event &event) { - if (event.stack_identifier == 0) { - //__malloc_printf("address: %lld, objtype: %u, size: %d", event.address, event.object_type, event.size); - return; - } - uint64_t object_type = event.object_type; uint64_t org_address = address; //ORIGINL_ADDRESS_FROM_ADDRESS(event.address); + // align to 16 + uint32_t event_size = (((event.size + 15) >> 4) << 4); // if object_type=0 // 1. If the assignment fails, it is classified into Alloc Fail @@ -269,7 +277,7 @@ std::shared_ptr generate_summary_report_i(allocation_event_db *allo if (org_address == 0) { object_type = UINT32_MAX; } else if (event.alloca_type & memory_logging_type_alloc) { - object_type = (((uint64_t)1 << 32) | event.size); + object_type = (((uint64_t)1 << 32) | event_size); } else if (event.alloca_type & memory_logging_type_vm_allocate) { object_type = (((uint64_t)2 << 32)); } else { @@ -295,12 +303,12 @@ std::shared_ptr generate_summary_report_i(allocation_event_db *allo sprintf(buff, "Alloc Fail"); new_category->name = buff; } else if (event.alloca_type & memory_logging_type_alloc) { - if (event.size < 1024) { - sprintf(buff, "Malloc %u Bytes", event.size); - } else if (event.size < 1024 * 1024) { - sprintf(buff, "Malloc %0.02f KiB", event.size / 1024.0); + if (event_size < 1024) { + sprintf(buff, "Malloc %u Bytes", event_size); + } else if (event_size < 1024 * 1024) { + sprintf(buff, "Malloc %0.02f KiB", event_size / 1024.0); } else { - sprintf(buff, "Malloc %0.02f MiB", event.size / (1024.0 * 1024.0)); + sprintf(buff, "Malloc %0.02f MiB", event_size / (1024.0 * 1024.0)); } new_category->name = buff; } else if (event.alloca_type & memory_logging_type_vm_allocate) { @@ -314,21 +322,23 @@ std::shared_ptr generate_summary_report_i(allocation_event_db *allo iter = category_map->insert(std::make_pair(object_type, new_category)).first; } - iter->second->size += event.size; + iter->second->size += event_size; iter->second->count++; // After finding the object classification, sort by stack type - auto iter2 = iter->second->stack_map.find(event.stack_identifier); - if (iter2 == iter->second->stack_map.end()) { - allocation_stack *new_stack = new allocation_stack(); - new_stack->stack_identifier = event.stack_identifier; - new_stack->is_nsobject = object_type_db_is_nsobject(object_type_reader, event.object_type); - iter->second->stacks.push_back(new_stack); - iter2 = iter->second->stack_map.insert(std::make_pair(event.stack_identifier, new_stack)).first; - } + if (event.stack_identifier > 0) { + auto iter2 = iter->second->stack_map.find(event.stack_identifier); + if (iter2 == iter->second->stack_map.end()) { + allocation_stack *new_stack = new allocation_stack(); + new_stack->stack_identifier = event.stack_identifier; + new_stack->is_nsobject = object_type_db_is_nsobject(object_type_reader, event.object_type); + iter->second->stacks.push_back(new_stack); + iter2 = iter->second->stack_map.insert(std::make_pair(event.stack_identifier, new_stack)).first; + } - iter2->second->size += event.size; - iter2->second->count++; + iter2->second->size += event_size; + iter2->second->count++; + } }); // map to vector @@ -374,6 +384,7 @@ std::shared_ptr generate_summary_report_i(allocation_event_db *allo // serialize to json rapidjson::StringBuffer sb; rapidjson::PrettyWriter writer(sb); + writer.SetIndent(' ', 0); writer.SetFormatOptions(rapidjson::kFormatSingleLineArray); writer.StartObject(); @@ -386,7 +397,7 @@ std::shared_ptr generate_summary_report_i(allocation_event_db *allo // Take top M or malloc size > 1M category for (int i = 0; i < category_list->size(); ++i) { allocation_category *category = (*category_list)[i]; - category->Serialize(writer, i, stack_frames_reader, dyld_image_info_reader, param.app_uuid, param.foom_scene); + category->Serialize(writer, i, stack_frames_reader, dyld_image_info_reader, param.app_uuid, (i == 0 ? param.foom_scene : "")); } writer.EndArray(); @@ -400,27 +411,3 @@ std::shared_ptr generate_summary_report_i(allocation_event_db *allo return std::make_shared(sb.GetString()); } - -std::unordered_map thread_alloc_size(const char *event_dir) { - allocation_event_db *allocation_event_reader = allocation_event_db_open_or_create(event_dir); - - if (!allocation_event_reader) { - allocation_event_db_close(allocation_event_reader); - return std::unordered_map(); - } - - std::unordered_map alloc_sizes; - std::unordered_map *alloc_sizes_in_block = &alloc_sizes; - allocation_event_db_enumerate(allocation_event_reader, ^(const uint64_t &address, const allocation_event &event) { - auto iter = alloc_sizes_in_block->find(event.t_id); - if (iter != alloc_sizes_in_block->end()) { - iter->second += event.size; - } else { - alloc_sizes_in_block->insert(std::make_pair(event.t_id, event.size)); - } - }); - - allocation_event_db_close(allocation_event_reader); - - return alloc_sizes; -} diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_report_generator.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_report_generator.h index 6301735d8..f5b6feaf4 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_report_generator.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryLogger/memory_report_generator.h @@ -78,6 +78,5 @@ struct object_type_db; std::shared_ptr generate_summary_report(const char *event_dir, const summary_report_param ¶m); std::shared_ptr generate_summary_report_i(allocation_event_db *, stack_frames_db *, dyld_image_info_db *, object_type_db *, const summary_report_param ¶m); -std::unordered_map thread_alloc_size(const char *event_dir); #endif /* stack_report_generator_h */ diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryRecordManager.mm b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryRecordManager.mm index f10c3b61c..1cd69ff40 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryRecordManager.mm +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryRecordManager.mm @@ -17,6 +17,7 @@ #import "WCMemoryRecordManager.h" #import "MatrixPathUtil.h" #import "MatrixLogDef.h" +#import "dyld_image_info.h" @interface WCMemoryRecordManager () { NSMutableArray *m_recordList; @@ -129,16 +130,34 @@ - (void)loadRecordList { } } - // just limit 3 record - if (m_recordList.count > 3) { + // delete records whose 'appUUID' not equal to curr uuid + NSString *appUUID = @(app_uuid()); + NSMutableArray *removed = [NSMutableArray array]; + for (int i = 0; i < m_recordList.count; ++i) { + MemoryRecordInfo *record = m_recordList[i]; + if (appUUID && [appUUID isEqualToString:record.appUUID] == NO) { + NSString *eventPath = [record recordDataPath]; + [[NSFileManager defaultManager] removeItemAtPath:eventPath error:NULL]; + [removed addObject:record]; + } + } + if (removed.count > 0) { + [m_recordList removeObjectsInArray:removed]; + [self saveRecordList]; + } + +#define RECORD_MAX_COUNT 2 + + // just limit N record + if (m_recordList.count > RECORD_MAX_COUNT) { [self sortRecordList]; - for (int i = 3; i < m_recordList.count; ++i) { + for (int i = RECORD_MAX_COUNT; i < m_recordList.count; ++i) { MemoryRecordInfo *record = m_recordList[i]; NSString *eventPath = [record recordDataPath]; [[NSFileManager defaultManager] removeItemAtPath:eventPath error:NULL]; } - [m_recordList removeObjectsInRange:NSMakeRange(3, m_recordList.count - 3)]; + [m_recordList removeObjectsInRange:NSMakeRange(RECORD_MAX_COUNT, m_recordList.count - RECORD_MAX_COUNT)]; [self saveRecordList]; } diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryStatModel.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryStatModel.h index 2753158e2..cb8f3f6a4 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryStatModel.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryStatModel.h @@ -18,27 +18,16 @@ #import "MatrixBaseModel.h" -// record the thread info -@interface MSThreadInfo : MatrixBaseModel - -@property (nonatomic, strong) NSString *threadName; -@property (nonatomic, assign) UInt64 allocSize; - -@end - @interface MemoryRecordInfo : MatrixBaseModel @property (nonatomic, assign) uint64_t launchTime; @property (nonatomic, strong) NSString *userScene; @property (nonatomic, strong) NSString *systemVersion; @property (nonatomic, strong) NSString *appUUID; -@property (nonatomic, strong) NSMutableDictionary *threadInfos; - (NSString *)recordID; - (NSString *)recordDataPath; - (NSData *)generateReportDataWithCustomInfo:(NSDictionary *)customInfo; -- (void)calculateAllThreadsMemoryUsage; - @end diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryStatModel.mm b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryStatModel.mm index ec5b934fb..4afe7d52d 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryStatModel.mm +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/Record/WCMemoryStatModel.mm @@ -21,16 +21,11 @@ #import "memory_logging.h" #import "memory_report_generator.h" -@implementation MSThreadInfo - -@end - @implementation MemoryRecordInfo - (id)init { self = [super init]; if (self) { - self.threadInfos = [[NSMutableDictionary alloc] init]; self.userScene = @""; self.systemVersion = @""; self.appUUID = @""; @@ -68,15 +63,4 @@ - (NSData *)generateReportDataWithCustomInfo:(NSDictionary *)customInfo { return [NSData dataWithBytes:content->c_str() length:content->size()]; } -- (void)calculateAllThreadsMemoryUsage { - std::unordered_map threadAllocSizes = thread_alloc_size([self recordDataPath].UTF8String); - - for (NSString *threadID in self.threadInfos.allKeys) { - auto iter = threadAllocSizes.find([threadID intValue]); - if (iter != threadAllocSizes.end()) { - self.threadInfos[threadID].allocSize = iter->second; - } - } -} - @end diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatConfig.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatConfig.h index 61845640c..ff3c34535 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatConfig.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatConfig.h @@ -35,6 +35,8 @@ typedef NS_ENUM(NSUInteger, EWCMemStatReportStrategy) { // the stack also be saved. Default to 8 @property (nonatomic, assign) int skipMaxStackDepth; +@property (nonatomic, assign) int dumpCallStacks; // 0 = not dump, 1 = dump all objects' call stacks, 2 = dump only objc objects' + @property (nonatomic, assign) EWCMemStatReportStrategy reportStrategy; @end diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatConfig.mm b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatConfig.mm index 0df363e46..0f0ccbea1 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatConfig.mm +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatConfig.mm @@ -23,6 +23,7 @@ + (WCMemoryStatConfig *)defaultConfiguration { WCMemoryStatConfig *config = [[WCMemoryStatConfig alloc] init]; config.skipMinMallocSize = (int)vm_page_size; config.skipMaxStackDepth = 8; + config.dumpCallStacks = 1; config.reportStrategy = EWCMemStatReportStrategy_Auto; return config; } diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatPlugin.h b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatPlugin.h index 9d13ff66a..774c714b0 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatPlugin.h +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatPlugin.h @@ -42,17 +42,7 @@ - (MatrixIssue *)uploadReport:(MemoryRecordInfo *)record withCustomInfo:(NSDictionary *)customInfo; -// ============================================================================ -#pragma mark - Current Thread -// ============================================================================ - -/// add a tag to current thread, then you can distinguish it from threads. -- (void)addTagToCurrentThread:(NSString *)tagString; -/// remove the tag of current thread. -- (void)removeTagOfCurrentThread; - -- (uint32_t)getMemoryUsageOfCurrentThread; -- (void)dumpMemoryAndGenerateReportData:(NSString *)issue customInfo:(NSDictionary *)customInfo callback:(void (^)(NSData *))callback; +- (void)memoryDumpAndGenerateReportData:(NSString *)issue customInfo:(NSDictionary *)customInfo callback:(void (^)(NSData *))callback; // ============================================================================ #pragma mark - Record diff --git a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatPlugin.mm b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatPlugin.mm index 16b620368..28aeefa93 100644 --- a/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatPlugin.mm +++ b/matrix/matrix-iOS/Matrix/WCMemoryStat/MemoryStatPlugin/WCMemoryStatPlugin.mm @@ -22,7 +22,6 @@ #import "MatrixDeviceInfo.h" #import "memory_logging.h" -#import "memory_report_generator.h" #import "logger_internal.h" #import "dyld_image_info.h" @@ -36,6 +35,24 @@ #define g_matrix_memory_stat_plguin_tag "MemoryStat" +// ============================================================================ +#pragma mark - Memory dump callback +// ============================================================================ + +static void (^s_callback)(NSData *) = nil; + +void memory_dump_callback(const char *data, size_t len) { + @autoreleasepool { + NSData *reportData = [NSData dataWithBytes:(void *)data length:len]; + s_callback(reportData); + s_callback = nil; + } +} + +// ============================================================================ +#pragma mark - WCMemoryStatPlugin +// ============================================================================ + @interface WCMemoryStatPlugin () { WCMemoryRecordManager *m_recordManager; @@ -125,64 +142,28 @@ - (MatrixIssue *)uploadReport:(MemoryRecordInfo *)record withCustomInfo:(NSDicti return issue; } -// ============================================================================ -#pragma mark - Current Thread -// ============================================================================ - -- (void)addTagToCurrentThread:(NSString *)tagString { - if (m_currRecord == nil) { - return; - } - MSThreadInfo *threadInfo = [[MSThreadInfo alloc] init]; - threadInfo.threadName = tagString; - [m_currRecord.threadInfos setObject:threadInfo forKey:[NSString stringWithFormat:@"%u", current_thread_id()]]; - [m_recordManager updateRecord:m_currRecord]; -} - -- (void)removeTagOfCurrentThread { - if (m_currRecord == nil) { - return; - } - [m_currRecord.threadInfos removeObjectForKey:[NSString stringWithFormat:@"%u", current_thread_id()]]; - [m_recordManager updateRecord:m_currRecord]; -} - -- (uint32_t)getMemoryUsageOfCurrentThread { - return get_current_thread_memory_usage(); -} - -- (void)dumpMemoryAndGenerateReportData:(NSString *)issue customInfo:(NSDictionary *)customInfo callback:(void (^)(NSData *))callback { +- (void)memoryDumpAndGenerateReportData:(NSString *)issue customInfo:(NSDictionary *)customInfo callback:(void (^)(NSData *))callback { if (m_currRecord == nil) { MatrixInfo(@"memstat is not running"); return; } - __block IMP dump_memory_callback = imp_implementationWithBlock(^(void *self, void *p0, void *p1, void *p2, void *p3) { - @autoreleasepool { - summary_report_param param; - param.phone = [MatrixDeviceInfo platform].UTF8String; - param.os_ver = [MatrixDeviceInfo systemVersion].UTF8String; - param.launch_time = [MatrixAppRebootAnalyzer appLaunchTime] * 1000; - param.report_time = [[NSDate date] timeIntervalSince1970] * 1000; - param.app_uuid = app_uuid(); - param.foom_scene = issue.UTF8String; - - for (id key in customInfo) { - std::string stdKey = [key UTF8String]; - std::string stdVal = [[customInfo[key] description] UTF8String]; - param.customInfo.insert(std::make_pair(stdKey, stdVal)); - } - - auto content = - generate_summary_report_i((allocation_event_db *)p0, (stack_frames_db *)p1, (dyld_image_info_db *)p2, (object_type_db *)p3, param); - NSData *reportData = [NSData dataWithBytes:content->c_str() length:content->size()]; - callback(reportData); - imp_removeBlock(dump_memory_callback); - } - }); + summary_report_param param; + param.phone = [MatrixDeviceInfo platform].UTF8String; + param.os_ver = [MatrixDeviceInfo systemVersion].UTF8String; + param.launch_time = [MatrixAppRebootAnalyzer appLaunchTime] * 1000; + param.report_time = [[NSDate date] timeIntervalSince1970] * 1000; + param.app_uuid = app_uuid(); + param.foom_scene = issue.UTF8String; + + for (id key in customInfo) { + std::string stdKey = [key UTF8String]; + std::string stdVal = [[customInfo[key] description] UTF8String]; + param.customInfo.insert(std::make_pair(stdKey, stdVal)); + } - if (dump_memory((void (*)(void *, void *, void *, void *, void *, void *))dump_memory_callback) == false) { - imp_removeBlock(dump_memory_callback); + if (memory_dump(memory_dump_callback, param)) { + s_callback = callback; } } @@ -250,9 +231,11 @@ - (BOOL)start { if (self.pluginConfig == nil) { self.pluginConfig = [WCMemoryStatConfig defaultConfiguration]; } + if (self.pluginConfig) { skip_max_stack_depth = self.pluginConfig.skipMaxStackDepth; skip_min_malloc_size = self.pluginConfig.skipMinMallocSize; + dump_call_stacks = self.pluginConfig.dumpCallStacks; } m_currRecord = [[MemoryRecordInfo alloc] init]; diff --git a/samples/sample-iOS/MatrixDemo/MatrixDemo/TestOOMViewController.mm b/samples/sample-iOS/MatrixDemo/MatrixDemo/TestOOMViewController.mm index d34a456af..a768c258e 100644 --- a/samples/sample-iOS/MatrixDemo/MatrixDemo/TestOOMViewController.mm +++ b/samples/sample-iOS/MatrixDemo/MatrixDemo/TestOOMViewController.mm @@ -116,7 +116,6 @@ - (void)testOOM NSLog(@"Make OOM"); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [[[MatrixHandler sharedInstance] getMemoryStatPlugin] addTagToCurrentThread:@"com.wechat.memdemo1"]; NSMutableArray *array = [NSMutableArray array]; while (1) { TestContact *contact = [[TestContact alloc] init];