Use Mach-O section as plist

背景

plist以其可读性强的特点,被大家首选用作配置文件。但是plist 文件的读取速度实在不给力,是否有可选方案?答案是有的!

使用Section 保存数据

我们的程序编译后代码在.text ,数据在.data段,我们可以通过声明一个字符串在data段的特定的section里(默认字符串在 __cstring这个section中)。

char * str __attribute((used,section("__DATA,Test"))) = "Hello world";

在运行的时候通过

///< 头文件:getsect.h
extern uint8_t *getsectiondata(
    const struct mach_header_64 *mhp,
    const char *segname,
    const char *sectname,
    unsigned long *size);

来获取某个二进制文件中,指定segment指定section的内容。这样子就能从代码中获得配置信息。

Coding

#ifndef __LP64__
#define mach_header mach_header
#else
#define mach_header mach_header_64
#endif

//使用 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)


#import "ViewController.h"
#include <mach-o/getsect.h>
#include <mach-o/loader.h>
#include <mach-o/dyld.h>
#include <dlfcn.h>

static NSString *configuration = @"";
const struct mach_header *machHeader = NULL;

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    NSLog(@"%@",[self readConfigFromSectionName:@"CustomSection"]);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (NSArray <NSDictionary *> *)readConfigFromSectionName:(NSString *)sectionName
{
    NSMutableArray *configs = [NSMutableArray array];
    if (sectionName.length)
    {
        if (machHeader == NULL)
        {
            Dl_info info;
            dladdr((__bridge const void *)(configuration), &info);
            machHeader = (struct mach_header*)info.dli_fbase;
        }
        unsigned long size = 0;
        uintptr_t *memory = (uintptr_t*)getsectiondata(machHeader, SEG_DATA, [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 configs;
}
@end

最终输出:

2017-06-05 22:41:54.431 WriteSectionData[27360:1459771] (
        {
        url = "www.baidu.com";
    }
)
WriteSectionData.png

由于小端序的原因,所以在镜像中的地址应该是0x0100001a70。 用hopper 打开程序,定位到地址:0x0100001a70。

WriteSectionData_hop.png

通过字符串定位到镜像文件的指定section,读取配置信息。并且实现了代码编写的时候注入,无需文件IO(内存读取),代码即配置,局部性强,可读性高。

TODO:性能对比

  • 对比数据从section 和plist 读取数据转化为json的耗时
  • 对比数据量一样的前提下,文件大小的对比。
  • section 段增大,是否会对启动速度有影响。

更多

关于DATA 段大小的限制

App Size for iOS (& tvOS) only

Your app’s total uncompressed size must be less than 4GB. Each Mach-O executable file (for example, app_name.app/app_name) must not exceed these limits:

For apps whose MinimumOSVersion is less than 7.0: maximum of 80 MB for the total of all __TEXT sections in the binary.
For apps whose MinimumOSVersion is 7.x through 8.x: maximum of 60 MB per slice for the __TEXT section of each architecture slice in the binary.
For apps whose MinimumOSVersion is 9.0 or greater: maximum of 500 MB for the total of all __TEXT sections in the binary.
However, consider download times when determining your app’s size. Minimize the file’s size as much as possible, keeping in mind that there is a 100 MB limit for over-the-air downloads.

以上引用自苹果官方文档,官方只给出了TEXT段的大小限制,并没有给出DATA 段的大小限制。
Ref :

Specifying Attributes of Variables

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 11,187评论 6 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,009评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,974评论 6 342
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,219评论 30 472
  • 人生有一千种一万种可能的路走,而我们选了一条几乎所有人都看来不理解的艰难道路前进。一切的选择都是为了我们心里梦想的...
    蜀湘情缘阅读 136评论 0 0