微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结

作者 : 开心源码 本文共14562个字,预计阅读时间需要37分钟 发布时间: 2022-05-13 共309人阅读

本文来自微信开发团队WeMobileDev公众号的原创技术分享,原题“iOS 微信编译速度优化分享”,即时通讯网收录时排版及部分文字有修订和优化。

1、引言

岁月真是个养猪场,这几年,人胖了,微信代码也翻了。

记得 14 年转岗来微信时,用自己笔记本编译微信工程才十来分钟。如今用公司配的 17 年款 27-inch iMac 编译要接近半小时;偶然间升级完代码,又莫名其妙需要全新编译。在这么低的编译效率下,开发心情受到严重影响。

于是年初我向上头请示,优化微信编译效率,上头也同意了。

学习交流:

– 即时通讯/推送技术开发交流5群:215477170?[推荐]

– 手机端IM开发入门文章:《新手入门一篇就够:从零开发手机端IM》

(本文同步发布于:http://www.52im.net/thread-2873-1-1.html)

2、相关文章

《微信团队分享:微信手机端的全文检索多音字问题处理方案》

《微信团队分享:iOS版微信的高性能通用key-value组件技术实践》

《微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?》

《微信团队原创分享:iOS版微信的内存监控系统技术实践》

《iOS后端唤醒实战:微信收款到账语音提示技术总结》

《微信团队分享:微信Android版小视频编码填过的那些坑》

《微信移动端的本地数据全文检索优化之路》

《微信团队披露:微信界面卡死超级bug“15。。。。”的来龙去脉》

《微信用户端团队负责人技术访谈:如何着手用户端性能监控和优化》

《微信团队原创分享:Android版微信的臃肿之困与模块化实践之路》

《微信团队原创分享:微信用户端SQLite数据库损坏修复实践》

《微信团队原创分享:Android版微信从300KB到30MB的技术演进》

《微信团队原创分享:Android内存泄漏监控和优化技巧总结》

《全面总结iOS版微信更新iOS9遇到的各种“坑”》

《微信团队原创资源混淆工具:让你的APK立减1M》

《Android版微信安装包“减肥”实战记录》

《iOS版微信安装包“减肥”实战记录》

《手机端IM实践:iOS版微信界面卡慢监测方案》

《手机端IM实践:iOS版微信小视频功能技术方案实录》

《手机端IM实践:iOS版微信的多设施字体适配方案讨论》

《手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)》

《微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅》

3、现有方案

在动手之前,先搜索目前已有方案,大概情况如下。

3.1 优化工程配置

1)将 Debug Information Format 改为 DWARF:

Debug 时是不需要生成符号表,可以检查一下子工程(尤其开源库)有没有设置正确。

2)将 Build Active Architecture Only 改为 Yes:

Debug 时是不需要生成全架构,可以检查一下子工程(尤其开源库)有没有设置正确。

3)优化头文件搜索路径:

避免工程 Header Search Paths 设置了路径递归引用:

Xcode 编译源文件时,会根据 Header Search Paths 自动增加 -I 参数,假如递归引用的路径下子目录越多,-I 参数也越多,编译器预解决头文件效率就越低,所以不能简单的设置路径递归引用。同样 Framework Search Paths 也相似解决。

3.2 使用 CocoaPods 管理第三方库

这是业界常用的做法,利用?cocoapods?插件 cocoapods-packager 将任意的 pod 打包成 Static Library,省去重复编译的时间;但缺点是不方便调试源码,假如库代码反复修改,需要重新生成二进制并上传到内部服务器,等等。

3.3 CCache

CCache?是一个能够把编译的中间产物缓存起来的工具,不需要过多修改项目配置,也不需要修改开发工具链。Xcode 9 有个很偶然的 bug,在源码没有任何修改的情况下经常触发全新编译,用 CCache 很好的处理这一问题。但随着 Xcode 10 修复全量编译问题,这一方案逐渐弃用了。

3.4 distcc

distcc?是一个分布式编译工具,它原理是把本地多个编译任务分发到网络中多个机器,其余机器编译完成后,再把产物返回给本机上执行链接,最终得到编译结果。

3.5 硬件处理

如把 Derived Data 目录放到由内存创立的虚拟磁盘,或者者购买最新款的 iMac Pro…

4、实践过程

4.1 优化编译选项

1)优化头文件搜索路径:

把少量递归引用路径去了后,整体编译速度快了 20s。

2)关闭 Enable Index-While-Building Functionality:

这选项无意中找到的(Xcode 9 的新特性?),默认打开,作用是 Xcode 编译时会顺带建立代码索引,但影响编译速度。关闭后整体编译速度快 80s(Xcode 会换回以前的方式,在空闲时间建立代码索引)。

4.2 优化 kinda

kinda 是今年引入支付跨平台框架(C++),但编译速度奇慢,一个源文件编译都要 30s。另外生成的二进制大小在 App 占比较高,感觉有不少冗余代码,理论上减少冗余代码也能加快编译速度。

经过分析 LinkMap 文件和使用 Xcode Preprocess 某些源文件,发现有以下问题:

1)proto 文件生成的代码较多;

2)某个基类/宏使用了大量模版。

对于问题一:可以设置 proto 文件选项为 optimize_for=CODE_SIZE 来让?protobuf?编译器生成精简版代码。但我是用自己的工具生成(具体原理可看《iOS版微信安装包“减肥”实战记录》),代码更少。

对于问题二:因为模版是编译期间的多态(添加代码膨胀和编译时间),所以可以把模版基类改成虚基类这种运行时的多态;另外推荐使用 hyper_function 取代 std::function,使得基类用通用函数指针,就能存储任意 lambda 回调函数,从而避免基类模板化。

例如:

template<typenameRequest, typenameResponse>

classBaseCgi {

public:

????BaseCgi(Request request, std::function<void(Response &)> &callback) {

????????_request = request;

????????_callback = callback;

????}

????voidonRequest(std::vector<uint8_t> &outData) {

????????_request.toData(outData);

????}

????voidonResponse(std::vector<uint8_t> &inData) {

????????Response response;

????????response.fromData(inData);

????????callback(response);

????}

public:

????Request _request;

????std::function<void(Response &)> _callback;

};

classCgiA : publicBaseCgi<RequestA, ResponseA> {

public:

????CgiA(RequestA &request, std::function<void(ResponseA &)> &callback) :

????????BaseCgi(request, callback) {}

};

可改成:

class BaseRequest {

public:

????virtual void toData(std::vector<uint8_t> &outData) = 0;

};

classBaseResponse {

public:

????virtualvoidfromData(std::vector<uint8_t> &outData) = 0;

};

classBaseCgi {

public:

????template<typenameRequest, typenameResponse>

????BaseCgi(Request &request, hyper_function<void(Response &)> callback) {

????????_request = newRequest(request);

????????_response = newResponse;

????????_callback = callback;

????}

????voidonRequest(std::vector<uint8_t> &outData) {

????????_request->toData(outData);

????}

????voidonResponse(std::vector<uint8_t> &inData) {

????????_response->fromData(inData);

????????_callback(*_response);

????}

public:

????BaseRequest *_request;

????BaseResponse *_response;

????hyper_function<void(BaseResponse &)> _callback;

};

classRequestA : publicBaseRequest { … };

classResponseA : publicBaseResponse { … };

classCgiA : publicBaseCgi {

public:

????CgiA(RequestA &request, hyper_function<void(ResponseA &)> &callback) :

????????BaseCgi(request, callback) {}

};

BaseCgi 由模版基类变成只有构造函数是模板的基类,onRequest 和 onResponse 逻辑代码并不由于基类模版实例化而被“复制黏贴”。

经过上述优化:整体编译速度快了 70s,而 kinda 二进制也减少了 60%,效果特别显著。

4.3 使用 PCH 预编译头文件

PCH(Precompile Prefix Header File)文件,也就是预编译头文件,其文件里的内容能被项目中的其余所有源文件访问。通常放少量通用的宏和头文件,方便编写代码,提高效率。

另外 PCH 文件预编译完成后,后面用到 PCH 文件的源文件编译速度也会加快。缺点是 PCH 文件和 PCH 引用到的头文件内容一旦发生变化,引用到 PCH 的所有源文件都要重新编译。所以使用时要谨慎。

在 Xcode 里设置 Prefix Header 和 Precompile Prefix Header 即用 PCH 文件并对它进行预编译:

微信使用 PCH 预编译后:编译速度提升非常可观,快了接近 280s。

5、终极优化

通过上述优化,微信工程的编译时间由原来的 1,626.4s 下降到 1,182.8s,快了将近 450s,但依然需要 20 分钟,令人不满意。

假如继续优化,得从编译器下手。正如我们平时做的用户端性能优化,在优化之前,先分析原理,输出每个地方的耗时,针对耗时做相对应的优化。

5.1 编译原理

编译器,是把一种语言(通常是高级语言)转换为另一种语言(通常是低级语言)的程序。

大多数编译器由三部分组成:

各部分的作用如下:

前台(Frontend):负责解析源码,检查错误,生成笼统语法树(AST),并把 AST 转化成类汇编中间代码;

优化器(Optimizer):对中间代码进行架构无关的优化,提高运行效率,减少代码体积,例如删除 if (0) 无效分支;

后台(Backend):把中间代码转换成目标平台的机器码。

LLVM 实现了更通用的编译框架,它提供了一系列模块化的编译器组件和工具链。首先它定义了一种 LLVM IR(Intermediate Representation,中间表达码)。Frontend 把原始语言转换成 LLVM IR;LLVM Optimizer 优化 LLVM IR;Backend 把 LLVM IR 转换为目标平台的机器语言。这样一来,不论是新的语言,还是新的平台,只需实现对应的 Frontend 和 Backend,新的编译器就出来了。

在 Xcode,C/C++/ObjC 的编译器是 Clang(前台)+LLVM(后台),简称 Clang。

Clang 的编译过程有这几个阶段:

?? clang -ccc-print-phases main.m

0: input, “main.m”, objective-c

1: preprocessor, {0}, objective-c-cpp-output

2: compiler, {1}, ir

3: backend, {2}, assembler

4: assembler, {3}, object

5: linker, {4}, image

6: bind-arch, “x86_64”, {5}, image

1)预解决:

这阶段的工作主要是头文件导入,宏开展/替换,预编译指令解决,以及注释的去除。

2)编译:

这阶段做的事情比较多,主要有:

a. 词法分析(Lexical Analysis):将代码转换成一系列 token,如大中小括号 paren'()’ square'[]’ brace'{}’、标识符 identifier、字符串 string_literal、数字常量 numeric_constant 等等;

b. 语法分析(Semantic Analysis):将 token 流组成笼统语法树 AST;

c. 静态分析(Static Analysis):检查代码错误,例如参数类型能否错误,调用对象方法能否有实现;

d. 中间代码生成(Code Generation):将语法树自顶向下遍历逐渐翻译成 LLVM IR。

3)生成汇编代码:

LLVM 将 LLVM IR 生成当前平台的汇编代码,期间 LLVM 根据编译设置的优化级别 Optimization Level 做对应的优化(Optimize),例如 Debug 的 -O0 不需要优化,而 Release 的 -Os 是尽可能优化代码效率并减少体积。

4)生成目标文件:

汇编器(Assembler)将汇编代码转换为机器代码,它会创立一个目标对象文件,以 .o 结尾。

5)链接:

链接器(Linker)把若干个目标文件链接在一起,生成可执行文件。

5.2 分析耗时

Clang/LLVM 编译器是开源的,我们可以从官网下载其源码,根据上述编译过程,在每个编译阶段埋点输出耗时,生成定制化的编译器。在自己准备动手的前一周,国外大神 Aras Pranckevi?ius 已经在 LLVM 项目提交了 rL357340 修改:clang 添加 -ftime-trace 选项,编译时生成 Chrome(chrome://tracing) JSON 格式的耗时报告,列出所有阶段的耗时。

效果如下:

说明如下:

1)整体编译(ExecuteCompiler)耗时 8,423.8ms

2)其中前台(Frontend)耗时 5,307.9ms,后台(Backend)耗时 3,009.6ms

3)而前台编译里头文件 SourceA 耗时 xx ms,B 耗时 xx ms,…

4)头文件解决里 Parse ClassA 耗时 xx ms,B 耗时 xx ms,…

5)等等

这就是我想要的耗时报告!

接下来修改工程?CC={YOUR PATH}/clang,让 Xcode 编译时使用自己的编译器;同时编译选项?OTHER_CFLAGS?后面添加?-ftime-trace,每个源文件编译后输出耗时报告。

最终把所有报告汇聚起来,形成整体的编译耗时:

由整体耗时可以看出:

1)编译器前台解决(Frontend)耗时 7,659.2s,占整体 87%;

2)而前台解决下头文件解决(Source)耗时 7,146.2s,占整体 71.9%!

猜测:头文件嵌套严重,每个源文件都要引入几十个甚至几百个头文件,每个头文件源码要做预解决、词法分析、语法分析等等。实际上源文件不需要使用某些头文件里的定义(如 class、function),所以编译时间才那么长。

于是又写了个工具,统计所有头文件被引用次数、总解决时间、头文件分组(指一个耗时顶部的头文件所引用到的所有子头文件的集合)。

列出一份表格(截取 Top10):

如上表所示:

Header1 解决时间 1187.7s,被引用 2,304 次;

Header2 解决时间 1,124.9s,被引用 3,831 次;

后面 Header3~10 都是被 Header1 引用。

所以可以尝试优化 TopN 头文件里的头文件引用,尽量不包含其余头文件。

5.3 处理耗时

通常我们写代码时,假如用到某个类,就直接 include 该类公告所在头文件,但在头文件,我们可以用前置公告处理。

因而优化头文件思路很简单:就是能用前置公告,就用前置公告替代 include。

实际上改动量非常大:我跟组内另外的同事 vakeee 分工优化 Header1 和 Header2,花了整整 5 个工作日,才改完。效果还是有,整体编译时间减少 80s。

但需要优化的头文件还有几十个,我们不可能继续做这种体力活。因而我们可以做这样的工具,通过 AST 找到代码里出现的标识符(包括类型、函数、宏),以及标识符定义所在文件,而后分析能否需要 include 它定义所在文件。

先看看代码如何转换 AST,如以下代码:

// HeaderA.h

struct StructA {

????intval;

};

// HeaderB.h

structStructB {

????intval;

};

// main.c

#include “HeaderA.h”

#include “HeaderB.h”

inttestAndReturn(structStructA *a, structStructB *b) {

????returna->val;

}

控制台输入:

?? TestContainer clang -Xclang -ast-dump -fsyntax-only main.c

TranslationUnitDecl 0x7f8f36834208 <<invalid sloc>> <invalid sloc>

|-RecordDecl 0x7faa62831d78 <./HeaderA.h:12:1, line:14:1> line:12:8 struct StructA definition

| `-FieldDecl 0x7faa6383da38 <line:13:2, col:6> col:6 referenced val ‘int’

|-RecordDecl 0x7faa6383da80 <./HeaderB.h:12:1, line:14:1> line:12:8 struct StructB definition

| `-FieldDecl 0x7faa6383db38 <line:13:2, col:6> col:6 val ‘int’

`-FunctionDecl 0x7faa6383de50 <main.c:35:1, line:37:1> line:35:5 testAndReturn ‘int (struct StructA *, struct StructB *)’

??|-ParmVarDecl 0x7faa6383dc30 <col:19, col:35> col:35 used a ‘struct StructA *’

??|-ParmVarDecl 0x7faa6383dd40 <col:38, col:54> col:54 b ‘struct StructB *’

??`-CompoundStmt 0x7faa6383dfc8 <col:57, line:37:1>

????`-ReturnStmt 0x7faa6383dfb8 <line:36:2, col:12>

??????`-ImplicitCastExpr 0x7faa6383dfa0 <col:9, col:12> ‘int'<LValueToRValue>

????????`-MemberExpr 0x7faa6383df70 <col:9, col:12> ‘int’lvalue ->val 0x7faa6383da38

??????????`-ImplicitCastExpr 0x7faa6383df58 <col:9> ‘struct StructA *'<LValueToRValue>

????????????`-DeclRefExpr 0x7faa6383df38 <col:9> ‘struct StructA *’lvalue ParmVar 0x7faa6383dc30 ‘a”struct StructA *’

从上可以看出:每一行包括 AST Node 的类型、所在位置(文件名,行号,列号)和结点形容信息。头文件定义的类也包含进 AST 中。AST Node 常见类型有 Decl(如 RecordDecl 结构体定义,FunctionDecl 函数定义)、Stmt(如 CompoundStmt 函数体括号内实现)。

Clang AST 有三个重要的基类:ASTFrontendAction、ASTConsumer 以及 RecursiveASTVisitor。

ClangTool 类读入命令行配置项后初始化 CompilerInstance;CompilerInstance 成员函数 ExcutionAction 会调用 ASTFrontendAction 3 个成员函数 BeginSourceFile(准备遍历 AST)、Execute(解析 AST)、EndSourceFileAction(结束遍历)。

ASTFrontendAction 有个重要的纯虚函数 CreateASTConsumer(会被自己 BeginSourceFile 调用),用于返回读取 AST 的 ASTConsumer 对象。

代码如下:

class MyFrontendAction : public clang::ASTFrontendAction {

public:

????virtualstd::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef file) override {

????????TheRewriter.setSourceMgr(CI.getASTContext().getSourceManager(), CI.getASTContext().getLangOpts());

????????returnllvm::make_unique<MyASTConsumer>(&CI);

????}

};

intmain(intargc, constchar**argv) {

????clang::tooling::CommonOptionsParser op(argc, argv, OptsCategory);

????clang::tooling::ClangTool Tool(op.getCompilations(), op.getSourcePathList());

????intresult = Tool.run(clang::tooling::newFrontendActionFactory<MyFrontendAction>().get());

????returnresult;

}

ASTConsumer 有若干个可以 override 的方法,用来接收 AST 解析过程中的回调,其中之一是工具用到的 HandleTranslationUnit 方法。当编译单元 TranslationUnit 的 AST 完整解析后,HandleTranslationUnit 会被回调。我们在 HandleTranslationUnit 使用 RecursiveASTVisitor 对象以深度优先的方式遍历 AST 所有结点。

代码如下:

class MyASTVisitor

: public clang::RecursiveASTVisitor<MyASTVisitor> {

public:

????explicitMyASTVisitor(clang::ASTContext *Ctx) {}

????boolVisitFunctionDecl(clang::FunctionDecl* decl) {

????????// FunctionDecl 下的所有参数公告允许前置公告取代 include

????????// 如上面 Demo 代码里 StructA、StructB

????????returntrue;

????}

????boolVisitMemberExpr(clang::MemberExpr* expr) {

????????// 被引用的成员所在的类,需要 include 它定义所在文件

????????// 如 StructA

????????returntrue;

????}

????boolVisitXXX(XXX) {

????????returntrue;

????}

????// 同一个类型,可能出现若干次判定结果

????// 假如其中一个判断的结果需要 include,则 include

????// 否则使用前置公告代替 include

????// 例如 StructA 只能 include,StructB 可以前置公告

};

class MyASTConsumer : public clang::ASTConsumer {

private:

????MyASTVisitor Visitor;

public:

????explicitMyASTConsumer(clang::CompilerInstance *aCI)

????: Visitor(&(aCI->getASTContext())) {}

????void HandleTranslationUnit(clang::ASTContext &context) override {

????????clang::TranslationUnitDecl *decl = context.getTranslationUnitDecl();

????????Visitor.TraverseTranslationUnitDecl(decl);

????}

};

工具框架大致如上所示。

不过早在 2011 年 Google 内部做了个基于 Clang libTooling 的工具?include-what-you-use,用来整理 C/C++ 头文件。

这个工具的使用效果如下:

?? include-what-you-use main.c

HeaderA.h has correct #includes/fwd-decls)

HeaderB.h has correct #includes/fwd-decls)

main.c should add these lines:

struct StructB;

main.c should remove these lines:

– #include “HeaderB.h”? // lines 2-2

The full include-list formain.c:

#include “HeaderA.h”? // for StructA

struct StructB;

我们在?IWYU?基础上,添加了 ObjC 语言的支持,并加强它的逻辑,让结果更好看(通常 IWYU 解决完后,会引入很多头文件和前置公告,我们做剪枝解决,进一步去掉多余的头文件和前置公告,篇幅限制就不多做解释了)。

微信源码通过工具优化头文件引入后,整体编译时间降到了?710s。另外头文件依赖的减少,也能降低因修改头文件引起大规模源码重编的可能性。

我们再用编译耗时分析工具分析当前瓶颈:

WCDB?头文件解决时间太长了,业务代码(如 Model 类)没有很好的隔离 WCDB 代码,把 WINQ 暴露出去,外面被动 include WCDB 头文件。处理方法有很多,例如 WCDB 相关放 category 头文件(XXModel+WCDB.h)里引入,或者者跟其余库一样,把 放 PCH。

最终编译时间优化到?540s?以下,是原来的三分之一,编译效率得到巨大的提升。

6、优化总结

总结微信的编译优化方案:

即:

A)优化头文件搜索路径;

B)关闭 Enable Index-While-Building Functionality;

C)优化 PB/模版,减少冗余代码;

D)使用 PCH 预编译;

E)使用工具优化头文件引入;尽量避免头文件里包含 C++ 标准库。

7、未来展望

期待公司的蓝盾分布式编译 for ObjC;另外可以把业务代码模块化,项目文件按模块加载,目前 kinda/小程序/mars 在很好的实践中。

8、参考文献

[1]?如何将 iOS 项目的编译速度提高5倍

[2]?深入剖析 iOS 编译 Clang / LLVM

[3]?Clang之语法笼统语法树AST

[4]?time-trace: timeline / flame chart profiler for Clang

[5]?Introduction to the Clang AST

附录:QQ、微信团队原创技术文章汇总

《微信朋友圈千亿访问量背后的技术挑战和实践总结》

《腾讯技术分享:腾讯是如何大幅降低带宽和网络流量的(图片压缩篇)》

《腾讯技术分享:腾讯是如何大幅降低带宽和网络流量的(音视频技术篇)》

《微信团队分享:微信手机端的全文检索多音字问题处理方案》

《腾讯技术分享:Android版手机QQ的缓存监控与优化实践》

《微信团队分享:iOS版微信的高性能通用key-value组件技术实践》

《微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?》

《腾讯技术分享:Android手Q的线程死锁监控系统技术实践》

《微信团队原创分享:iOS版微信的内存监控系统技术实践》

《让互联网更快:新一代QUIC协议在腾讯的技术实践分享》

《iOS后端唤醒实战:微信收款到账语音提示技术总结》

《腾讯技术分享:社交网络图片的带宽压缩技术演进之路》

《微信团队分享:视频图像的超分辨率技术原理和应用场景》

《微信团队分享:微信每日亿次实时音视频聊天背后的技术解密》

《QQ音乐团队分享:Android中的图片压缩技术详解(上篇)》

《QQ音乐团队分享:Android中的图片压缩技术详解(下篇)》

《腾讯团队分享:手机QQ中的人脸识别酷炫动画效果实现详解》

《腾讯团队分享 :一次手Q聊天界面中图片显示bug的追踪过程分享》

《微信团队分享:微信Android版小视频编码填过的那些坑》

《微信移动端的本地数据全文检索优化之路》

《企业微信用户端中组织架构数据的同步升级方案优化实战》

《微信团队披露:微信界面卡死超级bug“15。。。。”的来龙去脉》

《QQ 18年:解密8亿月活的QQ后端服务接口隔离技术》

《月活8.89亿的超级IM微信是如何进行Android端兼容测试的》

《以手机QQ为例讨论手机端IM中的“轻应用”》

《一篇文章get微信开源手机端数据库组件WCDB的一切!》

《微信用户端团队负责人技术访谈:如何着手用户端性能监控和优化》

《微信后端基于时间序的海量数据冷热分级架构设计实践》

《微信团队原创分享:Android版微信的臃肿之困与模块化实践之路》

《微信后端团队:微信后端异步消息队列的优化更新实践分享》

《微信团队原创分享:微信用户端SQLite数据库损坏修复实践》

《腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率》

《腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)》

《腾讯原创分享(三):如何大幅压缩移动网络下APP的流量消耗(上篇)》

《微信Mars:微信内部正在使用的网络层封装库,即将开源》

《如约而至:微信自用的手机端IM网络层跨平台组件库Mars已正式开源》

《开源libco库:单机千万连接、支撑微信8亿客户的后端框架基石 [源码下载]》

《微信新一代通信安全处理方案:基于TLS1.3的MMTLS详解》

《微信团队原创分享:Android版微信后端保活实战分享(进程保活篇)》

《微信团队原创分享:Android版微信后端保活实战分享(网络保活篇)》

《Android版微信从300KB到30MB的技术演进(PPT讲稿) [附件下载]》

《微信团队原创分享:Android版微信从300KB到30MB的技术演进》

《微信技术总监谈架构:微信之道——大道至简(演讲全文)》

《微信技术总监谈架构:微信之道——大道至简(PPT讲稿) [附件下载]》

《如何解读《微信技术总监谈架构:微信之道——大道至简》》

《微信海量客户背后的后端系统存储架构(视频+PPT) [附件下载]》

《微信异步化改造实践:8亿月活、单机千万连接背后的后端处理方案》

《微信朋友圈海量技术之道PPT [附件下载]》

《微信对网络影响的技术实验及分析(论文全文)》

《一份微信后端技术架构的总结性笔记》

《架构之道:3个程序员成就微信朋友圈日均10亿发布量[有视频]》

《快速裂变:见证微信强大后端架构从0到1的演进历程(一)》

《快速裂变:见证微信强大后端架构从0到1的演进历程(二)》

《微信团队原创分享:Android内存泄漏监控和优化技巧总结》

《全面总结iOS版微信更新iOS9遇到的各种“坑”》

《微信团队原创资源混淆工具:让你的APK立减1M》

《微信团队原创Android资源混淆工具:AndResGuard [有源码]》

《Android版微信安装包“减肥”实战记录》

《iOS版微信安装包“减肥”实战记录》

《手机端IM实践:iOS版微信界面卡慢监测方案》

《微信“红包照片”背后的技术难题》

《手机端IM实践:iOS版微信小视频功能技术方案实录》

《手机端IM实践:Android版微信如何大幅提升交互性能(一)》

《手机端IM实践:Android版微信如何大幅提升交互性能(二)》

《手机端IM实践:实现Android版微信的智能心跳机制》

《手机端IM实践:WhatsApp、Line、微信的心跳策略分析》

《手机端IM实践:谷歌消息推送服务(GCM)研究(来自微信)》

《手机端IM实践:iOS版微信的多设施字体适配方案讨论》

《信鸽团队原创:一起走过 iOS10 上消息推送(APNS)的坑》

《腾讯信鸽技术分享:百亿级实时消息推送的实战经验》

《IPv6技术详解:基本概念、应用现状、技术实践(上篇)》

《IPv6技术详解:基本概念、应用现状、技术实践(下篇)》

《腾讯TEG团队原创:基于MySQL的分布式数据库TDSQL十年锻造经验分享》

《微信多媒体团队访谈:音视频开发的学习、微信的音视频技术和挑战等》

《理解iOS消息推送一文就够:史上最全iOS Push技术详解》

《腾讯技术分享:微信小程序音视频技术背后的故事》

《腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面》

《微信多媒体团队梁俊斌访谈:聊一聊我所理解的音视频技术》

《腾讯音视频试验室:使用AI黑科技实现超低码率的高清实时视频聊天》

《腾讯技术分享:微信小程序音视频与WebRTC互通的技术思路和实践》

《手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)》

《微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)》

《微信技术分享:微信的海量IM聊天消息序列号生成实践(容灾方案篇)》

《腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践》

《微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅》

《社交软件红包技术解密(一):全面解密QQ红包技术方案——架构、技术实现等》

《社交软件红包技术解密(二):解密微信摇一摇红包从0到1的技术演进》

《社交软件红包技术解密(三):微信摇一摇红包雨背后的技术细节》

《社交软件红包技术解密(四):微信红包系统是如何应对高并发的》

《社交软件红包技术解密(五):微信红包系统是如何实现高可用性的》

《社交软件红包技术解密(六):微信红包系统的存储层架构演进实践》

《社交软件红包技术解密(九):谈谈手Q红包的功能逻辑、容灾、运维、架构等》

《QQ设计团队分享:新版 QQ 8.0 语音消息改版背后的功能设计思路》

《微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结》

>>?更多同类文章 ……

(本文同步发布于:http://www.52im.net/thread-2873-1-1.html)

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结

发表回复