WebRTC 源码分析之一:几个核心设计概念

WebRTC 源码分析之一:几个核心设计概念,第1张

下面要介绍的是 WebRTC 中最核心的几个概念。

1、OnMessage 消息机制

对象内部发送消息。这是一个普遍性,通用性的设计,例如 MFC、Android 消息机制都是如此。

在对象内把消息 Post 到主线程,并且把当前对象的句柄放在消息体内,线程队列根据消息里对象句柄来回调对应的 OnMessage 函数

2、sigslot 消息机制

对象之间发送消息。

发送者(发布主题者)生命一个信号量,绑定到接受者(观察者)的函数,当发送者调用一次信号量时,直接会回调观察者的函数。

3、消息进阶传递机制(OnMessage 和 sigsolt 结合)

最底层 sigslot 传递消息到中层后,中层使用 Post 消息传递到本层的OnMessage,在 OnMessage 里使用 sigsolt 再往上层传递消息。

即同层之间用 OnMessage 消息传递,下层向上层传递则使用 sigsolt。

4、线程封装原理

线程create传送的参数是一个 ThreadInit 的类指针,这个指针包含了一个正常的本身的线程类指针Thread,同时也包含了一个 Runnable 指针。

Start(Runnable * runnable),runnable 为空时,启用的是 Thread 的 Run,不为空时,启用的是 Runnable 的 Run

本文摘录于海阔天空的博客,作者: zjg555543,发布时间: 2014-07-09

打开发布的文件,看到里面的bin目录。

第1步:创建一个web站点(ASP.ent),将所有的发布文件都拷贝进去。

第2步:打开ILSpy ,---文件---打开---bin目录里的一个dll文件,

第3步:文件--保存代码,就可以把这个dll保存成一个有源代码的项目文件(Hidistro.SaleSystem.Member.csproj)。

第4步:在刚刚创建的web站点,将Hidistro.SaleSystem.Member.csproj 项目添加进去;

第5步:一次类推,将所有需要反编译的dll都弄成源码添加到web站点;

第6步:生成整个解决方案,一看有很多报错信息,没关系,咱们一个一个来解决; 这里的报错信息绝大部分都是因为 没有引用dll或者是项目之间没有引用上造成的。知道原因后,我们就好解决了。

-

此篇博客紧承上一篇,上片讨论了我们的webpack整个处理单个文件的流程,这一节主要说一说webpack的文件打包问题,其实本身是比较简单的,但是有异步块和html-plugin的加入,使这个步骤变得尤为复杂,这里先介绍几个重要的概念:

上一节中,我们成功的对每个文件进行了处理,并通过了process的方法对所有入口文件以及他们的依赖文件进行了处理,获得了最初的依赖文件列表,现在我们就可以对资源的依赖进行优化处理,本片的内容将从webpack/lib/Compiler.js:510的断点开始逐步的对源码进行分析

在seal之前,由于一轮compilition已经执行完成,先调用finish方法进行收尾处理与之对应的是我们注册的finish-modules事件,

这里我们首先看到的又是index.ejs这个老朋友,由于他是单独的文件经过了loader处理没有获得额外的处理函数的依赖,所以最终这里看到的module实际上是它的js外壳包起来的ejs文件,此阶段也还没有进行资源hash的注入等等

这里有一个FlagDependencyExportsPlugin进行了操作,听名字可能就听出来了,他是对我们资源中的export使用进行一个标志的作用, 和我们最终做出的tree shaking效果可能是相关的

调用seal事件处理

处理我们的preparedChunk,这个东西是我们刚好在进行addEntry的时候添加上的不知道你们还记不记得,中途就没有添加过新的,所以讲道理,一个entry是只用一个的,但是这里使用了一个数组不知道有什么用意

然后把这个入口模块添加到了block里面,过后打包也是从block里面拿数据,block里面的东西会被打包成为单独的文件,但是还是工作在之前的上下文中,这里可以通过看一下这里的import即是我们之前在路由文件中通过import函数设置引入的动态加载路由资源

进入到processDependenciesBlockForChunk函数,就开始处理我们之前做好准备的block了,这里这是一个不断处理依赖的过程,但是没有使用递归的做法,毕竟文件太多了,不断的进行递归会浪费很多空间,取而代之的是使用queue进行记录,处理过程中不断把新的需要处理的模块放到queue里面等待下一步处理

在每一步的处理中

处理完这一波循环依赖过后,本身的依赖树结构变得扁平化,之前一层一层的模块通过dependency连接起来作为一个树的结构,而现在变成了顶层最终的几个chunk

可以看到我们最终在这个入口(entry)设置中拿到了9个chunk,她们都有_modules属性,我们的所有依赖都是放到这里面的,是用的一个Set进行存储,其中的依赖关系则是通过origins和reason等标识进行模块间关系的连接的

还可以将我们的入口chunk和异步加载的chunk进行一些对比(上面的是入口文件),下面的chunk中出现的origins就是指向我们之前的router那个module

这个图里也可以看到,两个chunk实际上按照自己的路子搜集了所有的依赖,结果导致了_modules的文件数量都达到了一千多个,这就是我们常使用的CommonChunk插件需要处理的地方了,稍后进行讨论

这轮处理我们成功的把主要的入口module和异步加载的模块区分开了,然后开始按照类似的逻辑处理我们的第一个入口模块

这个时候拿到chunkDependencies进行处理,这就是之前那个存储block的东西,但是有个很奇怪的地方,就是这里面居然只有三个chunk,而不是和上面的一样是9个也不是只有一个入口模块,这就让人无从下手了(我异步加载的模块并不是一样的,而且这些模块之间没有没相互依赖)

喜闻乐见进行第二次处理,首先取出一个chunk拿到对应的存储在value中的deps,对每一个项目添加上了他们的parent,但是有个组件就是用来removeParent的

在RemoveParentModulesPlugin这个插件中,针对每个module都做了处理,看看这些模块在哪些chunk之中有被使用到,把他们所存在的chunks按照id记录下来,并改变她们的reason为几种统一的chunk组合数组。这样就做到了每个module知道了自己被哪些chunk使用,但是从之前的单一reason到现在的多reason具体不知道有什么用(恩。。可能是为作用域提升做准备)

然后嘛,移除空的模块,不需要多解释

然后这层处理就算完啦,主要进行了模块的依赖梳理和拆分,并为他们添加上了指向父节点的指针(话说之前不是有origins吗)

对模块进行排序工作,不过只是按照索引进行排序罢了,那个按照出现概率进行排序处理的插件不是在这里工作的

又是那个flag的插件进行了处理,但是只是把所有模块的used设置为了true,还有为一些被依赖的module设置上他们的usedExports为true

ChunkConditions插件用于监视模块上是否有chunkCondition函数,并返回他的执行结果,如果有模块的此函数返回了false,那么将会重写这个模块(重写即是重新添加进入parent的链接以及reason等的设置)并且还会返回true,到至此过程不断执行直至condition全部OK

RemoveParentModulesPlugin这个插件的作用有点玄乎,看样子是对每个chunk进行处理,看对于多个chunk中都有的某一些module,会直接把他们的reason设置为主要的入口chunk,而后把当前chunk中的module移除掉(话说这个事情不是应该Common来做吗)

然后移除所有空的模块,再就是移除重复的模块了(话说一直用set神他妈还会有重复的)

然后进行各种优化,比如出现的概率大的放到前面,这里还是做了module和chunk两种优化,也是有毛病,就像我们的react项目中可以知道react的使用次数最多,那么他就被放到了最钱前面,紧随其后的是echart等

HashedModuleIdsPlugin插件为我们的模块计算出它的id,默认是通过md5进行计算,解出来的是base64的,而且计算的参数也仅仅只是通过模块的libId进行hash,而这个libhash只是相对位置,连绝对的都不是,所以算下来这个东西能够当成单个文件的hash了

applyModuleId,到这里你可能会想,诶之前不是已经设置好每个元素的id了吗,为什么还要搞这么个函数专门处理,我们在上一个生成id的时候实际上得到的id是根据我们的设置进行了截断的,实际上拿到的hash碰撞的概率非常大,我们看看下面这个筛选的处理就可以知道,1885个模块里面竟然又3个重复的id,这种时候就要特殊处理了

执行sortItemsWithModuleIds依据id进行排序,不只是最外面的chunk,就连reason里的id也会被重新排序,也是蛮逗的,这里直接用的是id做比较并没有判断类型,也就是说把数字和字符串会混到一起,就算你是class也会拿valueOf出来比较,想想还是蛮刺激的,不过其实比较完成也没有太特殊的用途就这么随意一点也好

中间一些处理recordId的我忽略掉了

然后开始处理hash了,这里的hash具体使用了哪些参数和长度是多少呢

可以在此阶段添加hashSalt即噪声,给hash值添加一些特征

进入mainTemplate的处理函数中,添加了一些字符串参数和数字参数,并且调用了mainTemplate的hash插件,但是她们的执行过程并不是保证我们最后生成的文件中能够有结果的hash值,便于请求对应的资源文件,而是仅仅在hash的过程中添加了一些干扰的路径参数等

最终一轮hash下来,chunk会得到自己的renderHash,而compilation会得到一个针对编译过程的hash,这个hash就跟我们的所有资源扯上关联啦,所以每次都是新的

创建模块资源咯~

这些文章写的都有点水,相当于是阅读源码时候做的笔记了,看看图个乐子吧


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/807917.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-08-29
下一篇2023-08-29

发表评论

登录后才能评论

评论列表(0条)

    保存