编译器优化
有一次,你必须钦佩。 开发编译器的人,都很坚强。 例如,平时写的代码中一定有很多未使用的代码。 例如,如果定义了局部变量,但没有在整个类中调用它,编译器会在编译时将未使用的代码也编译到程序集吗
分析、流程和验证
创建项目
更改编译器的优化级别。 在此选择与Appstore相同的优化级别
写一个方法
方法中创建了一些局部变量,而不是在整个执行过程中使用
-(nsinteger ) Mytest{
int a=10;
int b=20;
返回a b;
}
-(void )视图下载
[super viewDidLoad]
NSInteger num=[self Mytest];
self.textfield.text=[ nsstringstringwithformat : @ ' % LD ',[long]num]
}
验证最后生成的程序集代码是否设计到这些变量
Mytest函数的内容如下。
内容被优化了
int a=10用完了int b=20; a b流程
return直接得出了结果30
将Mytest的代码更改为:
-(nsinteger ) Mytest{
int a=10;
int b=20;
return ab [ self.textfield2. textintegervalue ];
}
编译后的程序集
编译器优化`-[视图控制器mytest ] :
0x102ce6708 : stp x22,x21,[sp,#-0x30]!
0x102ce670c : stp x20,x19,[sp,#0x10]
0x102ce6710 : stp x29,x30,[sp,#0x20]
0x102ce6714 : add x29,sp,#0x20;=0x20
-0x102ce6718 : nop
0x102ce671c : ldr x1,#0x26a4; ' TextField2'
0x102ce6720 : bl0x102ce6a38; symbol stub for: objc_msgSend
0x102ce6724 : mov x29,x29
0x102ce6728 : bl0x102ce6a5c; symbolstubfor : objc _ retainautoreleasedreturnvalue
0x102ce672c : mov x19,x0
0x102ce6730 : nop
0x102ce6734 : ldr x1,#0x2694; 文本
0x102ce6738 : bl0x102ce6a38; symbol stub for: objc_msgSend
0x102ce673c : mov x29,x29
0x102ce6740 : bl0x102ce6a5c; symbolstubfor : objc _ retainautoreleasedreturnvalue
0x102ce6744 : mov x20,x0
0x102ce6748 : nop
0x102ce674c : ldr x1,#0x2684; ' integerValue '
0x102ce6750 : bl0x102ce6a38; symbol stub for: objc_msgSend
0x102ce6754 : add x21、x0、#0x1e;=0x1e
0x102ce6758 : mov x0,x20
0x102ce675c : bl0x102ce6a50; symbol stub for: objc_release
0x102ce6760 : mov x0,x19
0x102ce6764 : bl0x102ce6a50; symbol stub for: objc_release
0x102ce6768 : mov x0,x21
0x102ce676c : ldp x29,x30,[sp,#0x20]
0x102ce6770 : ldp x20,x19,[sp,#0x10]
0x102ce6774 : ldp x22,x21,[sp],#0x30
0x102ce6778 : ret
p>发现好多的代码,重点其实就是多了一个去取textfield2的值的汇编:
还是那句话,常量的运算过程优化,+ textfield2中的值得到结果 x0 = x21 返回x0
再次修改一下代码
-(NSInteger)Mytest{
int a = 10;
int b = 20;
return a + b + self.value;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.value = 10;
NSInteger num = [self Mytest];
self.TextField.text = [NSString stringWithFormat:@"%ld",(long)num];
}
得到的汇编代码
编译器优化`-[ViewController Mytest]:
0x100186704 : stp x29, x30, [sp, #-0x10]!
0x100186708 : mov x29, sp
-> 0x10018670c : nop
0x100186710 : ldr x1, #0x2710 ; "value"
0x100186714 : bl 0x100186a14 ; symbol stub for: objc_msgSend
0x100186718 : add x0, x0, #0x1e ; =0x1e
0x10018671c : ldp x29, x30, [sp], #0x10
0x100186720 : ret
将上述value属性替换成静态的变量
-(NSInteger)Mytest{
MyValue = 20;
int a = 10;
int b = 20;
return a + b + MyValue;
}
优化后的汇编
编译器优化`-[ViewController Mytest]:
-> 0x102526720 : mov w0, #0x32
0x102526724 : ret
C函数的优化
int Mytest2(int a ,int b){
int c = 10;
return a + b + MyValue;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.value = 10;
NSInteger num = Mytest2(10, 20);
self.TextField.text = [NSString stringWithFormat:@"%ld",(long)num];
}
在Viewdidload函数中,Mytest直接变成了0x28 = 40
证明一部分C语言的函数,会被直接优化转化成结果直接赋值
大概编译器优化的规则
所有常量的运算的过程都会优化掉,直接生成结果
能够直接从地址中获取值的变量、常量这些在编译完成后都会被优化成值
优化掉部分C语言函数
运行的结果是不会受到影响的
关于汇编多线程问题
将优化等级切换回来
int Mytest2(int a ,int b){
int c = 10;
return a + b + (int)MyValue;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.value = 10;
NSInteger num = Mytest2(10, 20);
self.TextField.text = [NSString stringWithFormat:@"%ld",(long)num];
}
分析
寄存器的访问本身是线程不安全的,底层是没有线程安全的说法
线程的切换是由操作系统把控
Apple的操作系统是没有公开的,但是所有的操作系统都会做一个寄存器保护的功能,当前线程切换的时候,当前的线程会对当前的寄存器做一个保护,当保护的当前的寄存器的时候,将当前寄存器的环境存入到内存当中, 那么在其他线程中就可以使用这些寄存器了,如果在切换回这个线程的时候,会从内存中再度回来这个线程的寄存器环境。
操作系统windows由相关寄存器保护的属性,在apple中是没有被证实的
所有的资源抢夺,都是对内存的保护。我们所做的加锁全部是对内存的加锁
寄存器的保护都是操作系统做的。
扩展
寄存器>高速缓存>内存>磁盘
指令执行的越多,越慢
app存在磁盘里面,打开app读到内存当中,A11 8MB将要执行的代码放入高速缓存,