老大让写一篇高大上的博文,那么如何才能高大上呢?从某种角度讲只要迎合老大的口味给他一篇重口味的岛国动作片剖析就能轻松过关;
从程序员角度讲,能写出高大上的范围有很多,如程序架构,算法分析、编程语言理解、操作系统理解、知名开源程序的原创分析、优秀博文的翻译等都能吸引许多同学的兴趣。今天我再教一招让博文高大上有营养的捷径就是攀高枝,用你现有的程序框架和知名的开源架构做比较剖析。今天我选择走捷径,为同学们来分析下我最近在负责的一款im客户端产品——TeamTalk(简称TT)和chorme执行模型的区别与联系。
题外话
chorme多进程多线程异步执行框架
TT单进程多线程异步执行框架
程序执行模型是啥?执行模型能够帮助程序解决啥?
简单的进程模型对比
为啥要说简单的对比呢?因为TT是单进程没有执行模型,chrome是多进程的,只需要来看chrome的多进程执行模型就可以了。chorme多进程执行模型要如何分析呢?不一样的人提出的问题不同,得出的结论也就不同。不过这副图是必须有的处置chrome的官方,可以说是chorme精华的一个缩影
Chrome进程模型
这张图告诉我们这几个点:
1 chorme是多进程的。
1.1 进程分为两类(其实有三类,还有一个plugin进程先忽略之):1 Browser进程,是所有其他进程的大脑 2
Render进程,负责chorme浏览器的渲染。Render进程与Render进程之间不能相互通信,都需要通过Browser进程来协同
1.2
Browser进程中,有RenderProcessHost,每一个host对应着一个RenderProcess,通过代理模式Browser对Host的操作会被host封装成IPC消息传递给Render进程处理
1.3 进程间通信(IPC),后续会深入分析包括windows进程间通信技术选型、通信协议的选定为啥不用google protocol
buffer
2
同时告诉我们chorme是多线程的。线程分为主线程、Render线程、I/O线程、fileThread、DBthread等,这里的线程模型是本博文讨论的重点。
TT和Chrome的线程模型
TT线程模型也可以说是执行逻辑模型如下图:
线程执行模型
这张图告诉我们几点:
1
TT是多线程的,线程分为UI主线程、网络异步I/O线程、逻辑任务执行器线程池等
1.1
主线程(UI线程):负责界面的显示和交互,以及消息的循环转发
1.2
网络异步I/O线程:负责TCP/IP长连接数据的收发
1.3 逻辑任务执行器线程池:一个简单的可伸缩的任务执行池,FIFO task list thread线程执行一些正常任务, Priority
queue thread可以执行一些优先级调度或者dependency调度,Priority queue
thread也可以在某个重任务把常驻线程耗掉的时候,开启一个新线程来执行后续饥渴任务。
2
任务执行单位——Task
1.1
task的创建和执行是分开的(command模式),可以在任何的线程中创建一个task,然后通过调用TaskPool的pushTask将任务放到TaskPool的线程池中执行
1.2
整个过程只有在pushTask的时候才加锁,等到开始执行的时候是无锁的,所以在设计task的时候,开发者需要考虑到task中的数据对象管辖的范围
1.3
task执行过程中产生的事件都是通过主线程的消息循环通知到主线程上(这一点与chrome有很大的不同)
Chrome的线程模型
chrome的线程根据执行模型大致分为:I/O
thread——负责进程间IPC的线程、render thread——负责页面渲染的线程、default
thread——负责处理常规业务的线程。虽然分为这么多的线程类型,但其实每个线程的执行流程是相差不大的,都是利用消息循环(在windows下是用messagePump),如下图
这张图告诉我们2点:
1
主线程、子线程都利用消息循环(MessagePump),来等待执行任务、事件响应
2 任务执行单位——Task
chrome的所有线程都遵从这个执行流程来执行业务,也就是说开发人员需要做的事情是如何封装一个Task并且将他放到合适的thread中去做即调用每个线程相应的PostTask。换句话说开发任务在chrome造的轮子基础上只需要了解如何创建一个Task以及每个Task的职责范围以及数据的管辖范围,一图胜千言先上两张图吧(出处:http://www.ha97.com/2908.html):
Task的执行模型
这两张图告诉我们关于task的这几点:
1
task的创建和执行是分开的(command模式),可以在任何的线程中创建一个task,然后通过调用另外线程的postTask将任务放到另外的那个线程中等待执行
2
整个过程只有在pushTask的时候才加锁,等到开始执行的时候是无锁的,所以在设计task的时候,开发者需要考虑到task中的数据对象管辖的范围
3
task是异步执行的,但是chrome又让这个异步过程变得非常简单,如右图:A线程需要B线程做一些事情,然后回到A线程继续做一些事情;在Chrome下你可以这样来做:生成一个Task,放到B线程的队列中,在该Task的Run方法最后,会生成另一个Task,这个Task会放回到A的线程队列,由A来执行。
TT与chrome多线程异步执行框架的对比
相同点:
1
执行框架都是用task作为业务执行的一个基本单位,将整个工程项目的业务进行分解
2
创建和执行task的环境是可以分开的(command模式)
3
都支持优先级任务(Priority task)调度,延迟执行任务(delay task),空闲时执行任务(Idle
task)
4
在任务执行过程中都是极力避免锁的存在,仅仅在将Task放入消息队列的时候才存在
不同点:
1 消息循环
TT将消息循环只放在了主线程,任务在子线程中执行过程中发出的通知都是通过主线程的消息循环来派发的
chrome在这一点做得更灵活,每个子线程都有自己的消息循环监听任何任务过来的通知,即有处理watcher的功能2 线程任务的设计上
chrome允许创建的每个线程都有执行各种任务的能力,并且也为之创建了各种的任务执行队列来异步执行,这样的轮子便于整个项目功能和业务的分解
TT上对于执行任务的线程可以说是一统的,即任何的任务在TT上只能在逻辑线程池中执行,任务不区分类型(chrome上有I/O相关的任务在I/Othread执行、render相关的任务在render
thread执行)3 UI渲染绘制上
由于本身采取的绘制不同,TT是GDI绘制的,chrome是directx绘制的,所以绘制的策略上也是很大的不同。
简单讲TT的和界面相关的任何处理都需要在主线程上执行,这也是为啥消息循环的设计上TT放到主线程上的一个原因
4
具体实现上
虽说都是用c++实现的,但是level真实不一样,chrome整个项目都是要c++
模板元编程,相信蛮多c++程序员看起来都会很累包括我自己,它提供了一大套的模板封装(参见task.h),可以将Task摆脱继承结构、函数名、函数参数等限制(就是基于模板的伪function实现,想要更深入了解,建议直接看鼻祖《Modern
C++》和它的Loki库…)
TT和chrome执行模型对比分析,布布扣,bubuko.com