27、iOSの下の分析 - プロモーターの最適化(バイナリ並べ替え)

スタートの最適化 - バイナリリメイク


IOSのシステムは、仮想および物理メモリページングなり、物理メモリへのマッピング仮想メモリページの最小単位です
 
 スタート:

我々はAPPの開始について話しているときに表示される最初のページから開始するには、アイコンをクリックしてください。
 

コールドスタート:

プログラム完全に(場合によっては、プロセスを強制終了した後、他の多くのAPPを開け、今回のプログラムが物理メモリに対応する物理メモリ、仮想メモリから再ロードされる別のプログラムのニーズによって使用されている)、または最初のインストールの開始(最初のインストールまたはアンインストール後、重機など)。

ホットスタート:

別の開始に続いて、プログラムを、殺した後、まだ我々のデータを保持している対応する物理メモリへのこの時間は、仮想メモリから完全な再読み込みを必要としません。
 プログラムが仮想メモリから物理メモリへの負荷がロードされたページングされ、開始します。データは、仮想メモリのページ(iOSの16キロバイト)してページを保存しています。物理メモリが、我々は負荷に必要なものではないときに、プログラムを起動する場合は、仮想メモリのページフォールトをリロードします。より多くの場合より少なく、その認識が、出てこない場合、それは、起動速度に影響を与えます。
 
 楽器
 Xcodeのデバッグツールが付属しています。開くにはXcodeのコマンド+ Iを開き
 、多くのシステムトレースを使用してここにありますデバッグツールを
 単にここで、各スレッド内のデータを参照するために、ダブルクリックして開きます、ここでスレッドは見る必要が仮想メモリであり、
 

 


 デモは、最初の空のプロジェクトを作成し、その後、携帯電話に実行し、その後、IPAのインストールを変更するには、IPAの署名を再インストールし、目的は、携帯電話のIPAをインストールするには、記述ファイルを追加することです。プロファイルがすでに携帯電話にインストールされて存在し、それが直接コマンド+ Rに可能です

デバッグを通じ、最初に開いた(コールドスタート)たくさんのファイルをロードしていますが、ロードされてはるかに少ないでしょう再起動(ウォームスタート)を指示し、プログラムを強制終了する場合。この後、我々は仮想メモリをロードする必要がないときに再び開始するために、物理メモリ、物理メモリにロードされていることを知って、それがすぐに開始します。プログラムを殺すために時間が、その後、他の開いているプログラムの多くがある場合は、我々は再びプログラムを開いて、それがコールドスタートであることがわかります。あなたが別のアプリケーションの実行により、使用中の物理メモリを分析することができます前にロード。
 物理メモリの仮想メモリ、仮想メモリは、連続しているコネクタを介して対応する物理メモリに対応し、対応する物理メモリが固定されていない状況下では、開かれたスペアメモリ、または対応する番号を上書きするには、noアイドル時間を見つけることですメモリ。
 ファイル担保ページにロードされたデータは、ファイルが1を占めていない、1は16キロバイトで、エネルギーの多くを置きます。
 


バイナリ並べ替え

 なぜバイナリ再配置、プログラムが順番に実行されるため。
 たとえば:
 246が負荷に開始された今、仮想メモリ6、123 456、135はロードを開始する必要はありません。しかし、実行順序が6つの完全にロードされた内側にあります。並び替えバイナリオブジェクトは、他の内容のロードを開始してから数ページの実行順序を上に移動するページに246枚のニーズです。
 バイナリ再配置は、これらのシンボルが再配置され、スタートシンボル系列を知ることは困難です。


Xcodeは設定可能です。彼はコネクタが長く、シンボルのパックXcodeの時間シーケンスがファイル内にパッケージ化されますへの書き込み、-order_file内部で使用されているldのXcodeの。
 
 どのようにブートシーケンスを確認するには
 、1シーケンスファイルの
 ビルドフェーズを- >実行順序内のコンパイルソース・ファイルは、オーダー(調整可能)で
 修飾法のないファイルの再配列は、道のため、機能を決定していない場合。B前ページにページを、方法Aは、B法の前に実行されます。
 
 図2に示すように、シンボル・テーブル・オーダー。
 ビルド設定- >リンクマップファイルを書く - > YES 自動的にシンボルテーブル生成
 翻訳が完了した後にコンパイルされ、このリンクマップに書き込まれます。
 そして、開いているビューの
 Xcodeの製品の展示- > filedome.app - >右ショーでファインダー- >二つのディレクトリ(および同様の製品は)Intermediates.noindexを発見したまで- > filedome.build - >デバッグ- iphoneos - > filedome.build - > filedome -LinkMap-通常arm64.txt(の.textファイルの末尾にこれを見つけます。)


 
 


 図4に示すように、シンボルは
 方法のいくつかの.o、機能、等シンボルファイル名に属する(16進数)多くのスペースを取る位置(アドレスコード)を開始します

# Address        Size        File          Name
 0x1000051C8    0x00000098    [  1] +[LJLWeakProxy proxyWithTarget:]
 0x100005260    0x0000006C    [  1] -[LJLWeakProxy methodSignatureForSelector:]
 0x1000052CC    0x0000009C    [  1] -[LJLWeakProxy forwardInvocation:]
 0x100005368    0x00000034    [  1] -[LJLWeakProxy target]
 0x10000539C    0x00000048    [  1] -[LJLWeakProxy setTarget:]
 0x1000053E4    0x0000003C    [  1] -[LJLWeakProxy .cxx_destruct]
 0x100005420    0x000000E0    [  2] -[LJLGCDTwoViewController viewDidLoad]
 0x100005500    0x00000014    [  2] -[LJLGCDTwoViewController createGroup]
 0x100005514    0x000000C4    [  2] -[LJLGCDTwoViewController groupRest1]
 0x1000055D8    0x0000003C    [  2] ___37-[LJLGCDTwoViewController groupRest1]_block_invoke
 0x100005614    0x0000003C    [  2] ___37-[LJLGCDTwoViewController groupRest1]_block_invoke_2
 0x100005650    0x0000002C    [  2] ___37-[LJLGCDTwoViewController groupRest1]_block_invoke_3
 0x10000567C    0x000001A0    [  2] -[LJLGCDTwoViewController groupRest2]
 0x10000581C    0x00000054    [  2] ___37-[LJLGCDTwoViewController groupRest2]_block_invoke


 バイナリ並べ替え開始

 1. .ORDER作成し
 、プロジェクトのルートディレクトリを開き、入力するターミナル:タッチliujilou.orderを入力します。liujilou.orderを生成するためのルートディレクトリにあるファイル(自分の状況プロジェクトに従って命名)。
 
 2、Xcodeの設定
 ビルド- >設定- >注文ファイル (./liujilou.order 相対パスでのルートディレクトリにあります)

@implementation ViewController
//随便写一些代码
//函数
void test()
{
    block1();
}
void(^block1)(void) = ^(void){
    
};
......
//例如 :编辑 liujilou.order 
 _main
 -[LJLWeakProxy setTarget:]
 -[LJLWeakProxy .cxx_destruct]
 -[liujilou hello]

その後、コンパイラのコマンド+ Bキャッシュに関するコマンド+ Kをクリア、

# Symbols:
 # Address    Size        File  Name
 0x1000051C8    0x000000A4    [ 11] _main
 0x10000526C    0x00000048    [  1] -[LJLWeakProxy setTarget:]
 0x1000052B4    0x0000003C    [  1] -[LJLWeakProxy .cxx_destruct]
 0x1000052F0    0x00000098    [  1] +[LJLWeakProxy proxyWithTarget:]
 0x100005388    0x0000006C    [  1] -[LJLWeakProxy methodSignatureForSelector:]
 0x1000053F4    0x0000009C    [  1] -[LJLWeakProxy forwardInvocation:]
 0x100005490    0x00000034    [  1] -[LJLWeakProxy target]
 0x1000054C4    0x000000E0    [  2] -[LJLGCDTwoViewController viewDidLoad]
 0x1000055A4    0x00000014    [  2] -[LJLGCDTwoViewController createGroup]
 0x1000055B8    0x000000C4    [  2] -[LJLGCDTwoViewController groupRest1]
 0x10000567C    0x0000003C    [  2] ___37-[LJLGCDTwoViewController

 以上の結果を対比し、我々は今我々が.ORDER編集したもののブートシーケンスの順序を確認することができます 

 _main
 -[LJLWeakProxy setTarget:]
 -[LJLWeakProxy .cxx_destruct]

私たちのプロジェクトの一つとエラーが無視されることはありません、私たちは順番に書かれている場合でも、このメソッドを持っていません。だから、間違った状況を心配し、問題が発生しません。

-[liujilou hello]

拡張:

シンボル他の方法は、(アドレスの並び順に応じて完全に、緩んでいない)NM参照
 ターミナル。

//打开自己APP 目录,并不是让输入  ../
 cd  ... /filedome.app
 nm filedome
 nm -p filedome  书序排列,但是也不是完全按照启动顺序排列的
 nm -u filedome  只看系统的方法等
 nm -U filedome  只看自定义的方法等

それはまだ、リンク・マップの対象となるので、それは、許可されていません。
 

真のバイナリの再配置を実現するために、我々はすべてのメソッド、関数やその他の記号を始めるために、と順番保存し、ファイルがバイナリ再配置を達成するために書かれている必要があります。記事ビブラートが、それはそれを見るために、すべての特定の記事をフックしません。
 ビブラートの研究開発実践:ベースのソリューションは、APP速度バイナリを起動するには、15%以上向上させるために再配置され

、そのアイデアの:
)このシステムの機能をすべてOCプロセスは、(objc_msgsend行くだろうし、あなたは釣り針フックobjc_msgSend()あなたが得ることができると行くことができます[すべてのOCメソッド呼び出し、およびobjc_msgsendから、この内部をフックは、()は、第2のパラメータ(SEL)は、すべてのシンボルを得ました。
しかし、この1は関係していobjc_msgSend()は変数のパラメータであるため、ピットである、唯一のスタックレジスタを介してバランスを維持するためにアセンブラを書くことができます。あなたがこの中で深い探求することができない、と釣り針について学ぶためにコンパイルされたiOSラムがわからない場合。
 そして、このような初期化できませんフック
 よりも部分ブロックフック
 C ++間接的な関数呼び出しの静的スキャンレジスタを介して出てきません。
 あなたは90%に80%を転位することができます。これは推奨されていない場合は100%を必要としています。
 
 私は完全に私たちが使用しているすべてのシンボルにフックしたいです


 打ち鳴らす計装

 これは、コード・カバレッジ・ツールは、翻訳
 の中で、すべてのカスタムプロジェクトのためのコードを検出することが可能です。
 1.設定の
 ビルド設定- >その他Cフラグを追加します。

-fsanitize-coverage=trace-pc-guard


 
 その後、コンパイルエラー(未定義のシンボルが、私たちはそのいくつかのポイント必見のシステムコールでこれらええ、それだけのショーでプロジェクトを配るません)します。

Undefined symbol: ___sanitizer_cov_trace_pc_guard_init
Undefined symbol: ___sanitizer_cov_trace_pc_guard

あなたはすべてのメソッドにデフォルト___sanitizer_cov_trace_pc_guardで追加さ-fsanitizeカバレッジ=トレース-PC-ガードを追加したためです。文書のルック打ち鳴らします。プロジェクトにこれらの二つの機能を検索します。

extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
                                                    uint32_t *stop) {
  static uint64_t N;  // Counter for the guards.
  if (start == stop || *start) return;  // Initialize only once.
  printf("INIT: %p %p\n", start, stop);
  for (uint32_t *x = start; x < stop; x++)
    *x = ++N;  // Guards should start from 1.
}

extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
  if (!*guard) return;  // Duplicate the guard check.
  // If you set *guard to 0 this code will not be called again for this edge.
  // Now you can get the PC and do whatever you want:
  //   store it somewhere or symbolize it and print right away.
  // The values of `*guard` are as you set them in
  // __sanitizer_cov_trace_pc_guard_init and so you can make them consecutive
  // and use them to dereference an array or a bit vector.
  void *PC = __builtin_return_address(0);
  char PcDescr[1024];
  // This function is a part of the sanitizer run-time.
  // To use it, link with AddressSanitizer or other sanitizer.
  __sanitizer_symbolize_pc(PC, "%p %F %L", PcDescr, sizeof(PcDescr));
  printf("guard: %p %x PC %s\n", guard, *guard, PcDescr);
}

もちろん__sanitizer_symbolize_pc()がエラーした後、重要な最初のコメントを継続していきます。


さて、このプロジェクトを開始し、起動が完了した後に一時停止します。そして、それを印刷

 INIT: 0x1029135e8 0x102913e70
 ......
 (lldb) x 0x1029135e8
 0x1029135e8: 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00  ................
 0x1029135f8: 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00  ................
 (lldb) x 0x102913e70
 0x102913e70: 98 cb 90 02 01 00 00 00 00 00 00 00 00 00 00 00  ................
 0x102913e80: ca 98 90 02 01 00 00 00 00 00 00 00 00 00 00 00  ................
 (lldb) x 0x102913e70-0x4
 0x102913e6c: 22 02 00 00 98 cb 90 02 01 00 00 00 00 00 00 00  "...............
 0x102913e7c: 00 00 00 00 ca 98 90 02 01 00 00 00 00 00 00 00  ................

最後の印刷が終了位置であり、ディスプレイは、4で4であるので、前進4を移動させる、最後のものでなければならないプリントアウト。
リトルエンディアンモード2202万は、16進数222ブートローダー546進表記です。
ViewControllerをプラスloadメソッドでは(必ずしも主にこれは私がシンボルの数をプリントアウト推測起動しないかどうかを確認するために、負荷、負荷への負荷が始まりである必要はありません)

 INIT: 0x10286b610 0x10286be9c
 ......
 (lldb) x 0x10286b610
 0x10286b610: 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00  ................
 0x10286b620: 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00  ................
 (lldb) x 0x10286be9c
 0x10286be9c: 00 00 00 00 98 4b 86 02 01 00 00 00 00 00 00 00  .....K..........
 0x10286beac: 00 00 00 00 c7 18 86 02 01 00 00 00 00 00 00 00  ................
 (lldb) x 0x10286be9c-0x4
 0x10286be98: 23 02 00 00 00 00 00 00 98 4b 86 02 01 00 00 00  #........K......
 0x10286bea8: 00 00 00 00 00 00 00 00 c7 18 86 02 01 00 00 00  ................

ディスカバリーは変更され、現在のものより2302万以上でました。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    test();
}

 + (void)initialize
 {
 
 }
 void(^block)(void) = ^(void) {
 
 };
 
 void test(){
     block();
 }

3回を印刷するには、画面上のポイント。

 guard: 0x10de29ae0 f5 PC (\3041
 guard: 0x10de29ae4 f6 PC \211\352:
 guard: 0x10de29ae8 f7 PC 0/\337\341\376

使用して、ブロックを初期化し、関数が増加しますので、この方法は、すべてのシンボルをフックすることができるかもしれません。
 
 
 その後、ビューをコンパイル
 
 

filedome`-[ViewController touchesBegan:withEvent:]:
.....
 0x10214cca4 <+40>:  bl     0x10214ce44               ; __sanitizer_cov_trace_pc_guard at ViewController.m:117
 0x10214cca8 <+44>:  ldr    x8, [sp, #0x28]

 BLコンパイル手段は、アドレス0x10214ce44にジャンプする命令をジャンプ
 ;セミコロンは説明コメント注釈コンテンツはコンパイルViewController.mで117 __sanitizer_cov_trace_pc_guardの最初の行のアドレスであるものとします

filedome`test:
 ->  0x100df0d2c <+0>:  stp    x29, x30, [sp, #-0x10]!
 0x100df0d30 <+4>:  mov    x29, sp
 0x100df0d34 <+8>:  adrp   x8, 23
 0x100df0d38 <+12>: add    x0, x8, #0x9d8            ; =0x9d8
 0x100df0d3c <+16>: bl     0x100df0e44               ; __sanitizer_cov_trace_pc_guard at ViewController.m:117
filedome`block1_block_invoke:
 0x102becd60 <+0>:  sub    sp, sp, #0x30             ; =0x30
 0x102becd64 <+4>:  stp    x29, x30, [sp, #0x20]
 0x102becd68 <+8>:  add    x29, sp, #0x20            ; =0x20
 0x102becd6c <+12>: adrp   x8, 23
 0x102becd70 <+16>: add    x8, x8, #0x9dc            ; =0x9dc
 0x102becd74 <+20>: str    x0, [sp, #0x8]
 0x102becd78 <+24>: mov    x0, x8
 0x102becd7c <+28>: bl     0x102bece44               ; __sanitizer_cov_trace_pc_guard at ViewController.m:117

テストブロックでは、ブレークポイントでマークされ、その後、一つ一つを失い、__sanitizer_cov_trace_pc_guardまでのすべてのジャンプを発見しました。
私たちが配置された打ち鳴らすようなコードは、オーバーレイに挿入されています。メソッド、関数、コードの先頭行に含まれる内部ブロックで、静的で計装。挿入のエッジでコード、新たな行動フックの行を挿入することです。
 大要のアドレスを決定するには、次の関数のアドレスを関数が実行されたときに実行されるように保存されますときX30レジスタへの完全復帰。

#import "ViewController.h"
#import <dlfcn.h>
#import <libkern/OSAtomic.h>
#import "filedome-Swift.h"
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
                                                    uint32_t *stop) {
    static uint64_t N;  // Counter for the guards.
    if (start == stop || *start) return;  // Initialize only once.
    printf("INIT: %p %p\n", start, stop);
    for (uint32_t *x = start; x < stop; x++)
        *x = ++N;  // Guards should start from 1.
}

シンボルのすべてを取得するために保存する必要が後が、子スレッドであり、実行することができるので、配列を使用することはできませんので、配列に問題があるでしょう 

//原子队列  1、先进后出  2、线程安全  3、只能保存结构体
static OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT;

//定义符号结构体
typedef struct {
    void *pc;
    void *next;//下一个数据的结构体指针地址
}SYNode;


void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
//    if (!*guard) return;  // Duplicate the guard check.
    
//    汇编一个函数执行完返回会将下一个要执行的函数地址给保存到 x30 寄存器中,将返回值给下一个函数。
//    所以这个函数的命名就是 返回 内存地址。 这里PC 就是拿到的内存地址
    void *PC = __builtin_return_address(0);
    
    SYNode * node = malloc(sizeof(SYNode));
    *node = (SYNode){PC,NULL};
//    进入 入栈
//    最后一个参数是下一个数据的位置,也就是往上边的*node 的第二位插入
//    offsetof(SYNode, next)  next 成员在 结构体 SYNode 中的偏移值
    OSAtomicEnqueue(&symbolList, node, offsetof(SYNode, next));
    
    
    
//    dlopen 通过动态库拿到句柄 通过句柄拿到函数的内存地址
//    dladdr 通过函数内存地址拿到函数
//    typedef struct dl_info {
//        const char      *dli_fname;     /* Pathname of shared object      函数的路径  */
//        void            *dli_fbase;     /* Base address of shared object  函数的地址  */
//        const char      *dli_sname;     /* Name of nearest symbol         函数符号    */
//        void            *dli_saddr;     /* Address of nearest symbol      函数起始地址 */
//    } Dl_info;
//    Dl_info info;
//    dladdr(PC, &info);
//    printf("fnam:%s \n fbase:%p \n sname:%s \n saddr:%p \n",
//           info.dli_fname,
//           info.dli_fbase,
//           info.dli_sname,
//           info.dli_saddr);
//fnam:/Users/liujilou/Library/Developer/CoreSimulator/Devices/F8857F80-4697-496A-8FE8-255DA2056C17/data/Containers/Bundle/Application/B57CF494-5D7D-4044-87B4-949E971BD39D/filedome.app/filedome
//fbase:0x108a1d000
//sname:-[LGPerson setNum:]
//saddr:0x108a27ff0
//    拿到了全部的符号之后需要保存,但是不能用数组,因为有可能会有在子线程执行的,所以用数组会有问题
//    用原子队列 #import <libkern/OSAtomic.h>
}

貯蔵の完了後に除去横断し、次に注文シンボルテーブルファイルを編集するために必要。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSMutableArray <NSString *>* symbolNames = [NSMutableArray array];
    while (YES) {
        SYNode * node = OSAtomicDequeue(&symbolList, offsetof(SYNode, next));
        if (node == NULL) {
            break;
        }
        Dl_info info;
        dladdr(node->pc, &info);
        
        NSString * name = @(info.dli_sname);
        BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
        NSString * symbolName = isObjc? name : [@"_" stringByAppendingString:name];//c函数前面带下划线
        [symbolNames addObject:symbolName];
        printf("%s \n",info.dli_sname);
    }
//    symbolNames = [[symbolNames reverseObjectEnumerator] allObjects];//取反
    NSEnumerator * emt = [symbolNames reverseObjectEnumerator];
    NSMutableArray<NSString*>* funcs = [NSMutableArray arrayWithCapacity:symbolNames.count];
    NSString * name;
    while (name = [emt nextObject]) {
        if (![funcs containsObject:name]) {
            [funcs addObject:name];
        }
    }
    //    删掉当前方法(因为这个点击方法不是必须的)
    [funcs removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];
    
    NSString * funcStr = [funcs componentsJoinedByString:@"\n"];
    
    NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"liujilou.order"];
    NSData * fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
//    在路径上创建文件
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];
    
    
    NSLog(@"%@",filePath);

//    1、压栈先进后出
//    2、获取的符号会有重复
//    3、load 的首位是0,所以要把if (!*guard) return; 注释掉。由此可以知道如果我们想过来某些函数,可以类似这样操作
}

この場所には穴があります

ダイレクト一方(YES){}無限ループになり、それが印刷されています

-[ViewController touchesBegan:withEvent:]
-[ViewController touchesBegan:withEvent:]
......

アセンブラビューを見ることでポイントを破る、あなたは見つけるでしょう

- [ViewControllerをtouchesBegan:withEventは:] : コール三回
__sanitizer_cov_trace_pc_guard
CBNZ×8、
これは私たちのwhileループ、トリガ__sanitizer_cov_trace_pc_guardです。
あなたが休憩bを持っている場合は、コードが先頭に継続していない場合は、飛び出します。
サイクルが来る
(offsetofは&symbolList、ノード、OSAtomicEnqueue )次に、(SYNode)を、
添加
SYNode *ノード= OSAtomicDequeue(&symbolList )、次に、offsetofは(SYNode);
少なくとも一つ、及びその後に入るプラス1なり取り出しを、内少なくとも一つを除去しました。それはサイクルとなっています。
ソリューションのビルド- >設定- >その他Cフラグは
、-カバレッジを-fsanitize =トレース-PC-ガードプラスFUNC

-fsanitize-coverage=func,trace-pc-guard

printf();呼び出しはこれにジャンプするつもりはない()メソッドは、社内のprintfではないので、それがあります。社内プラスメソッド内のみ

これは、プログラムを実行することによって、コンパイラを可能にし、画面をクリックしてサンドボックス内のliujilou.orderファイルを生成します。今すぐファイルをエクスポートし、プロジェクトliujilou.orderプロジェクトの前にファイルを交換しました。

実機Xcodeのアプリのサンドボックスのコンテンツを参照してください
メニュー開くためにウィンドウ- >デバイスやシミュレータを(ショートカットはShift +コマンド+ 2)
選択したデバイスに接続されている実機で


 


 代替的に、再コンパイルコマンド+ Bの終了後シーケンスを見てみること

 # Symbols:
 # Address    Size        File  Name
 0x100005710    0x000000C8    [ 11] _main
 0x1000057D8    0x00000058    [ 23] -[AppDelegate window]
 0x100005830    0x00000070    [ 23] -[AppDelegate setWindow:]
 0x1000058A0    0x000001A0    [ 23] -[AppDelegate application:didFinishLaunchingWithOptions:]
 0x100005A40    0x00000090    [ 10] -[ViewController .cxx_destruct]
 0x100005AD0    0x0000066C    [ 10] -[ViewController viewDidLoad]
 0x10000613C    0x00000070    [ 10] -[ViewController setDataArr:]
 0x1000061AC    0x00000068    [ 12] -[LGPerson setNum:]
 0x100006214    0x00000068    [ 12] -[LGPerson setHeight:]
 0x10000627C    0x00000068    [ 12] -[LGPerson setAge:]
 0x1000062E4    0x00000074    [ 23] -[AppDelegate applicationDidBecomeActive:]

転位が完了している、我々は、シーケンス開始
 
 
 迅速わずかに異なる設定を
 増やすドームSWIFTコード以下、テストのために。

//  SwiftTest.swift
//  filedome

//import Foundation
import UIKit
//简单点用UIKit
class SwiftTest: NSObject {
    @objc class public func swiftTestLoad(){
        print("swiftTest");
    }
}

ViewControllerをインポートヘッダーファイルとそれを呼び出します

#import "filedome-Swift.h"

- (void)viewDidLoad {    
    [SwiftTest swiftTestLoad];
}

ビルド設定 - >その他スウィフトフラグ(必要なプロジェクトは、人が検索よりも小さいかどうか、SWIFTコードを持っています)

-sanitize-coverage=func
-sanitize=undefined

プリントルックプリントラン

-[ViewController touchesBegan:withEvent:]
 -[AppDelegate applicationDidBecomeActive:]
 -[AppDelegate window]
// 下面的这4个就是swift 的
 $ss5print_9separator10terminatoryypd_S2StFfA1_
 $ss5print_9separator10terminatoryypd_S2StFfA0_
 $s8filedome9SwiftTestC05swiftC4LoadyyFZ
 $s8filedome9SwiftTestC05swiftC4LoadyyFZTo
 -[LGPerson setAge:]
 -[LGPerson setHeight:]
 

バイナリ重みの最後の行の後、注文ファイル、リンクマップの構成を生成します。弊社のバイナリ並べ替え並べ替えが完了した場合でも、この時間、この時間の必要性その他のCフラグ/その他スウィフトフラグの設定を削除し、この設定は自動的に我々のコードにジャンプ実行__sanitizer_cov_trace_pc_guardが挿入されているので。ヘビーエンド行が必要とされていない、除去する必要があります。
同時に__sanitizer_cov_trace_pc_guardにおける当社のViewControllerでもを取り除きたいです。
 
 最適化された結果:
 非常に明白ではありませんが、主な目的は、プロジェクトが、バイナリ並べ替えを見てする必要がある場合には、非常に大きなありながら、これ以上のスペースを最適化することはできないがある場合、プロジェクトが最適化された最適化することです。

公開された83元の記事 ウォン称賛12 ビュー180 000 +

おすすめ

転載: blog.csdn.net/shengdaVolleyball/article/details/104984267