参考资料
Introduction to Code Size Performance Guidelines
Important: This document may not represent best practices for current development. Links to downloads and other resources may no longer be valid.
In the context of performance, there is a distinct correlation between memory usage and efficiency. The more memory your application occupies, the more inefficient it is going to be. More memory means more memory allocations, more code, and a greater potential for paging.
The focus of this programming topic is on the reduction of your executable code. Reducing your code footprint is not just a matter of turning on code optimizations in your compiler, although that does help. You can also reduce your code footprint by organizing your code so that only the minimum set of required functions is in memory at any given time. You implement this optimization by profiling your code.
Reducing the amount of memory allocated by your application is also important in reducing your memory footprint; however, that information is covered in Memory Usage Performance Guidelines in Performance Documentation.
Organization of This Document
This programming topic contains the following articles:
Overview of the Mach-O Executable Format describes how to use the organization of the Mach-O executable format to improve the efficiency of your code.
Managing Code Size describes several compiler options that you can use to reduce the overall size of your executables.
Improving Locality of Reference describes how to profile and reorganize your code to improve loading times for code segments.
Reducing Shared Memory Pages describes ways to reduce the size of your __DATA segments.
Minimizing Your Exported Symbols shows how you identify and eliminate unnecessary symbol information in your code.
show code
char * str __attribute((used,section("__DATA,Test"))) = "Hello world";
//使用 used字段,即使没有任何引用,在Release下也不会被优化
#define WriteSection(sectName) __attribute((used, section("__DATA,"#sectName" ")))
#define SectionDataWithKeyValue(key,value) char * k##key WriteSection(CustomSection) = "{ \""#key"\" : \""#value"\"}";
// 注入 :
SectionDataWithKeyValue(url, www.baidu.com)
static NSString *configuration = @"";
const struct mach_header_64 *machHeader = NULL;
int main(int argc, const char * argv[]) {
Person *p = [[Person alloc] init];
NSString *sectionName = @"__objc_methname";
NSMutableArray *configs = [NSMutableArray array];
if (machHeader == NULL)
{
Dl_info info;
dladdr((__bridge const void *)(configuration), &info);
machHeader = (struct mach_header_64*)info.dli_fbase;
}
unsigned long size = 0;
uint8_t *memory = getsectiondata(machHeader, SEG_TEXT, [sectionName UTF8String], & size);
NSUInteger counter = size/sizeof(void*);
NSError *converError = nil;
for(int idx = 0; idx < counter; ++idx){
char *string = (char*)memory[idx];
NSString *str = [NSString stringWithUTF8String:string];
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&converError];
if (json && [json isKindOfClass:[NSDictionary class]])
{
[configs addObject:json];
}
}
return 0;
}
获取所有加载的镜像的回调:
+ (void)load
{
_dyld_register_func_for_add_image(&image_added);
_dyld_register_func_for_remove_image(&image_removed);
}
方法如下:
static void image_added(const struct mach_header *mh, intptr_t slide)
{
_print_image(mh, true);
}
static void image_removed(const struct mach_header *mh, intptr_t slide)
{
_print_image(mh, false);
}
以下是具体的_print_image
方法:
static void _print_image(const struct mach_header *mh, bool added)
{
Dl_info image_info;
int result = dladdr(mh, &image_info);
if (result == 0) {
printf("Could not print info for mach_header: %p\n\n", mh);
return;
}
const char *image_name = image_info.dli_fname;
const intptr_t image_base_address = (intptr_t)image_info.dli_fbase;
const uint64_t image_text_size = _image_text_segment_size(mh);
char image_uuid[37];
const uuid_t *image_uuid_bytes = _image_retrieve_uuid(mh);
uuid_unparse(*image_uuid_bytes, image_uuid);
const char *log = added ? "Added" : "Removed";
printf("%s: 0x%02lx (0x%02llx) %s <%s>\n\n", log, image_base_address, image_text_size, image_name, image_uuid);
}
static const uuid_t *_image_retrieve_uuid(const struct mach_header *mh)
{
__block const struct uuid_command *uuid_cmd = NULL;
_image_visit_load_commands(mh, ^ (struct load_command *lc, bool *stop) {
if (lc->cmdsize == 0) {
return;
}
if (lc->cmd == LC_UUID) {
uuid_cmd = (const struct uuid_command *)lc;
*stop = true;
}
});
if (uuid_cmd == NULL) {
return NULL;
}
return &uuid_cmd->uuid;
}
static uint32_t _image_header_size(const struct mach_header *mh)
{
bool is_header_64_bit = (mh->magic == MH_MAGIC_64 || mh->magic == MH_CIGAM_64);
return (is_header_64_bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
}
static void _image_visit_load_commands(const struct mach_header *mh, void (^visitor)(struct load_command *lc, bool *stop))
{
assert(visitor != NULL);
uintptr_t lc_cursor = (uintptr_t)mh + _image_header_size(mh);
for (uint32_t idx = 0; idx < mh->ncmds; idx++) {
struct load_command *lc = (struct load_command *)lc_cursor;
bool stop = false;
visitor(lc, &stop);
if (stop) {
return;
}
lc_cursor += lc->cmdsize;
}
}
static uint64_t _image_text_segment_size(const struct mach_header *mh)
{
static const char *text_segment_name = "__TEXT";
__block uint64_t text_size = 0;
_image_visit_load_commands(mh, ^ (struct load_command *lc, bool *stop) {
if (lc->cmdsize == 0) {
return;
}
if (lc->cmd == LC_SEGMENT) {
struct segment_command *seg_cmd = (struct segment_command *)lc;
if (strcmp(seg_cmd->segname, text_segment_name) == 0) {
text_size = seg_cmd->vmsize;
*stop = true;
return;
}
}
if (lc->cmd == LC_SEGMENT_64) {
struct segment_command_64 *seg_cmd = (struct segment_command_64 *)lc;
if (strcmp(seg_cmd->segname, text_segment_name) == 0) {
text_size = seg_cmd->vmsize;
*stop = true;
return;
}
}
});
return text_size;
}
最后我们来看一下打印日志:
Added: 0x100000000 (0x2000) /Users/kyson/Library/Developer/Xcode/DerivedData/objc-grjuykqorhtyindmhcyxnyclzwsc/Build/Products/Debug/debug-objc <3E50C058-2477-3C17-BC84-F8466E78BB61>
Added: 0x1000a7000 (0x9000) /Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib <78E47484-9F4B-3C80-9D7A-2354B4046EE1>
Added: 0x1000b9000 (0x2c000) /Applications/Xcode.app/Contents/Developer/usr/lib/libMainThreadChecker.dylib <8E3CDC3C-82EC-309A-A105-8D99E61CC321>
Added: 0x1002ae000 (0x32000) /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Debugger/libViewDebuggerSupport.dylib <32D897CB-17C4-3A99-9B24-517C72372B61>
Added: 0x7fff419e0000 (0x3c7000) /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation <8EA924F3-ADAE-3F4B-8482-8B11C027D9A5>
Added: 0x100312000 (0x401000) /Users/kyson/Library/Developer/Xcode/DerivedData/objc-grjuykqorhtyindmhcyxnyclzwsc/Build/Products/Debug/libobjc.A.dylib <2C77662C-856F-3B69-98D9-0CF59D5FC34E>
Added: 0x7fff656a7000 (0x57000) /usr/lib/libc++.1.dylib <7D3DACCC-3804-393C-ABC1-1A580FD00CB6>
Added: 0x7fff65472000 (0x2000) /usr/lib/libSystem.B.dylib <CD555F3B-FDDB-35E5-A2FB-FBBF3D62031A>
Added: 0x7fff655ce000 (0x1000) /usr/lib/libauto.dylib <A05C7900-F8C7-3E75-8D3F-909B40C19717>
Added: 0x7fff4181a000 (0x6000) /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration <A975AD56-4CD3-3A89-8732-858CA9BD3DAA>
Added: 0x7fff6551e000 (0x2b000) /usr/lib/libarchive.2.dylib <8FC28DD8-E315-3C3E-95FE-D1D2CBE49888>
Added: 0x7fff650fc000 (0x2000) /usr/lib/libDiagnosticMessagesClient.dylib <9712E980-76EE-3A89-AEA6-DF4BAF5C0574>
Added: 0x7fff661d2000 (0x228000) /usr/lib/libicucore.A.dylib <34EBADD6-4092-30EC-90E8-F75241E94D76>
Added: 0x7fff67430000 (0xe8000) /usr/lib/libxml2.2.dylib <C2B5C43F-9C0B-31E6-8EC0-939591EDAC49>
Added: 0x7fff67541000 (0x13000) /usr/lib/libz.1.dylib <48C67CFC-940D-3857-8DAD-857774605352>
Added: 0x7fff3f87f000 (0x4a2000) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation <E5D594BF-9142-3325-A62D-CF4AAF472642>
Added: 0x7fff3e80b000 (0x39b000) /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork <76EB8CB6-BF59-3BDA-BF2B-F21B161611B9>
Added: 0x7fff4be79000 (0x71000) /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration <8532B8E9-7E30-35A3-BC4A-DDE8E0614FDA>
Added: 0x7fff409f8000 (0x1000) /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices <C8368F17-1589-3BA5-A0E7-89CB8DF2454F>
Added: 0x7fff66446000 (0x2000) /usr/lib/liblangid.dylib <39C39393-0D05-301D-93B2-F224FC4949AA>
Added: 0x7fff420bd000 (0x9c000) /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit <2EA4F383-CAA9-3AF0-99C5-90C22ADAA6B6>
Added: 0x7fff65025000 (0x3a000) /usr/lib/libCRFSuite.dylib <FE5EDB68-2593-3C2E-BBAF-1C52D206F296>
Added: 0x7fff656fe000 (0x25000) /usr/lib/libc++abi.dylib <EF5E37D7-11D9-3530-BE45-B986612D13E2>
Added: 0x7fff675ef000 (0x5000) /usr/lib/system/libcache.dylib <092479CB-1008-3A83-BECF-E115F24D13C1>
Added: 0x7fff675f4000 (0xb000) /usr/lib/system/libcommonCrypto.dylib <029F5985-9B6E-3DCB-9B96-FD007678C6A7>
Added: 0x7fff675ff000 (0x8000) /usr/lib/system/libcompiler_rt.dylib <968B8E3F-3681-3230-9D78-BB8732024F6E>
Added: 0x7fff67607000 (0xa000) /usr/lib/system/libcopyfile.dylib <3885083D-50D8-3EEC-B481-B2E605180D7F>
Added: 0x7fff67611000 (0x86000) /usr/lib/system/libcorecrypto.dylib <5C26364F-2269-31EC-84AF-0FED2C902E38>
Added: 0x100825000 (0x3f000) /usr/lib/system/introspection/libdispatch.dylib <9C60E29A-5FF8-33F8-B474-57B7826AC7EE>
Added: 0x7fff67758000 (0x1e000) /usr/lib/system/libdyld.dylib <81BF3A82-5719-3B54-ABA9-76C82D932CAC>
Added: 0x7fff67776000 (0x1000) /usr/lib/system/libkeymgr.dylib <E34E283E-90FA-3C59-B48E-1277CDB9CDCE>
Added: 0x7fff67784000 (0x1000) /usr/lib/system/liblaunch.dylib <B184B521-FF24-3142-AFAF-23D170CF918C>
Added: 0x7fff67785000 (0x5000) /usr/lib/system/libmacho.dylib <1902A611-081A-3452-B11E-EBD1B166E831>
Added: 0x7fff6778a000 (0x3000) /usr/lib/system/libquarantine.dylib <26C0BA22-8F93-3A07-9A4E-C8D53D2CE42E>
Added: 0x7fff6778d000 (0x2000) /usr/lib/system/libremovefile.dylib <711E18B2-5BBE-3211-A916-56740C27D17A>
Added: 0x7fff6778f000 (0x18000) /usr/lib/system/libsystem_asl.dylib <39E46A6F-B228-3E78-B83E-1779F9707A39>
网友评论