AiTel


  • Startseite

  • Archiv

  • Tags

linux 性能调优

Veröffentlicht am 2018-11-05

##使用perf

首先需要linux支持使用perf命令,可以以下命令进行安装

sudo apt-get install linux-tools-common linux-tools-generic linux-tools-uname -r

在perf中可以用perf stat对某个进程进行分析

perf list

可以列出所有的事件采集点

##画火焰图

perf record -a -p pid -g

-g 记录堆栈,-p指定perf的进程id

perf script > out.perf

将相关信息dump到out.perf, 然后

git clone –depth 1 https://github.com/brendangregg/FlameGraph.git
stackcollapse-perf.pl out.perf > out.folded
flamegraph.pl out.folded > out.svg

具体的参数参见项目FlameGraph所约定的参数,out.svg即是我们所需要的火焰图

关于线程

Veröffentlicht am 2018-11-05

关于C++线程

Green Threads

green threads 是相对于native threads而言的,实际的green threads是依赖于jvm或者其他实现的,不论有多少,系统都认为它只是一条native thread,不能同时调度到不同的cpu中进行处理,现实意义上讲不能实现真正意义上的并行,而后出现了1:1的线程模型,Green Thread的线程概念就逐渐淡出。


Fibers and Coroutine

纤程、微线程,就是轻量版的线程,如同线程对于进程而言。纤程的优点显而易见,无需线程的开销、上下文切换、变量加锁等,轻量使其比线程的更快更有优势,目前在lua和python均开始支持。
为了避免引入第三方的线程库,有些编程语言引入了协程——Coroutine的概念,在语法层面实现了纤程的功能。


Native Threads

Native Thread 就是我们一般意义上的线程概念,cpu的最小调度单元(green thread 与 fibers都是基于第三分库或者jvm实现的,底层依然是线程的实现)

QUIC I

Veröffentlicht am 2018-03-02

QUIC

QUIC(Quick UDP Internet Connections),QUIC实际就是基于UDP实现的可靠传输协议,包含了多种控制算法,其中最主要的如bbr、cubic等,当然可以根据具体的网络需求进行不同的切换。在QUIC中,基于逻辑的channel、stream和connect等设计,保证了QUIC可以和tcp一样完成有序可靠的重传。


QUIC 的优势在哪儿

  1. QUIC 相较于TCP,QUIC在既有缓存的情况下,可以实现0 RTT的握手
  2. 队头拥塞避免
  3. 对于连接的迁移
  4. 向前纠错的支持
  5. 拥塞控制算法(当然,目前大多数linux都已经支持BBR)

关于0RTT握手

0RTT,意思是当前无须产生握手操作,立即可以开始发送数据。
QUIC是如何实现0RTT的?首先在无任何缓存情况下,QUIC是无法实现0RTT的。
先来看一下熟悉的1RTT连接:

1
2
client->server: syn
server->client: syn/ack

如果涉及到密钥交换,如https,握手过程应该是这样的:

1
2
3
4
5
6
7
client->server: syn
server->client: syn/ack
client->server: client hello
server->client: server hello、certificate、exchange key...
client->server: certificate、exchange key、change finnish...
server->client: change finnish
client->server: send data

故而这样一趟下来,将花费3个RTT。

首先,明确QUIC握手采用的是DH算法。
待续

目前遇到的一些问题

Veröffentlicht am 2017-11-22

目前遇到的一些问题

为啥EAGLContext要setCurrentContext:nil


在iOS的OpenGL中,释放资源时我们最后一般会在最末调用setCurrentContext:nil,否则再一次使用时会产生crash。原因:苹果内部将维持了context,外部退出时,这个context可能就会失效,如果再次进入且被访问,就会crash。

deleteDraw的坑


当使用完OpenGL的时候,我们一般会调用deleteDraw销毁OpenGL的一些数据。但是,在此方法中会调用setCurrentContext:context,将当前的context设置进去。所以一定要保证setCurrentContext:nil在最后调用,不然可能依然会出现crash。

关于二维码扫描


在改变metadataObjectTypes的时候一定要先设置addOutput,不然可能会出现意外的崩溃。

AVAudioSessionThread Notify Thread Crash


notify线程崩溃大多是外部去改变了sesison的属性导致的,因为AVAudio内部采用mrc,外部属性改变可能使内部变量意外release。大多是多线程引起的,尽可能的将属性的set与访问在这个通知线程中去做。[AVAudio sharedInstance] currentRout..]此方法可能导致session属性改变,故而尽量不要同时监听route时也去调用这个方法。

Objective-C 内存模型

Veröffentlicht am 2016-10-09

前篇

在Objective-C有说到Objective-C的消息机制。
Objective-C的内存模型时怎样的一个模型呢?

Objective-C 对象

@interface NSObject {
Class isa OBJC_ISA_AVAILABILITY;
}

在定义一个类的时候,其成员变量如上,发现它实际是一个Class。而Class的本质是一个结构体,如下:

struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
…
…
…
}

从上面可以看到,Class实际是继承自object,那么OC里面的类从这里来讲它应该也是一个对象。

再次追溯objc_object对象的定义:

struct objc_object {
private:
isa_t isa;
public:
Class ISA();
Class getIsa();
void initIsa(Class cls /nonpointer=false/);
void initClassIsa(Class cls /nonpointer=maybe/);
void initProtocolIsa(Class cls/nonpointer=maybe/);
void initInstanceIsa(Class cls, bool hasCxxDtor);
Class changeIsa(Class newCls);
…
…};

显而易见,OC里面的类实际是一个结构体。

模型

内存模型

如上所示,OC中出现了元类的概念,同时元类是指向自己的。

对象的模型,isa 指针指向其类,其余空间保存各级的属性(ivar):

对象模型

参考

C/C++/OC内存模型总结 参考

Objective-C 消息机制

Veröffentlicht am 2016-09-30

开头

使用消息结构而非函数调用

使用消息结构的语言,其运行时执行的代码由运行时的具体环境来决定,典型的如OC。而使用函数调用的语言,典型如C等,则是由编译器决定的。
简单的两个特点:

  1. 利用虚方法表来实现多态。
  2. 运行时的检查,OC的重要工作都由运行期的组件来完成而非编译器。

在运行时,消息和方法通过objc_msgSend进行动态绑定。

此时存在方法调用[receiver mssage]

通过此调用整个逻辑转化objc_msgSend(receiver, selector)函数,该函数的参数实际是一个不定参数,其形式如objc_msgSend(receiver, selector,arg1,arg2,…)。一般的还会传入self和_cmd,编译器将会在编译时将这两个参数传入到函数中。


动态绑定

在前文中,提到了了消息机制实际是基于objc_msgSend这个函数的。但是在这个函数中如何实现动态绑定呢?
当[Object message]时,编译器会将这个方法调用转换成objc_msgSend函数

该函数会根据Object的isa指针,找到其所属的类,然后在其类中的方法列表中查找这个message对应的@selector

如果在这个类中没有找到则会遍历其父类,直到NSObject为止。一般的,OC中的类都是NSObject的子类。如果到NSObject都仍未找到则会调用_objc_msgForward函数,该函数用于消息转发。


关于消息转发

  1. 先征询接收者,检查是否存在的动态添加。
  2. 当运行完第1步时则不再检查,而查看其他对象是否有处理,如果没有处理则会启动完整的转发机制,封装到NSInvation中。

完整的消息转发机制如下图
消息转发图

  1. resolveInstanceMethod 方法时,允许用户为类动态添加方法,如果此方法捕获到相应的实现则会进行调用。否则进行下一个方法调用。
  2. forwardingTargetForSelector:方法,尝试找到一个能响应该消息的对象。如果获取到,则直接转发给它。如果返回了nil,继续下面的动作。
  3. forwardInvocation方法,实际是处理methodSignatureForSelector(该方法将尝试获得一个方法签名。如果获取不到,则直接调用doesNotRecognizeSelector抛出异常)得到的签名,该签名被包装成Invocation传入,forwardInvocation方法中进行处理。如果处理失败则该消息将得不到处理。

一个linux系统如何启动

Veröffentlicht am 2016-09-25

关于linux启动的问题


其流程图如下所示:

流程图

  1. 启动的第一步即是BIOS阶段,在BIOS阶段大多是已经写死的程序,程序员在这一步可做的更改很少。
  2. 第二步则是BIOS程序进行外设的初始化,如键盘鼠标等。因为当BIOS程序启动之后,可能是需要使用这些外设进行一系列的操作的。所以当BIOS启动完成之后一些不要的外设就会被初始化。
  3. 引导记录,主引导扇区记录着硬盘本身的相关信息以及硬盘各个分区的大小及位置信息,是数据信息的重要入口。
  4. 这一步即是常说的Boot Loader,Boot Loader是一小段程序,用以初始化硬件设备、内存环境。让系统的软硬件环境达到合适的状态。

    大多数的Boot Loader分为两个模式:1、加载模式,即是从本地的硬盘中加载系统 2、下载模式,这种模式会通过网络去获取系统,从而加载。常见于很多学校的实验室中。

  5. 内核启动。

  6. 启动系统的第一个进程/sbin/init进程,当此进程启动之后,系统的其他的一些程序(进程)才会启动。init是所有进程的父进程。
    经过这样一个步骤,一个linux系统得以完全启动。
Finn Cheong

Finn Cheong

7 Artikel
2 Tags
GitHub
© 2019 Finn Cheong
Erstellt mit Hexo
Theme - NexT.Muse