精华内容
下载资源
问答
  • 多目标优化

    万次阅读 多人点赞 2018-09-14 11:40:57
    优化问题的分类 1)无约束和有约束条件;...使多个目标给定区域同时尽可能最佳,多目标优化的解通常是一组均衡解(即一组由众多 Pareto最优解组成的最优解集合 ,集合中的各个元素称为 Pareto最优解或非劣最...

    最优化问题的分类
    1)无约束和有约束条件;
    2)确定性和随机性最优问题(变量是否确定);
    3)线性优化与非线性优化(目标函数和约束条件是否线性);
    4)静态规划和动态规划(解是否随时间变化)。


    1. 什么是多目标优化?

    使多个目标在给定区域同时尽可能最佳,多目标优化的解通常是一组均衡解(即一组由众多 Pareto最优解组成的最优解集合 ,集合中的各个元素称为 Pareto最优解或非劣最优解)。

    非劣解——多目标优化问题并不存在一个最优解,所有可能的解都称为非劣解,也称为Pareto解。
    Pareto最优解——无法在改进任何目标函数的同时不削弱至少一个其他目标函数。这种解称作非支配解或Pareto最优解。

    • 多目标优化问题的描述

    这里写图片描述

    • Pareto支配关系:

    这里写图片描述


    2. 如何实现多目标优化?有哪些方法?

    多目标优化问题不存在唯一的全局最优解 ,过多的非劣解是无法直接应用的 ,所以在求解时就是要寻找一个最终解

    (1)求最终解主要有三类方法:

    一是求非劣解的生成法,即先求出大量的非劣解,构成非劣解的一个子集,然后按照决策者的意图找出最终解;(生成法主要有加权法﹑约束法﹑加权法和约束法结合的混合法以及多目标遗传算法

    二为交互法,不先求出很多的非劣解,而是通过分析者与决策者对话的方式,逐步求出最终解;

    三是事先要求决策者提供目标之间的相对重要程度,算法以此为依据,将多目标问题转化为单目标问题进行求解

    (2)多目标优化算法归结起来有传统优化算法和智能优化算法两大类。

    传统优化算法包括加权法、约束法和线性规划法等,实质上就是将多目标函数转化为单目标函数,通过采用单目标优化的方法达到对多目标函数的求解。

    线性加权求和法——对多目标优化问题中的N个目标按其重要程度赋以适当的权系数,其乘积和作新的目标函数,再求最优解。

    智能优化算法包括进化算法(Evolutionary Algorithm, 简称EA)、粒子群算法(Particle Swarm Optimization, PSO)等。

    两者的区别——传统优化技术一般每次能得到Pareo解集中的一个,而用智能算法来求解,可以得到更多的Pareto解,这些解构成了一个最优解集,称为Pareto最优解(任一个目标函数值的提高都必须以牺牲其他目标函数值为代价的解集)。


    3. 多目标进化算法 (MOEA )

    ①MOEA通过对种群 X ( t)执行选择、交叉和变异等操作产生下一代种群 X ( t + 1) ;
    ②在每一代进化过程中 ,首先将种群 X ( t)中的所有非劣解个体都复制到外部集 A ( t)中;
    ③然后运用小生境截断算子剔除A ( t)中的劣解和一些距离较近的非劣解个体 ,以得到个体分布更为均匀的下一代外部集 A ( t + 1) ;
    ④并且按照概率 pe从 A ( t + 1)中选择一定数量的优秀个体进入下代种群;
    ⑤在进化结束时 ,将外部集中的非劣解个体作为最优解输出。

    3.1 NSGA(非支配排序遗传算法)


    这里写图片描述

    小生境技术——将每一代个体划分为若干类,每个类中选出若干适应度较大的个体作为一个类的优秀代表组成一个群,再在种群中,以及不同种群中之间,杂交,变异产生新一代个体群。同时采用预选择机制和排挤机制或分享机制完成任务。
    基于共享机制的小生境实现方法——通过反映个体之间的相似程度的共享函数来调节群体中各个个体的适应度,从而在这以后的群体进化过程中,算法能够依据这个调整后的新适应度来进行选择运算,以维持群体的多样性,创造出小生境的进化环境。
    共享函数——表示群体中两个个体之间密切关系程度的一个函数

    共享度是某个个体在群体中共享程度的一中度量,它定义为该个体与群体内其它各个个体之间的共享函数值之和,用S 表示:
    S = (i=1,… ,M)
    在计算出了群体中各个个体的共享度之后,依据下式来调整各个个体的适应度
    F(X) =F(X) / S (i=1,… ,M)

    小生境算法的描述如下:
    (1)设置进化代数计数器;随机生成M个初始群体P(t),并求出各个个体的适应度F (i=1,2,M)。
    (2)依据各个个体的适应度对其进行降序排列,记忆前N个个体(N小于M)。
    (3)选择算法。对群体P(t)进行比例选择运算,得到P (t)。
    (4)交叉选择。对选择的个体集合P (t) 作单点交叉运算,得到P (t)。
    (5)变异运算。对P (t)作均匀变异运算,得到P (t)。
    (6)小生境淘汰运算。将第(5)步得到的M个个体和第(2)步所记忆的N个个体合并在一起,得到一个含有M+N 个个体的新群体;对着M+N个个体,按照下式得到两个个体x 和x 之间的海明距离:|| x - x ||= d,当|| x - x ||小于L时,比较个体x 和个体x 的适应度大小,并对其中适应度较低的个体处以罚函数: Fmin(x,x )=Penalty。
    (7)依据这M+N个个体的新适应度对各个个体进行降序排列,记忆前N个个体。
    (8)终止条件判断。若不满足终止条件,则:更新进化代数记忆器t = t+1, 并将第(7)步排列中的前M个个体作为新的下一代群体P(t),然后转到第(3)步:若满足终止条件,则:输出计算结果,算法结束。

    NSGA使用了非支配分层方法和适应度共享策略。非支配分层方法可以使好的个体有更大的机会遗传到下一代;适应度共享策略则使得准Pareto面上的个体均匀分布,保持了群体多样性,克服了超级个体的过度繁殖,防止了早熟收敛。

    NSGA与简单的遗传算法的主要区别在于:该算法在选择算子执行之前根据个体之间的支配关系进行了分层。其选择算子、交叉算子和变异算子与简单遗传算法没有区别。

    3.2 NSGAII(带精英策略的非支配排序的遗传算法)


    这里写图片描述

    NSGA一II算法的基本思想:
    (1)首先,随机产生规模为N的初始种群,非支配排序后通过遗传算法的选择、交叉、变异三个基本操作得到第一代子代种群;
    (2)其次,从第二代开始,将父代种群与子代种群合并,进行快速非支配排序,同时对每个非支配层中的个体进行拥挤度计算,根据非支配关系以及个体的拥挤度选取合适的个体组成新的父代种群;
    (3)最后,通过遗传算法的基本操作产生新的子代种群:依此类推,直到满足程序结束的条件。

    非支配排序算法
    考虑一个目标函数个数为K(K>1)、规模大小为N的种群,通过非支配排序算法可以对该种群进行分层,具体的步骤如下:
    这里写图片描述

    通过上述步骤得到的非支配个体集是种群的第一级非支配层;

    然后,忽略这些标记的非支配个体,再遵循步骤(1)一(4),就会得到第二级非支配层;

    依此类推,直到整个种群被分类。

    快速非支配排序算法:
    这里写图片描述

    拥挤度——指种群中给定个体的周围个体的密度,直观上可表示为个体。

    拥挤度比较算子:
    这里写图片描述

    3.3 多目标粒子群算法( PSO )


    设想这么一个场景:一群鸟进行觅食,而远处有一片玉米地,所有的鸟都不知道玉米地到底在哪里,但是它们知道自己当前的位置距离玉米地有多远。那么找到玉米地的最佳策略,也是最简单有效的策略就是是搜寻目前距离玉米地最近的鸟群的周围区域。

    基本粒子群算法:
    粒子群由 n个粒子组成 ,每个粒子的位置 xi 代表优化问题在 D维搜索空间中潜在的解;
    粒子在搜索空间中以一定的速度飞行 , 这个速度根据它本身的飞行经验和同伴的飞行经验来动态调整下一步飞行方向和距离;
    所有的粒子都有一个被目标函数决定的适应值(可以将其理解为距离“玉米地”的距离) , 并且知道自己到目前为止发现的最好位置 (个体极值 pi )和当前的位置 ( xi ) 。

    粒子群算法的数学描述 :
    每个粒子 i包含为一个 D维的位置向量 xi = ( xi1, xi2, …, xiD )和速度向量 vi = ( vi1, vi2,…, viD ) ,粒子 i搜索解空间时 ,保存其搜索到的最优经历位置pi = ( pi1, pi2, …, piD ) 。在每次迭代开始时 ,粒子根据自身惯性和经验及群体最优经历位置 pg = ( pg1, pg2, …, pgD )来调整自己的速度向量以调整自身位置。

    粒子群算法基本思想:
    (1)初始化种群后 ,种群的大小记为 N。基于适应度支配的思想 ,将种群划分成两个子群 ,一个称为非支配子集 A,另一个称为支配子集 B ,两个子集的基数分别为 n1、n2 。
    (2)外部精英集用来存放每代产生的非劣解子集 A,每次迭代过程只对 B 中的粒子进行速度和位置的更新 ;
    (3)并对更新后的 B 中的粒子基于适应度支配思想与 A中的粒子进行比较 ,若 xi ∈B , ϖ xj ∈A,使得 xi 支配 xj,则删除 xj,使 xi 加入 A 更新外部精英集 ;且精英集的规模要利用一些技术维持在一个上限范围内 ,如密度评估技术、分散度技术等。
    (4)最后 ,算法终止的准则可以是最大迭代次数 Tmax、计算精度ε或最优解的最大凝滞步数 Δt等。


    展开全文
  • 你算一下,同等的硬件投入的情况下,你的软件负载能力是别人的两倍,或者更高!这里面产生的价值就很高了,等于你没有成本再做了一套系统。老板是不是应该给你翻倍工资呢?各位大神小白,我们一起...

    @TOC学习如何优化软件系统,最大化利用硬件,节约硬件成本,老板省钱了,要求涨工资吧

    为什么要学优化

    能创造价值才能拿到回报,写程序做软件是第一步,能做出软件的时候已经月薪过万了,那如果能走系统优化,那就更了不起了。你算一下,在同等的硬件投入的情况下,你的软件负载能力是别人的两倍,或者更高!这里面产生的价值就很高了,等于你没有成本再做了一套系统。老板是不是应该给你翻倍工资呢?各位大神小白,我们一起来量化软件的性能,量化自己创造的价值,有理有据地让老板涨工资吧。

    哪里可以优化

    一个生产系统包括了服务器、服务器系统、软件的运行环境、web容器、软件本尊、数据库(大概罗列,想到啥说啥,自己补充)

    那么想一下,单位价格买回来的服务器可以优化吗?答案应该是可以的,我们可以根据自己的项目,选择不同的内存cpu,磁盘等搭配,达到最佳的组合,这样不也是节省了资源浪费吗?(我胡扯的)

    服务器系统可以优化吗?答案是可以的。比用Windows 和linux系统,他们的底层算法是不一样的,不同版本的linux性能也是不一样的。比如有资料说Windows默认支持2000个客户端连接,linux 1000个。如果我们能懂底层的原理,那么这个数据可能可以改改。当然系统还要考虑很多因素,比如稳定性。

    软件运行环境是否可以优化?比如java程序运行的jre……jvm……,有资料说不通版本的java有不通的性能,我们当然可以择优,如果能懂更多底层的原理,那么你想怎么搞都行啦。

    web容器的优化,我们经常用tomcat呀,已tomcat为例,下面会介绍我找到的tomcat优化方案。

    软件本尊的优化,这个,呵呵了,自己写的软件,心里连点逼数都没有吗?如果没有还优化个毛。

    数据库的优化,这个我也找了一些资料,一会罗列一下吧。最终结论还是要懂得软件底层原理,甚至最好知道它底层代码。

    废话说完,罗列优化方案

    以下方案在网上找到的,没有经过验证,罗列出来只是为了记住有这么回事,以后再求证。

    服务器的优化

    1.用内存数据库。
    2.增加缓存。
    3.用Rdd算法。
    4.用固态盘。
    5.优化数据库。
    6.用多内核策略。
    7.分布式部署。
    8.选用适合的io。

    Tomcat优化

    1.内存化,多设置内存。
    2.线程化(单机和集群的线程设置)。
    3.禁用dns查询,急用ajp。
    4.设置session过期。
    5.Io优化,选用恰当的io方案。
    6.Apr插件使用。(很厉害的插件)。
    7.多做几个tomcat实例。Apache+3Tomccat集群(多实例单应用部署)。

    优化sql语句

    1.把返回的时候把*号改成对应字段,联表查询的时候字段应该添加前缀减少判断,不要写没必要返回的字段。
    2.添加索引,通过索引作为查询条件,同事注意不要以任何形式改变索引字段,改变后就不再是索引,比如函数计算等。
    3.杜绝不必要的联表查询。
    4.避免语句中出现子查询作为判断条件,应该用left join等方式构成判断添加。
    5.合理使用临时表(减少对大表的查询和多联表查询,单线程使用select into比较快,但是会使用锁堵塞其他通道,多线程使用先建表再插数据的方式)。
    6.In后面的集合把出现频率高的放前面啊,尽量允许返回值重复,避免判断。
    7.让解析器先处理小表关系,减少大表的查询数量。
    8.避免数据转换。
    9.避免同一条件的同类语句多次执行,一次性插入所有字段,而不是一个个字段插入。

    Mysql优化方案

    1.用能将结果存到缓存的sql。
    2.Explain 关键字跟踪查询语句,优化语句。
    3.只需要返回一个结果的尽量用limit 1 声明,比如判断某个查询是否有结果。
    4.为经常用于搜索的字段添加索引。
    5.Join on条件两边应该数据类型应该一致。
    6.避免用*号。
    7.一定要设置自增主键,唯一主键,有外键的关系表除外,主键的数据类型应优化。
    8.优化选用数据类型,可借助系统字典工具给建议,ip地址存储等。
    9.尽量使用非空。
    10.注意不同的mysql版本的Prepared Statements,如果不支持缓存则不能用这种语句。
    11.查询某些数据不要放在缓冲区。
    12.垂直分割数据表,达到不同数据类型不同表,不同应用频率不同表。
    13.拆分需要较长时间的rud语句,使之有时间空隙让其他语句运行。
    14.选择正确的引擎,有些利于读,有些利于写。
    15.选用性能好的连接池。

    结束语

    都是笔记和废话,相信没人看得懂,只提供关键词,自己百度或者站内找,大把的资料。

    展开全文
  • iOS之性能优化·优化App的启动速度

    万次阅读 2020-11-11 04:16:35
    苹果是一家特别注重用户体验的公司,过去几年一直在优化 App 的启动时间,特别是去年的 WWDC 2019 keynote [1] 上提到,过去一年苹果开发团队对启动时间提升了 200%; 虽然说是提升了 200%,但是有些问题还是没有...

    抛砖引玉

    • 启动是 App 给用户的第一印象,启动越慢用户流失的概率就越高,良好的启动速度是用户体验不可缺少的一环。
    • 苹果是一家特别注重用户体验的公司,过去几年一直在优化 App 的启动时间,特别是去年的 WWDC 2019 keynote [1] 上提到,在过去一年苹果开发团队对启动时间提升了 200%;
    • 虽然说是提升了 200%,但是有些问题还是没有说清楚,比如:
      • 为什么优化了这么多时间?
      • 作为开发者的我们,我们还可以做哪些针对启动速度的优化?
      • 所以我们今天结合 WWDC2019 - 423 - Optimizing App Launch [2] 聊一下和启动相关的东西。

    概念引入

    一、Mach-O
    • Mach-O 是 iOS 系统不同运行时期可执行文件的文件类型统称。主要分以下三类:
      • Executable :可执行文件,是 App 中的主要二进制文件;
      • Dylib :动态库,在其他平台也叫 DSO 或者 DLL;
      • Bundle :苹果平台特有的类型,是无法被连接的 Dylib。只能在运行时通过 dlopen() 加载。
    • Mach-O 的基本结构如下图所示,分为三个部分:

    在这里插入图片描述

    • 结构分析:
      • Header: 包含了 Mach-O 文件的基本信息,如 CPU 架构,文件类型,加载指令数量等;
      • Load Commands: 是跟在 Header 后面的加载命令区,包含文件的组织架构和在虚拟内存中的布局方式,在调用的时候知道如何设置和加载二进制数据;
      • Data:包含 Load Commands 中需要的各个 Segment 的数据;
    • 绝大多数 Mach-O 文件包括以下三种 Segment:
      • __TEXT :代码段,包括头文件、代码和常量,只读不可修改。
      • __DATA :数据段,包括全局变量, 静态变量等,可读可写。
      • __LINKEDIT :如何加载程序, 包含了方法和变量的元数据(位置,偏移量),以及代码签名等信息,只读不可修改。
    二、Image
    • 指的是 Executable,Dylib 或者 Bundle 的一种。
    三、Framework
    • 有很多东西都叫做 Framework,但在本文中,Framework 指的是一个 dylib,它周围有一个特殊的目录结构来保存该 dylib 所需的文件。
    • 一般会用 Root Controller 的 viewDidApper 作为渲染的终点,但其实这时候首帧已经渲染完成一小段时间了,Apple 在 MetricsKit 里对启动终点定义是第一个CA::Transaction::commit()。
    • 什么是 CATransaction 呢?我们先来看一下渲染的大致流程:

    在这里插入图片描述

    • iOS 的渲染是在一个单独的进程 RenderServer 做的,App 会把 Render Tree 编码打包给 RenderServer,RenderServer 再调用渲染框架(Metal/OpenGL ES)来生成 bitmap,放到帧缓冲区里,硬件根据时钟信号读取帧缓冲区内容,完成屏幕刷新。CATransaction 就是把一组 UI 上的修改,合并成一个事务,通过 commit 提交。
    • 渲染可以分为四个步骤:
      • Layout(布局),源头是 Root Layer 调用[CALayer layoutSubLayers],这时候 UIViewController 的 viewDidLoad 和 LayoutSubViews 会调用,autolayout 也是在这一步生效;
      • Display(绘制),源头是 Root Layer 调用[CALayer display],如果 View 实现了 drawRect 方法,会在这个阶段调用;
      • Prepare(准备),这个过程中会完成图片的解码;
      • Commit(提交),打包 Render Tree 通过 XPC 的方式发给 Render Server。

    在这里插入图片描述

    四、虚拟内存(Virtual Memory)
    • 虚拟内存是建立在物理内存和进程之间的中间层。是一个连续的逻辑地址空间,而且逻辑地址可以没有对应的实际物理内存地址,也可以让多个逻辑地址对应到一个物理内存地址上。
    • 内存可以分为虚拟内存和物理内存,其中物理内存是实际占用的内存,虚拟内存是在物理内存之上建立的一层逻辑地址,保证内存访问安全的同时为应用提供了连续的地址空间。
    • 物理内存和虚拟内存以页为单位映射,但这个映射关系不是一一对应的:一页物理内存可能对应多页虚拟内存;一页虚拟内存也可能不占用物理内存。

    在这里插入图片描述

    • iPhone 6s 开始,物理内存的 Page 大小是 16K,6 和之前的设备都是 4K,这是 iPhone 6 相比 6s 启动速度断崖式下降的原因之一。
    五、Page Fault
    • 当进程访问一个没有对应物理地址的逻辑地址时,会发生 Page Fault。
    六、Lazy Reading
    • 某个想要读取的页没有在内存中就会触发 Page Fault,系统通过调用 mmap() 函数读取指定页,这个过程叫做 Lazy Reading。
    七、COW(Copy-On-Write)
    • 当进程需要对某一页内容进行修改时,内核会把需要修改的部分先复制一份,然后再修改,并把逻辑地址重新映射到新的物理内存去,这个过程叫做 Copy-On-Write。
    八、Dirty Page & Clean Page
    • Image 加载后,被修改过内容的 Page 叫做 Dirty Page,会包含着进程特定的信息。
    • 与之相对的叫 Clean Page,可以从磁盘重新生成。
    九、共享内存(Share RAM)
    • 当多个 Mach-O 都依赖同一个 Dylib(eg. UIKit)时,系统会让这几个 Mach-O 的调用 Dylib 的逻辑地址都指向同一块物理内存区域,从而实现内存共享。
    • Dirty Page 为进程独有,不能被共享。
    十、地址空间布局随机化(ASLR)
    • 当 Image 加载到逻辑地址空间的时候,系统会利用 ASLR 技术,使得 Image 的起始地址总是随机的,以避免黑客通过起始地址+偏移量找到函数的地址。
    • 当系统利用 ASLR 分配了随机地址后,从 0 到该地址的整个区间会被标记为不可访问,意味着不可读,不可写,不可被执行。这个区域就是 __PAGEZERO 段,它的大小在 32 位系统是 4KB+,而在 64 位系统是 4GB+
    十一、代码签名(Code Sign)
    • 代码签名可以让 iOS 系统确保要被加载的 Image 的安全性,用 Code Sign 设置签名时,每页内容都会生成一个单独的加密散列值,并存储到 __LINKEDIT 中去,系统在加载时会校验每页内容确保没有被篡改。
    十二、dyld(dynamic loader)
    • dyld 是 iOS 上的二进制加载器,用于加载 Image。有不少人认为 dyld 只负责加载应用依赖的所有动态链接库,这个理解是错误的。dyld 工作的具体流程如下:

    在这里插入图片描述

    十三、Load dylibs
    • dyld 在加载 Mach-O 之前会先解析 Header 和 Load Commands, 然后就知道了这个 Mach-O 所依赖的 dylibs,以此类推,通过递归的方式把全部需要的 dylib 都加载进来。
    • 一般来说,一个 App 所依赖的 dylib 在 100 - 400 左右,其中大多数都是系统的 dylib,因为有缓存和共享的缘故,读取速度比较高。
    十四、Fix-ups
    • 因为 ASLR 和 Code Sign 的原因,刚被加载进来的 dylib 都处于相对独立的状态,为了把它们绑定起来,需要经过一个 Fix-ups 过程。
    • Fix-ups 主要有两种类型:Rebase 和 Bind。
    十五、PIC(Position Independent Code)
    • 因为代码签名的原因,dyld 无法直接修改指令,但是为了实现在运行时可以 Fix-ups,在 code gen 时,通过动态 PIC(Position Independent Code)技术,使本来因为代码签名限制不能再修改的代码,可以被加载到间接地址上。
    • 当要调用一个方法时,会先在 __DATA 段中建立一个指针指向这个方法,再通过这个指针实现间接调用。
    十六、Rebase
    • Rebase:修复内部指针。这是因为 Mach-O 在 mmap 到虚拟内存的时候,起始地址会有一个随机的偏移量 slide,需要把内部的指针指向加上这个 slide。
    • Rebase 是针对“因为 ASLR 导致 Mach-O 在加载到内存中是一个随机的首地址”这一个问题做一个数据修正的过程。会将内部指针地址都加上一个偏移量,偏移量的计算方法如下:
       Slide = actual_address - preferred_address
    
    • 所有需要 Rebase 的指针信息已经被编码到 __LINKEDIT 里。然后就是不断重复地对 __DATA 中需要 Rebase 的指针加上这个偏移量。这个过程中可能会不断发生 Page Fault 和 COW,从而导致 I/0 的性能损耗问题,不过因为 Rebase 处理的是连续地址,所以内核会预先读取数据,减少 I/O 的消耗。
    十七、Binding
    • Binding:修复外部指针。这个比较好理解,因为像 printf 等外部函数,只有运行时才知道它的地址是什么,Binding 就是把指针指向这个地址。
    • Binding 就是对调用的外部符号进行绑定的过程。比如我们要使用到 UITableView,即符号 OBJC_CLASS$_UITableView,但这个符号又不在 Mach-O 中,需要从 UIKit.framework 中获取,因此需要通过 Binding 把这个对应关系绑定到一起。
    • 在运行时,dyld 需要找到符号名对应的实现。而这需要很多计算,包括去符号表里找。找到后就会将对应的值记录到 __DATA 的那个指针里。Binding 的计算量虽然比 Rebasing 更多,但实际需要的 I/O 操作很少,因为之前 Rebasing 已经做过了。
    • 举个例子:一个 Objective C 字符串@“1234”,编译到最后的二进制的时候是会存储在两个 section 里的:
      • __TEXT,__cstring,存储实际的字符串"1234"
      • __DATA,__cfstring,存储 Objective C 字符串的元数据,每个元数据占用 32Byte,里面有两个指针:内部指针,指向__TEXT,__cstring中字符串的位置;外部指针 isa,指向类对象的,这就是为什么可以对 Objective C 的字符串字面量发消息的原因。
    • 如下图,编译的时候,字符串 1234 在__cstring的 0x10 处,所以 DATA 段的指针指向 0x10。但是 mmap 之后有一个偏移量 slide=0x1000,这时候字符串在运行时的地址就是 0x1010,那么 DATA 段的指针指向就不对了。Rebase 的过程就是把指针从 0x10,加上 slide 变成 0x1010。运行时类对象的地址已经知道了,bind 就是把 isa 指向实际的内存地址。
      在这里插入图片描述
    十八、dyld2 & dyld3
    • 在 iOS 13 之前,所有的第三方 App 都是通过 dyld 2 来启动 App 的,主要过程如下:
      • 解析 Mach-O 的 Header 和 Load Commands,找到其依赖的库,并递归找到所有依赖的库
      • 加载 Mach-O 文件
      • 进行符号查找
      • 绑定和变基
      • 运行初始化程序
    • 上面的所有过程都发生在 App 启动时,包含了大量的计算和I/O,所以苹果开发团队为了加快启动速度,在 WWDC2017 - 413 - App Startup Time: Past, Present, and Future [4] 上正式提出了 dyld3。
    • dyld2 & dyld3 比较如下:

    在这里插入图片描述

    • dyld3 被分为了三个组件:
      • 一个进程外的 MachO 解析器

        • 预先处理了所有可能影响启动速度的 search path、@rpaths 和环境变量
        • 然后分析 Mach-O 的 Header 和依赖,并完成了所有符号查找的工作
        • 最后将这些结果创建成了一个启动闭包
        • 这是一个普通的 daemon 进程,可以使用通常的测试架构
      • 一个进程内的引擎,用来运行启动闭包

        • 这部分在进程中处理
        • 验证启动闭包的安全性,然后映射到 dylib 之中,再跳转到 main 函数
        • 不需要解析 Mach-O 的 Header 和依赖,也不需要符号查找。
      • 一个启动闭包缓存服务

        • 系统 App 的启动闭包被构建在一个 Shared Cache 中, 我们甚至不需要打开一个单独的文件
        • 对于第三方的 App,我们会在 App 安装或者升级的时候构建这个启动闭包。
        • 在 iOS、tvOS、watchOS中,这这一切都是 App 启动之前完成的。在 macOS 上,由于有 Side Load App,进程内引擎会在首次启动的时候启动一个 daemon 进程,之后就可以使用启动闭包启动了。
    • dyld 3 把很多耗时的查找、计算和 I/O 的事前都预先处理好了,这使得启动速度有了很大的提升。
    十九、mmap
    • mmap 的全称是 memory map,是一种内存映射技术,可以把文件映射到虚拟内存的地址空间里,这样就可以像直接操作内存那样来读写文件。当读取虚拟内存,其对应的文件内容在物理内存中不存在的时候,会触发一个事件:File Backed Page In,把对应的文件内容读入物理内存。
    • 启动的时候,Mach-O 就是通过 mmap 映射到虚拟内存里的(如下图)。下图中部分页被标记为 zero fill,是因为全局变量的初始值往往都是 0,那么这些 0 就没必要存储在二进制里,增加文件大小。操作系统会识别出这些页,在 Page In 之后对其置为 0,这个行为叫做 zero fill。
      在这里插入图片描述
    二十、Page In
    • 启动的路径上会触发很多次 Page In,其实也比较容易理解,因为启动的会读写二进制中的很多内容。Page In 会占去启动耗时的很大一部分,我们来看看单个 Page In 的过程:
      在这里插入图片描述
    • 分析如下:
      • MMU 找到空闲的物理内存页面;
      • 触发磁盘 IO,把数据读入物理内存;
      • 如果是 TEXT 段的页,要进行解密;
      • 对解密后的页,进行签名验证;
    • 其中解密是大头,IO 其次。为什么要解密呢?因为 iTunes Connect 会对上传 Mach-O 的 TEXT 段进行加密,防止 IPA 下载下来就直接可以看到代码。这也就是为什么逆向里会有个概念叫做“砸壳”,砸的就是这一层 TEXT 段加密。iOS 13 对这个过程进行了优化,Page In 的时候不需要解密了。
    二十一、二进制重排
    • 既然 Page In 耗时,有没有什么办法优化呢?
    • 启动具有局部性特征,即只有少部分函数在启动的时候用到,这些函数在二进制中的分布是零散的,所以 Page In 读入的数据利用率并不高。如果我们可以把启动用到的函数排列到二进制的连续区间,那么就可以减少 Page In 的次数,从而优化启动时间:
    • 以下图为例,方法 1 和方法 3 是启动的时候用到的,为了执行对应的代码,就需要两次 Page In。假如我们把方法 1 和 3 排列到一起,那么只需要一次 Page In,从而提升启动速度。
      在这里插入图片描述
    • 链接器 ld 有个参数-order_file 支持按照符号的方式排列二进制。获取启动时候用到的符号的有很多种方式,这里不做说明。

    IPA 构建

    • 既然要构建,那么必然会有一些地方去定义如何构建,对应 Xcode 中的两个配置项:
      • Build Phase:以 Target 为维度定义了构建的流程。可以在 Build Phase 中插入脚本,来做一些定制化的构建,比如 CocoaPod 的拷贝资源就是通过脚本的方式完成的。
      • Build Settings:配置编译和链接相关的参数。特别要提到的是 other link flags 和 other c flags,因为编译和链接的参数非常多,有些需要手动在这里配置。很多项目用的 CocoaPod 做的组件化,这时候编译选项在对应的.xcconfig 文件里。
    • 以单 Target 为例,来看下构建流程:
      在这里插入图片描述
    • 流程说明:
      • 源文件(.m/.c/.swift 等)是单独编译的,输出对应的目标文件(.o)
      • 目标文件和静态库/动态库一起,链接出最后的 Mach-O
      • Mach-O 会被裁剪,去掉一些不必要的信息
      • 资源文件如 storyboard,asset 也会编译,编译后加载速度会变快
      • Mach-O 和资源文件一起,打包出最后的.app
      • 对.app 签名,防篡改

    编译

    • 编译器可以分为两大部分:前端和后端,二者以 IR(中间代码)作为媒介。这样前后端分离,使得前后端可以独立的变化,互不影响。C 语言家族的前端是 clang,swift 的前端是 swiftc,二者的后端都是 llvm。
      • 前端负责预处理,词法语法分析,生成 IR;
      • 后端基于 IR 做优化,生成机器码;

    在这里插入图片描述

    • 那么如何利用编译优化启动速度呢?
      代码数量会影响启动速度,为了提升启动速度,我们可以把一些无用代码下掉。那怎么统计哪些代码没有用到呢?可以利用 LLVM 插桩来实现。LLVM 的代码优化流程是一个一个 Pass,由于 LLVM 是开源的,我们可以添加一个自定义的 Pass,在函数的头部插入一些代码,这些代码会记录这个函数被调用了,然后把统计到的数据上传分析,就可以知道哪些代码是用不到的了 。
    • Facebook 给 LLVM 提的 order_file[2]的 feature 就是实现了类似的插桩。

    链接

    • 经过编译后,我们有很多个目标文件,接着这些目标文件会和静态库,动态库一起,链接出一个 Mach-O。链接的过程并不产生新的代码,只会做一些移动和补丁。

    在这里插入图片描述

    • tbd 的全称是 text-based stub library,是因为链接的过程中只需要符号就可以了,所以 Xcode 6 开始,像 UIKit 等系统库就不提供完整的 Mach-O,而是提供一个只包含符号等信息的 tbd 文件。
    • 最开始讲解 Page In 的时候,我们提到 TEXT 段的页解密很耗时,有没有办法优化呢?可以通过 ld 的-rename_section,把 TEXT 段中的内容,比如字符串移动到其他的段(启动路径上难免会读很多字符串),从而规避这个解密的耗时。
      在这里插入图片描述

    App 启动

    一、启动定义
    • 启动有两种定义:
      • 广义:点击图标到首页数据加载完毕;
      • 狭义:点击图标到 Launch Image 完全消失第一帧;
    • 不同产品的业务形态不一样,对于抖音来说,首页的数据加载完成就是视频的第一帧播放;对其他首页是静态的 App 来说,Launch Image 消失就是首页数据加载完成。由于标准很难对齐,所以我们一般使用狭义的启动定义:即启动终点为启动图完全消失的第一帧
    • 启动最佳时间是 400ms 以内,因为启动动画时长是 400ms。
    • 这是从用户感知维度定义启动,那么代码上如何定义启动呢?Apple 在 MetricKit 中给出了官方计算方式:
      • 起点:进程创建的时间;
      • 终点:第一个CA::Transaction::commit();
    • CATransaction 是 Core Animation 提供的一种事务机制,把一组 UI 上的修改打包,一起发给 Render Server 渲染。
    二、App 启动为什么这么重要?
    • App 启动是和用户的第一个交互过程,所以要尽量缩短这个过程的时间,给用户一个良好的第一印象;
    • 启动代表了你的代码的整体性能,如果启动的性能不好,其他部分的性能可能也不会太好
      启动会占用 CPU 和内存,从而影响系统性能和电池;
    • 所以我们要好好优化启动时间。
    三、启动类型

    App 的启动类型分为三类

    • Cold Launch 也就是冷启动,即为系统里没有任何进程的缓存信息,典型的是重启手机后直接启动 App。冷启动需要满足以下几个条件:
      • 重启之后
      • App 不在内存中
      • 没有相关的进程存在
    • Warm Launch 也就是热启动,即为如果把 App 进程杀了,然后立刻重新启动,这次启动就是热启动,因为进程缓存还在。热启动需要满足以下几个条件:
      • App 刚被终止
      • App 还没完全从内存中移除
      • 没有相关的进程存在
    • Resume Launch 指的是被挂起的 App 继续的过程,大多数时候不会被定义为启动,因为此时 App 仍然活着,只不过处于 suspended 状态。需要满足以下几个条件:
      • App 被挂起
      • App 还全部都在内存中
      • 还存在相关的进程
    四、App 启动阶段
    • App 启动分为三个阶段:
      • 初始化 App 的准备工作;
      • 绘制第一帧 App 的准备工作及绘制(这里的第一帧并不是获取到数据之后的第一帧,可以是一张占位视图),这时候用户与App已经可以交互了,比如 tabbar 切换;
      • 获取到页面的所有数据之后的完整的绘制第一帧页面。
    • 在这个地方,苹果再次强调了一下,建议「用户从点击 App 图标到可以再次交互,也就是第二阶段结束」的时间最好在 400ms 以内。目前来看,大部分 App 都没有达到这个目标。
    • 下面,我们把上面三个阶段分成下面这 6 个部分,讲一下这几个阶段做了什么以及有什么可以优化的地方。

    在这里插入图片描述

    五、启动优化

    System Interface

    • 初始化 App 的准备工作,系统主要做了两个事情:Load dylibs 和 libSystem init;
    • 在 2017 年苹果介绍过 dyld3 给系统 App 带来了多少优化,今年 dyld3 正式开发给开发者使用,这意味着 iOS 系统会将热启动的运行时依赖给缓存起来,以达到减少启动时间的目的,这也就是提升 200% 的原因之一。
    • 除此之外,在 Load dylibs 阶段,开发者还可以做以下优化:
      • 避免链接无用的 frameworks,在 Xcode 中检查一下项目中的「Linked Frameworks and Librares」部分是否有无用的链接。
      • 避免在启动时加载动态库,将项目的 Pods 以静态编译的方式打包,尤其是 Swift 项目,这地方的时间损耗是很大的。
      • 硬链接你的依赖项,这里做了缓存优化。
    • 也许有人会困惑是不是使用了 dyld3 了,我们就不需要做 Static Link 了,其实还是需要的,感兴趣的可以看一下 Static linking vs dyld3 [5] 这篇文章,里面有一个详细的数据对比。
    • libSystem init 部分,主要是加载一些优先级比较低的系统组件,这部分时间是一个固定的成本,所以我们开发人员不需要关心。

    Static Runtime Initializaiton

    • 这个阶段主要是 Objective-C 和 Swift Runtime 的初始化,会调用所有的 +load 方法,将类的信息注册到 runtime 中。
    • 在这个阶段,原则上不建议开发者做任何事情,所以为了避免一些启动时间的损耗,你可以做以下几个事情:
      • 在 framework 开发时,公开专有的初始化 API;
      • 减少在 +load 中做的事情;
      • 使用 initialize 进行懒加载初始化工作;

    UIKit Initializaiton

    • 这个阶段主要做了两个事情:
      • 实例化 UIApplication 和 UIApplicationDelegate;
      • 开始事件处理和系统集成。
    • 所以这个阶段的优化也比较简单,需要做两个事情:
      • 最大限度的减少 UIApplication 子类初始化时候的工作,更甚至与不子类化 UIApplication;
      • 减少 UIApplicationDelegate 的初始化工作。

    Application Initializaiton

    • 这个阶段主要是生命周期方法的回调,也正是我们开发者最熟悉的部分。
    • 调用 UIApplicationDelegate 的 App 生命周期方法:
    	application:willFinishLaunchingWithOptions: 
        application:didFinishLaunchingWithOptions:
    
    • UIApplicationDelegate 的 UI 生命周期方法:
    	applicationDidBecomeActive:
    
    • 同时,iOS 13 针对 UISceneDelegate 增加了新的回调:
    	scene:willConnectToSession:options:
        sceneWillEnterForeground:
        sceneDidBecomeActive:
    
    • 也会在这个阶段调用。感兴趣的可以关注一下 Getting the Most out of Multitasking 这个 Session,暂时没有视频资源,怀疑是现场演示翻车了,所以没有把视频资源放出来。
    • 在这个阶段,我们可以做的优化:
      • 推迟和启动时无关的工作
      • Senens 之间共享资源

    Fisrt Frame Render

    • 这个阶段主要做了创建、布局和绘制视图的工作,并把准备好的第一帧提交给渲染层渲染。会频繁调用以下几个函数:
    	loadView
        viewDidLoad 
        layoutSubviews
    
    • 在这个阶段,开发者可以做的优化:
      • 减少视图层级,懒加载一些不需要的视图;
      • 优化布局,减少约束。
    • 更多细节可以从 WWDC2018 - 220 - High Performance Auto Layout [6] 中了解。

    Extend

    • 大部分 App 都会通过异步的方式获取数据,并最终呈现给用户。我们把这一部分称为 Extend。
    • 因为这一部分每个 App 的表现都不一样,所以苹果建议开发者使用 os_signpost 进行测量然后慢慢分析慢慢优化。

    load 举例

    • 如果+load 方法里的内容很简单,会影响启动时间么?比如这样的一个+load 方法?
    	+ (void)load { 
    		printf("1234"); 
    	}
    
    • 编译完了之后,这个函数会在二进制中的 TEXT 两个段存在:__text存函数二进制,cstring存储字符串 1234。为了执行函数,首先要访问__text触发一次 Page In 读入物理内存,为了打印字符串,要访问__cstring,还会触发一次 Page In。
    • 为了执行这个简单的函数,系统要额外付出两次 Page In 的代价,所以 load 函数多了,page in 会成为启动性能的瓶颈。
      在这里插入图片描述
    • static initializer 产生的条件:静态初始化是从哪来的呢?以下几种代码会导致静态初始化
      • attribute((constructor))
      • static class object
      • static object in global namespace
    • 注意,并不是所有的 static 变量都会产生静态初始化,编译器很智能,对于在编译期间就能确定的变量是会直接 inline。
    	// 会产生静态初始化
    	class Demo{ 
    	static const std::string var_1; 
    	};
    	const std::string var_2 = "1234"; 
    	static Logger logger;
    	// 不会产生静态初始化
    	static const int var_3 = 4; 
    	static const char * var_4 = "1234";
    
    • std::string 会合成 static initializer 是因为初始化的时候必须执行构造函数,这时候编译器就不知道怎么做了,只能延迟到运行时。
    • +load 和 static initializer 执行完毕之后,dyld 会把启动流程交给 App,开始执行 main 函数。main 函数里要做的最重要的事情就是初始化 UIKit。UIKit 主要会做两个大的初始化:
      • 初始化 UIApplication;
      • 启动主线程的 Runloop;
    • 由于主线程的 dispatch_async 是基于 runloop 的,所以在+load 里如果调用了 dispatch_async 会在这个阶段执行。
    • 线程在执行完代码就会退出,很明显主线程是不能退出的,那么就需要一种机制:事件来的时候执行任务,否则让线程休眠,Runloop 就是实现这个功能的。
    • Runloop 本质上是一个While 循环,在图中橙色部分的 mach_msg_trap 就是触发一个系统调用,让线程休眠,等待事件到来,唤醒 Runloop,继续执行这个 while循环。
    • Runloop 主要处理几种任务:Source0,Source1,Timer,GCD MainQueue,Block。在循环的合适时机,会以 Observer 的方式通知外部执行到了哪里。
      在这里插入图片描述
    • 那么,Runloop 与启动又有什么关系呢?
      • App 的 LifeCycle 方法是基于 Runloop 的 Source0 的;
      • 首帧渲染是基于 Runloop Block 的。
        在这里插入图片描述
    • Runloop 在启动上主要有几点应用:
      • 精准统计启动时间;
      • 找到一个时机,在启动结束去执行一些预热任务;
      • 利用 Runloop 打散耗时的启动预热任务。

    测量 App 启动时间

    • 要找到启动过程中的问题,就要进行多次测量并前后比较。但是如果变量没有控制好,就会导致误差。
    • 所以为了保证测量的数据能够真实的反应问题,我们要减少不稳定性因素,保证在可控的相近的环境下进行测量,最后使用一致的结果来分析。
    • ① 条件一致性
      • 为了保证环境一致,我们可以做下面这几个事情:
        • 重启手机,并等待 2-3 分钟
        • 启用飞行模式或者使用模拟网络
        • 不使用或者不变更 iCloud 的账户
        • 使用 release 模式进行 build
        • 测量热启动时间
        • iColud 账户切换会影响性能,所以不要切换账号或者不开启 iCloud。
    • ② 测量注意点
      • 尽可能的使用具有代表性的数据进行测试;
      • 如果不使用具有代表性的数据进行测试,就会出现偏差;
      • 使用不同的新旧设备进行测试;
      • 最后你还可以使用 XCTest 来测试,多运行几次,取平均结果。
    • ③ 关于使用 XCTest 测试启动时间的信息,可以看一下 WWDC2019 - 417 - Improving Battery Life and Performance [7],但是我测试了一下,目前好像还有一部分 API 还没有开放出来,暂时还不能使用。

    使用 Instruments 分析和优化 App 启动过程

    一、Minimize Work
    • 推迟与第一帧无关的工作
    • 从主线程移开阻塞工作
    • 减少内存使用量
    二、Prioritize Work
    • 定义好任务的优先级
    • 利用好 GCD 来优化你的启动速度
    • 让重要的事情保持优先
    三、Optimize Work
    • 简化现有工作,比如只请求必要的数据
    • 优化算法和数据结构
    • 缓存资源和计算
    四、使用 Instruments 分析 App 启动过程
    • 当知道如何优化之后,我们需要针对我们的启动过程进行分析。Xcode 11 的 Instruments 为此新增了一个 App launch 模板,让开发者可以更好的分析自己 App 的启动速度。

    在这里插入图片描述

    • 运行后可以看到各个阶段的具体时间,根据数据进行优化,还能看到耗时的函数调用。

    系统优化

    • 苹果做了很多优化,下面这几个高亮的是和启动速度有关的优化:

    在这里插入图片描述

    • 但是不知道是不是时间原因,在 session 中对于这部分的解释特别少,很难理解 200% 到底做了什么。
    • 但是 Craig Federighi 在 The Talk Show Live From WWDC 2019, With Craig Federighi and Greg Joswiak[9] 中针对为什么优化了 200% 说了这样一段话:

    Isn’t that crazy that was quite a discovery for us. No it turns out that over times as in terms of the way the apps were encrypted and the way fair play worked and so forth. The encryption became part of the critical path actually of launching the apps. I mean the processors are capable or up and through the thing that actually it was a problem. And then there are other optimizations that based on what was visible to system at certain things. And so it actually cut out optimization opportunities and so when we really identified that opportunity we said okay. We can actually come up with better format that’s gonna eliminate that being on the critical path, It’s going to enable all these pre-binding things. And then we did a whole bunch of other work to optimize the objective-c runtime to optimize the linker the dynamic linker a bunch of other things and you put it all together. And yeah that I mean a cold launch this is we’ve never had a win like this to launch time in a single release.

    • 从这段话中,除了 dyld3 的功劳之外,减少对代码签名加密也是优化之一。

    监控线上用户 App 的启动

    • Xcode 11 在 Xcode Organizer 新增了一个监控面板,在这个面板里面可以查看多个维度的用户数据,其中还包括平均启动时间。
    • 当你通过 Instruments 分析完你的启动过程,并做了大量优化之后,你就可以通过 Xcode Organizer 来分析你这次优化效果到底怎么样。
    • 当然你可以通过去年新出的 MetricKit [10] 获取一些自定义的数据,具体参照 WWDC2019 - 417 -Improving Battery Life and Performance [11]

    参考资料

    展开全文
  • 开发优化--老板优化

    千次阅读 2016-03-17 16:59:44
     而且 你发现开发了很多,别人用了下后,就哪里冰箱就放进哪里去! 而且 经常是上午提要求,下午就要!!整天开发,而且加班地开发,周日也开发, 结果人家都不用. 无视你的劳动成果!! 战略优化 : 优化

    优化需要时间 否则就是无米之炊!

    作为开发人员 追求的是 速度,以最快的速度把需求给实现,什么质量,什么性能 统统是狗屁! 

    因为来自业务的压力,老板的压力,市场的压力,开发项目经理的GDP业绩压力. 

    而且 你发现开发了很多,别人用了下后,就哪里冰箱就放进哪里去! 

    而且 经常是上午提要求,下午就要!!

    整天在开发,而且加班地开发,周日也开发, 结果人家都不用. 无视你的劳动成果!! 


    战略优化 : 优化老板的大脑

    老板都是市场久经考验的成功人士! 喜欢最求快,快速抢占市场. 希望今天上午提出的想法,下午就能看到成品!!

    仿佛软件开发是 孙悟空样!!

    应该给老板大脑里植入 制造的概念. 告诉他 软件制造 跟 工厂里制造都需要个时间, 不能无限压缩时间. 并且告诉他要压缩时间 出来的产品只是半调子的,就是能看而已.

    当然 为了抢市场,整天加班,周日加班 是必须的!  

    后期 或者 二期开发 必须需要一个很长的时间来开发,解决各种坑,设计不足,质量不足,性能不足等各种问题. 出个质量过硬 性能高超,用户友好很亲的产品.

    展开全文
  • 本场 Chat 首先会带领大家畅聊 MySQL 性能优化之查询优化,了解 MySQL 之查询优化有那些,并且后期运用项目中。本场 Chat 您将学到如下内容: 了解查询优化器模块; 了解查询优化的基本思路; 了解查询的基本原则...
  • 优化

    千次阅读 2016-08-30 21:43:33
    直接找到公式的全局最优解是一个非常困难的任务,不过,这种凸优化问题当中,我们能够很多场合之下有效的找到全局最优解。 凸优化哪里好了,因为凸优化局部最优解就是全局最优解而且凸优化理论有个强大的工具...
  • 内存优化

    2018-04-12 17:37:24
    内存优化属于性能优化的一部分,但却还有一些自身的切入点问题 ...2.内存消耗的大小因不同设备中而不同 3.程序不能直接控制 4.支持后台多任务处理 OOM与内存泄漏的区别 新手很容易混淆概念,往...
  • Android-性能优化-内存优化

    千次阅读 2017-09-22 11:16:56
    Android-性能优化-内存优化 概述 JVM 内存分配机制 ...Dalvik 虚拟机(DVM)是 Android 系统 java虚拟机(JVM)基础上优化得到的,DVM 是基于寄存器的,而 JVM 是基于栈的,由于寄存器高效快速的特性,...
  • -- 优化专题: 整理一系列的专题:比如APK瘦身、插件化、程序架构、性能优化、自定义view、增量升级、移动开发各种技术解决方案等。 Android后期发展的五大趋势:一、性能优化;二、高级UI;三、JNI/NDK开发;...
  • Android性能优化系列之内存优化

    万次阅读 2017-01-21 21:00:45
    Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的,程序员不需要通过调用函数来释放内存,但也随之带来了内存泄漏的可能,上篇博客,我介绍了 Android性能优化系列之...
  • Android性能优化系列之电量优化

    万次阅读 2017-07-07 01:03:24
    电量消耗的计算与统计是一件麻烦而且矛盾的事情,记录电量消耗本身也是一个费电量的事情,随着Android开的性能要求越来越高,电量的优化,也显得格外重要,一个耗电的应用,用户肯定会毫不犹豫的进行卸载,所以本篇...
  • Android 性能优化 UI优化

    千次阅读 2016-11-15 23:52:14
    前言:本篇文章主要学习UI性能优化。1. 应用UI卡顿的原理1.1 原理用户感觉到卡顿的原理就是渲染时出现了掉帧。Android系统要求 1s内渲染60帧,即渲染1帧必须要16ms完成。如果你的界面没有16ms内准备好一帧,...
  • 与没有进行优化的普通网站相比,做过SEO优化的网站的优越性主要表现以下几方面。  1. 搜索引擎友好度高 经过优化的网站,对搜索引擎的友好度,明显要比普通网站高。  2. 页面的布局良好 对网站的页面布局...
  • 优化和非凸优化

    万次阅读 多人点赞 2017-02-08 14:14:18
    优化和非凸优化 2014-09-15 09:31 14094人阅读 评论(2) 收藏 举报  分类: 机器学习(37)  数学中最优化问题的一般表述是求取,使,其中是n维向量,是的可行域,是上的实值函数。 凸优化问题是指是...
  • 优化的场景分为单纯场景与复杂场景,不同场景有不同场景的优化工具与手段,我们在优化sql语句时应该先判断属于哪一种场景,根据场景选择优化途径,不要盲目地去优化sql语句,否则得不偿失。 1.单纯场景。 例如一条...
  • 单表优化、两表优化、三表优化 单表优化数据准备 create table book ( bid int(4) primary key, name varchar(20) not null, authorid int(4) not null, publicid int(4) not null, typeid int(4) not null )...
  • 2019年,BATJ等大厂继续优化。 良心企业,滴滴,给了不少补偿N+1个月。 黑心企业,xx,毁应届生offer、裁员还想不给补偿、绩效打C之类的逼人走,诸如此类。 虽然雷哥没有经历过被动裁员,从来都是主动跳槽,但...
  • Android性能优化—布局优化技巧

    千次阅读 2017-03-21 19:12:08
    安卓 布局优化 提高性能
  • 优化理论与凸优化到底是干嘛的?

    万次阅读 多人点赞 2017-12-15 20:47:53
    优化的定义 1.1 凸优化 ...1.1 凸优化优化问题目前机器学习,数据挖掘等领域应用非常广泛,因为机器学习简单来说,主要做的就是优化问题,先初始化一下权重参数,然后利用优化方法来优化这个
  • SEO优化工作无非就是就搜索引擎优化工作,说起来容易说起来难的,不过没有优化的网站一定没有排名这是事实。所以说,SEO网站优化它是企业网站上线后都会着手做的一项必不可少的重要工作,否则网站就回沦为僵尸站,...
  • CodeWarrior中用MemoryBanker优化代码

    千次阅读 2017-09-30 11:28:40
    CodeWarrior HC12 编译器和链接器支持对代码、数据和常量section进行自动...当激活这个优化时,链接器会尝试使用最优化的方式来不同的内存区域间分配对象。 这篇文章描述了CodeWarrior中MemoryBanker的作用和用法。
  • 数据库优化

    千次阅读 2018-07-06 18:01:35
    出处:https://www.cnblogs.com/easypass/archive/2010/12/08/1900127.html1.数据库访问优化法则要正确的优化SQL,我们需要快速定位能性的瓶颈点,也就是说快速找到我们SQL主要的开销在哪里?而大多数情况性能最慢的...
  • Cpu优化大全 之 代码优化

    千次阅读 2017-02-28 10:37:33
    玩家眼里这是游戏优化的不够好,太耗电。主要原因是CPU运算量大。这篇文章从两个方面介绍如何提高运算效率。其中“使用技巧”主要介绍Unity研发中一些使用不当的方式,以及如何修正。“算法优化”项算是抛砖引玉...
  • 网站关键字设定(1) 核心关键字举例如果想把“http://www.pillarseo.cn 关键字:网站优化优化到第一页怎么办?我觉得还是把时间节省出来。因为很多热门关键字已经被一些权威站点或者百度竞价垄断。不过我可以选择...
  • Python代码优化优化策略

    千次阅读 2015-02-16 22:42:48
    本文介绍了Python代码优化策略,相关原则和方法同样适用于其它编程语言编写的应用程序。
  • c++优化

    千次阅读 2010-06-01 14:41:00
    我只是想把一些可以简单的应用到你的C++代码中的优化技术总结这里,这样,当你遇到几种不同的编程策略的时候,就可以对每种策略的性能进行一个大概的估计。这也是本文的目的之所在。 <br />目录: 一. ...
  • 数据库SQL优化大总结之 百万级数据库优化方案

    万次阅读 多人点赞 2016-06-23 09:43:50
    网上关于SQL优化的教程很多,但是比较杂乱。近日有空整理了一下,写出来跟大家分享一下,其中有错误...1.对查询进行优化,要尽量避免全表扫描,首先应考虑 where 及 order by 涉及的列上建立索引。 2.应尽量避免 w
  • Linux性能优化-内存性能优化思路

    千次阅读 2019-01-07 08:27:48
    内存优化思路

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 201,411
精华内容 80,564
关键字:

优化在哪里