精华内容
下载资源
问答
  • 【Unity优化】关于优化方面的整理

    千次阅读 2016-07-08 18:22:56
    建议在 OC 之前先确定自己的场景是否适合利用 OC 来优化; Texture Packing ,或者叫 Texture Atlasing , 是将同种 shader 的纹理进行拼合,根据 Unity 的 static batching 的特性来减少 draw call 。 建议...

    0.如果你做了一个图集是1024X1024的。此时你的界面上只用了图集中的一张很小的图,那么很抱歉1024X1024这张大图都需要载入你的内存里面,1024就是4M的内存,如果你做了101024的图集,你的界面上刚好都只用了每个图集里面的一张小图,那么再次抱歉你的内存直接飙40M。意思是任何一个4096的图片,不管是图集还是texture,他都占用4*4=16M

    1、顶点性能     
    一般来说,如果您想在iPhone 3GS或更新的设备上每帧渲染不超过40,000可见点,
    那么对于一些配备 MBX GPU的旧设备(比如,原始的 iPhone,如 iPhone 3g和 iPod Touch第1和第2代)来说,你应该保证每帧的渲染顶点在10000以下。
    2、光照性能     
    像素的动态光照将对每个受影响的像素增加显著的计算开销,并可能导致物体会被渲染多次。
    为了避免这种情况的发生,您应该避免对于任何单个物体都使用多个像素光照,并尽可能地使用方向光。
    需要注意的是像素光源是一个渲染模式(Render Mode)设置为重要(Important)的光源。
    像素的动态光照将对顶点变换增加显著的开销。所以,应该尽量避免任何给定的物体被多个光源同时照亮的情况。
    对于静态物体,采用烘焙光照方法则是更为有效的方法。
    3、角色     
    每个角色尽量使用一个Skinned Mesh Renderer,这是因为当角色仅有一个 Skinned Mesh Renderer 时,
    Unity 会使用可见性裁剪和包围体更新的方法来优化角色的运动,而这种优化只有在角色仅含有一个 Skinned Mesh Renderer时才会启动。
    角色的面数一般不要超过1500,骨骼数量少于30就好,角色Material数量一般1~2个为最佳。
    4、静态物体     
    对于静态物体定点数要求少于500,UV的取值范围不要超过(0,1)区间,这对于纹理的拼合优化很有帮助。
    不要在静态物体上附加Animation组件,虽然加了对结果没什么影响,但是会增加CPU开销。
    5、摄像机     
    将远平面设置成合适的距离,远平面过大会将一些不必要的物体加入渲染,降低效率。
    另外我们可以根据不同的物体来设置摄像机的远裁剪平面。Unity 提供了可以根据不同的 layer 来设置不同的 view distance ,
    所以我们可以实现将物体进行分层,大物体层设置的可视距离大些,而小物体层可以设置地小些,
    另外,一些开销比较大的实体(如粒子系统)可以设置得更小些等等。
    6、DrawCall      
    尽可能地减少 Drawcall 的数量。 IOS 设备上建议不超过 100 。
    减少的方法主要有如下几种: Frustum Culling ,Occlusion Culling , Texture Packing 。 Frustum Culling 是 Unity 内建的,我们需要做的就是寻求一个合适的远裁剪平面;
    Occlusion Culling ,遮挡剔除, Unity 内嵌了 Umbra ,一个非常好 OC 库。
    但 Occlusion Culling 也并不是放之四海而皆准的,有时候进行 OC 反而比不进行还要慢,
    建议在 OC 之前先确定自己的场景是否适合利用 OC 来优化; Texture Packing ,或者叫 Texture Atlasing ,
    是将同种 shader 的纹理进行拼合,根据 Unity 的 static batching 的特性来减少 draw call 。
    建议使用,但也有弊端,那就是一定要将场景中距离相近的实体纹理进行拼合,否则,拼合后很可能会增加每帧渲染所需的纹理大小,
    加大内存带宽的负担。这也就是为什么会出现“ DrawCall 降了,渲染速度也变慢了”的原因。

    7.1.粒子系统运行在iPhone上时很慢,怎么办?
    答:iPhone拥有相对较低的fillrate 。
    如果您的粒子效果覆盖大部分的屏幕,而且是multiple layers的,这样即使最简单的shader,也能让iPhone傻眼。
    我们建议把您的粒子效果baking成纹理序列图。
    然后在运行时可以使用1-2个粒子,通过动画纹理来显示它们。这种方式可以取得很好的效果,以最小的代价。 

    优化: 

    1. 更新不透明贴图的压缩格式为ETC 4bit,因为android市场的手机中的GPU有多种,
    每家的GPU支持不同的压缩格式,但他们都兼容ETC格式,

    2. 对于透明贴图,我们只能选择RGBA 16bit 或者RGBA 32bit。

    3. 减少FPS,在ProjectSetting-> Quality中的
    VSync Count 参数会影响你的FPS,EveryVBlank相当于FPS=60,EverySecondVBlank = 30;
    这两种情况都不符合游戏的FPS的话,我们需要手动调整FPS,首先关闭垂直同步这个功能,然后在代码的Awake方法里手动设置FPS(Application.targetFrameRate = 45;)
    降低FPS的好处:
    1)省电,减少手机发热的情况;
    2)能都稳定游戏FPS,减少出现卡顿的情况。

    4. 当我们设置了FPS后,再调整下Fixed timestep这个参数,
    这个参数在ProjectSetting->Time中,目的是减少物理计算的次数,来提高游戏性能。

    5. 尽量少使用Update LateUpdate FixedUpdate,这样也可以提升性能和节省电量。
    多使用事件(不是SendMessage,使用自己写的,或者C#中的事件委托)。

    6. 待机时,调整游戏的FPS为1,节省电量。

    7. 图集大小最好不要高于1024,否则游戏安装之后、低端机直接崩溃、原因是手机系统版本低于2.2、超过1000的图集无法读取、导致。
    2.2 以上没有遇见这个情况。
    注意手机的RAM 与 ROM、小于 512M的手机、直接放弃机型适配。

    VSCount 垂直同步
       unity3d中新建一个场景空的时候,帧速率(FPS总是很低),大概在60~70之间。
    一直不太明白是怎么回事,现在基本上明白了。我在这里解释一下原因,如有错误,欢迎指正。
    unity3D中当运行场景打开Profiler的时候,我们会看到VSync 这一项占了很大的比重。
    这个是什么呢,这个就是垂直同步,稍后再做解释。
    我们可以关闭VSync来提高帧速率,选择edit->project settings->Quality。



    这就关闭了VSync(垂直同步),现在在运行场景看看,帧速率是不是提高很多。

    现在来说说什么是垂直同步,要知道什么是垂直同步,必须要先明白显示器的工作原理,
    显示器上的所有图像都是一线一线的扫描上去的,无论是隔行扫描还是逐行扫描,
    显示器都有两种同步参数——水平同步和垂直同步。

    什么叫水平同步?什么叫垂直同步?
    垂直和水平是CRT中两个基本的同步信号,水平同步信号决定了CRT画出一条横越屏幕线的时间,
    垂直同步信号决定了CRT从屏幕顶部画到底部,再返回原始位置的时间,
    而恰恰是垂直同步代表着CRT显示器的刷新率水平。

    为什么关闭垂直同步信号会影响游戏中的FPS数值?
    如果我们选择等待垂直同步信号(也就是我们平时所说的垂直同步打开),
    那么在游戏中或许强劲的显卡迅速的绘制完一屏的图像,但是没有垂直同步信号的到达,
    显卡无法绘制下一屏,只有等85单位的信号到达,才可以绘制。
    这样FPS自然要受到操作系统刷新率运行值的制约。

    而如果我们选择不等待垂直同步信号(也就是我们平时所说的关闭垂直同步),那么游戏中作完一屏画面,
    显卡和显示器无需等待垂直同步信号就可以开始下一屏图像的绘制,自然可以完全发挥显卡的实力。
    但是不要忘记,正是因为垂直同步的存在,才能使得游戏进程和显示器刷新率同步,使得画面更加平滑和稳定。
    取消了垂直同步信号,固然可以换来更快的速度,但是在图像的连续性上势必打折扣。
    这也正是很多朋友抱怨关闭垂直后发现画面不连续的理论原因。

    合并材质球unity 3d中每倒入一次模型就多一个材质球,可我的这些模型都是共用一张贴图的就想共用一个材质球,所以每次都要删除再附上,很麻烦。怎么才能合并这些材质球?
    采用TexturePacking吧
    1、遍历gameobject,取出material,并根据shader来将material分类
    2、调用Unity自带的PackTextures函数来合并每个shader分类中的material所对应的textures(PackTextures函数有缺陷,不过可以将就用)
    3、根据合并的大的texture来更新原有模型的texture、material已经uv坐标值。

    需要注意的是:需要合并的纹理应该是物体在场景中距离相近的,如果物体在场景中的距离较远,
    则不建议合并纹理,因为这样做很有可能非但起不到优化的作用,反而降低了运行效率。 

    ======================分割线==================

    • 角色Material数量
    2-3
    • 骨骼数量
    小于30个
    • 面片数量
    300-1500
    • 一般角色应该没有IK结点
    这是因为角色的动作大多数都是事先设定好的,并不需要经过IK操作来进行实时计算(Rogdoll除外),所以在模型导入时,不要将IK结点一起导入。

    2、静态实体

    • 不要附加Animation Component
    在静态实体上附加Animation部件虽然对结果没有影响,但却会增加一定的CPU开销来调用这一组件,所以尽量去掉该组件。
    • 网格顶点数
    小于500
    • UV值范围尽量不要超过(0, 1)区间
    尽量保证UV值不越界,这对于将来的纹理拼合优化很有帮助。

    3、地形

    • 地形的分辨率大小
    长宽均尽量小于257。这是因为地形太大,会造成大量顶点数据,给你的内存带宽造成一定的影响,在目前的ios设备中,内存带宽是非常有限的,需要尽量节省。同时,如果用Unity自带的地形,一定也要使用Occlusion Culling,因为Unity的刷地形工具虽然方便,但却是framekiller,刷过之后,你会发现drawcall增加的非常多。
    • 混合纹理数量
    不要超过4。地形的混合操作是很耗时的,应该尽量避免。能合并的纹理尽量合并。

    4、纹理

    • 纹理格式
    建议png或tga。不用转成ios硬件支持的PVRTC格式,因为Unity在发布时会帮你自动转的。
    • 纹理尺寸
    长宽小于1024。同时应该尽可能地小,够用就好,以保证纹理对内存带宽的影响达到最小。
    • 支持Mipmap
    建议生成Mipmap。虽然这种做法会增加一些应用程序的大小,但在游戏运行时,系统会根据需求应用Mipmap来渲染,从而减少内存带宽。
    • 检查Alpha值
    如果纹理的alpha通道均为1,则用RGB的24位纹理来代替RGBA的32位纹理。(据说Unity内部会进行自动检测)

    5、光源

    • 光源“Important”个数
    建议1个,一般为方向光。“Important”个数应该越小越少。个数越多,drawcall越多。
    • Pixel Light数目
    1-2个。

    6、粒子特效

    • 屏幕上的最大粒子数
    建议小于200个粒子。
    • 每个粒子发射器发射的最大粒子数
    建议不超过50个。
    • 粒子大小
    如果可以的话,粒子的size应该尽可能地小。因为Unity的粒子系统的shader无论是alpha test还是alpha blending都是一笔不小的开销。同时,对于非常小的粒子,建议粒子纹理去掉alpha通道。
    • 尽量不要开启粒子的碰撞功能。
    非常耗时。

    7、音频

    • 游戏中播放时间较长的音乐(如背景音乐)
    使用.ogg或.mp3的压缩格式。
    • 较短音乐(如枪声)
    使用.wav和.aif的未压缩音频格式。

    8、相机

    • 裁剪平面
    将远平面设置成合适的距离。远平面过大会将一些不必要的物体加入渲染,降低效率。
    • 根据不同的物体设置不同的远裁剪平面
    Unity提供了可以根据不同的layer来设置不同的view distance,所以我们可以实现将物体进行分层,大物体层设置的可视距离大些,而小物体层可以设置地小些,另外,一些开销比较大的实体(如粒子系统)可以设置得更小些等等。

    9、碰撞

    • 尽量不用MeshCollider
    如果可以的话,尽量不用MeshCollider,以节省不必要的开销。如果不能避免的话,尽量用减少Mesh的面片数,或用较少面片的代理体来代替。

    10、其他

    • Drawcall
    尽可能地减少Drawcall的数量。IOS设备上建议不超过100。减少的方法主要有如下几种:Frustum Culling,Occlusion Culling,Texture Packing。Frustum Culling是Unity内建的,我们需要做的就是寻求一个合适的远裁剪平面;Occlusion Culling,遮挡剔除,Unity内嵌了Umbra,一个非常好OC库。但Occlusion Culling也并不是放之四海而皆准的,有时候进行OC反而比不进行还要慢,建议在OC之前先确定自己的场景是否适合利用OC来优化;Texture Packing,或者叫Texture Atlasing,是将同种shader的纹理进行拼合,根据Unity的static batching的特性来减少draw call。建议使用,但也有弊端,那就是一定要将场景中距离相近的实体纹理进行拼合,否则,拼合后很可能会增加每帧渲染所需的纹理大小,加大内存带宽的负担。这也就是为什么会出现“DrawCall降了,渲染速度也变慢了”的原因。

    • 非运动物体尽量打上Static标签
    Unity在运行时会对static物体进行自动优化处理,所以应该尽可能将非运行实体勾上static标签。

    • 场景中尽可能地使用prefab
    尽可能地使用prefab的实例化物体,以降低内存带宽的负担。检查实体的PrefabType,尽量将其变成PrefabInstance,而不是ModelPrefabInstance。
    ================分割线===============

    移动平台相对于PC机,具有体积小,计算弱,带宽少的特点。

    因此做手机游戏的开发,优化的方向,与力度对比PC游戏都有所区别。


    必须要做到优化流程,合理利用资源。

    目前在手机上面,还不能够像PC游戏那样追求高质量渲染效果,为了让手机不那么容易发烫,还要控制cpu,gpu,不能让他们全速运算。


    材质方面:

    纹理方面,建议使用压缩纹理,

    android上面使用ETC1,苹果上面使用PVRTC。


    UV坐标控制在0到1之间,人物模型面数控制在1500内,骨骼控制在30个以内。

    场景中使用一个主光(不能再多了)。


    尽量减少alphaTest和alphaBlend材质的使用。在手机上,这是很杀效率的。


    骨骼动画方面:

    在动画方面可以考虑不使用插值,固定的帧率的动画。

    如果要做插值,考虑使用四元数(表示旋转)和向量(表示位移)来做插值。

    四元数做插值速度比矩阵来的快,Slerp提供了平滑插值。

    ================分割线===============

    在美术制作场景的过程中,会使用到大量的粒子系统。
    比如场景中的火把。在我们的一个地下城场景中,美术们放置了大量的火把。整个场景中的各个地方,有100来个火把。

    unity中,在摄像机范围外的粒子系统虽然不会被绘制。
    但是update是一直持续的。这也就意味着,这100多个火把,不论是否可见都在更新。

    这个设计应该是很不合理的,在我看过的其他引擎中,都会有一个开关,来控制不可见的粒子系统是否需要update。
    有的粒子系统在不可见的时候需要更新,比如爆炸。有的不需要更新,比如火堆火把。

    为了避免不必要的update开销,尤其是最后游戏是要发布到页游平台(web player只能使用一个cpu的核)。
    于是写了一个脚本,控制不可见的粒子系统就不更新。

    该脚本主要是用到了2个MonoBehaviour的函数。
    OnBecameInvisible() 当变为不可见   和   OnBecameVisible() 当变成可见。 

    要这2个函数起作用的前提是,该GameObject绑定了MeshRender组件。
    所以,我们要在粒子系统的GameObject放置在一个GameObject  下,且给该GameObject绑定一个MeshRender 与 MeshFilter。
    MeshFilter中的mesh可以随便找个cube。

    在Start() 的时候,把最GameObject的scale设置为很小,以保证该cube不被看见。
    其实遍历所有的child,把active设置为false。

    在OnBecameVisible 中 遍历所有child,把active设置为true。
    在OnBecameInvisible中 遍历所有child,把active设置为false。




    整理资源来至 :http://www.manew.com/thread-21597-1-1.html

              http://www.manew.com/thread-90138-1-1.html

    展开全文
  • unity几种优化建议

    千次阅读 2016-10-14 16:28:20
    最简单的优化建议: 1.PC平台的话保持场景中显示的顶点数少于200K~3M,移动设备的话少于10W,一切取决于你的目标GPU与CPU。 2.如果你用U3D自带的SHADER,在表现不差的情况下选择Mobile或Unlit目录下的。它们更...

    最简单的优化建议:

    1.PC平台的话保持场景中显示的顶点数少于200K~3M,移动设备的话少于10W,一切取决于你的目标GPU与CPU。
    2.如果你用U3D自带的SHADER,在表现不差的情况下选择Mobile或Unlit目录下的。它们更高效。
    3.尽可能共用材质。
    4.将不需要移动的物体设为Static,让引擎可以进行其批处理。
    5.尽可能不用灯光。
    6.动态灯光更加不要了。
    7.尝试用压缩贴图格式,或用16位代替32位。
    8.如果不需要别用雾效(fog)
    9.尝试用OcclusionCulling,在房间过道多遮挡物体多的场景非常有用。若不当反而会增加负担。
    10.用天空盒去“褪去”远处的物体。
    11.shader中用贴图混合的方式去代替多重通道计算。
    12.shader中注意float/half/fixed的使用。
    13.shader中不要用复杂的计算pow,sin,cos,tan,log等。
    14.shader中越少Fragment越好。
    15.注意是否有多余的动画脚本,模型自动导入到U3D会有动画脚本,大量的话会严重影响消耗CPU计算。
    16.注意碰撞体的碰撞层,不必要的碰撞检测请舍去。


    1.为什么需要针对CPU(中央处理器)与GPU(图形处理器)优化?

    CPU和GPU都有各自的计算和传输瓶颈,不同的CPU或GPU他们的性能都不一样,所以你的游戏需要为你目标用户的CPU与GPU能力进行针对开发。


    2.CPU与GPU的限制

    GPU一般具有填充率(Fillrate)和内存带宽(Memory Bandwidth)的限制,如果你的游戏在低质量表现的情况下会快很多,那么,你很可能需要限制你在GPU的填充率。

    CPU一般被所需要渲染物体的个数限制,CPU给GPU发送渲染物体命令叫做DrawCalls。一般来说DrawCalls数量是需要控制的,在能表现效果的前提下越少越好。通常来说,电脑平台上DrawCalls几千个之内,移动平台上DrawCalls几百个之内。这样就差不多了。当然以上并不是绝对的,仅作一个参考。

    往往渲染(Rendering)并不是一个问题,无论是在GPU和CPU上。很可能是你的脚本代码效率的问题,用Profiler查看下。

    关于Profiler介绍:http://docs.unity3d.com/Documentation/Manual/Profiler.html

    需要注意的是:
    在GPU中显示的RenderTexture.SetActive()占用率很高,是因为你同时打开了编辑窗口的原因,而不是U3D的BUG。

    3.关于顶点数量和顶点计算

    CPU和GPU对顶点的计算处理都很多。GPU中渲染的顶点数取决于GPU性能和SHADER的复杂程度,一般来说,每帧之内,在PC上几百万顶点内,在移动平台上不超过10万顶点。

    CPU中的计算主要是在蒙皮骨骼计算,布料模拟,顶点动画,粒子模拟等。GPU则在各种顶点变换、光照、贴图混合等。

    【个人认为,具体还是看各位的项目需求,假设你项目的是3d游戏。你游戏需要兼容低配置的硬件、流畅运行、控制硬件发热的话,还要达到一定效果(LIGHTMAP+雾效),那么顶点数必定不能高。此时同屏2W顶点我认为是个比较合适的数目,DRAWCALL最好低于70。另,控制发热请控制最高上限的帧率,流畅的话,帧率其实不需要太高的。】



    4.针对CPU的优化——减少DRAW CALL 的数量

    为了渲染物体到显示器上,CPU需要做一些工作,如区分哪个东西需要渲染、区分开物体是否受光照影响、使用哪个SHADER并且为SHADER传参、发送绘图命令告诉显示驱动,然后发送命令告诉显卡删除等这些。

    假设你有一个上千三角面的模型却用上千个三角型模型来代替,在GPU上花费是差不多的,但是在CPU上则是极其不一样,消耗会大很多很多。为了让CPU更少的工作,需要减少可见物的数目:

    a.合并相近的模型,手动在模型编辑器中合并或者使用UNITY的Draw call批处理达到相同效果(Draw call batching)。具体方法和注意事项查看以下链接:

    Draw call batching : http://docs.unity3d.com/Documentation/Manual/DrawCallBatching.html


    b.在项目中使用更少的材质(material),将几个分开的贴图合成一个较大的图集等方式处理。

    如果你需要通过脚本来控制单个材质属性,需要注意改变Renderer.material将会造成一份材质的拷贝。因此,你应该使用Renderer.sharedMaterial来保证材质的共享状态。

    有一个合并模型材质不错的插件叫Mesh Baker,大家可以考虑试下。

    c.尽量少用一些渲染步骤,例如reflections,shadows,per-pixel light 等。

    d.Draw call batching的合并物体,会使每个物体(合并后的物体)至少有几百个三角面。

    假设合并的两个物体(手动合并)但不共享材质,不会有性能表现上的提升。多材质的物体相当于两个物体不用一个贴图。所以,为了提升CPU的性能,你应该确保这些物体使用同样的贴图。

    另外,用灯光将会取消(break)引擎的DRAW CALL BATCH,至于为什么,查看以下:

    Forward Rendering Path Details:
    http://docs.unity3d.com/Documentation/Components/RenderTech-ForwardRendering.html

    e.使用相关剔除数量直接减少Draw Call数量,下文有相关提及。


    5.优化几何模型

    最基本的两个优化准则:
    a.不要有不必要的三角面。
    b.UV贴图中的接缝和硬边越少越好。

    需要注意的是,图形硬件需要处理顶点数并跟硬件报告说的并不一样。不是硬件说能渲染几个点就是几个点。模型处理应用通展示的是几何顶点数量。例如,一个由一些不同顶点构成的模型。在显卡中,一些集合顶点将会被分离(split)成两个或者更多逻辑顶点用作渲染。如果有法线、UV坐标、顶点色的话,这个顶点必须会被分离。所以在游戏中处理的实际数量显然要多很多。


    6.关于光照

    若不用光肯定是最快的。移动端优化可以采用用光照贴图(Lightmapping)去烘培一个静态的贴图,以代替每次的光照计算,在U3D中只需要非常短的时间则能生成。这个方法能大大提高效率,而且有着更好的表现效果(平滑过渡处理,还有附加阴影等)。

    在移动设备上和低端电脑上尽量不要在场景中用真光,用光照贴图。这个方法大大节省了CPU和GPU的计算,CPU得到了更少的DRAWCALL,GPU则需要更少顶点处理和像素栅格化。

    Lightmapping : http://docs.unity3d.com/Documentation/Manual/Lightmapping.html


    7.对GPU的优化——图片压缩和多重纹理格式

    Compressed Textures(图片压缩):

    http://docs.unity3d.com/Documentation/Components/class-Texture2D.html

    图片压缩将降低你的图片大小(更快地加载更小的内存跨度(footprint)),而且大大提高渲染表现。压缩贴图比起未压缩的32位RGBA贴图占用内存带宽少得多。

    之前U3D会议还听说过一个优化,贴图尽量都用一个大小的格式(512 * 512 , 1024 * 1024),这样在内存之中能得到更好的排序,而不会有内存之间空隙。这个是否真假没得到过测试。

    MIPMAps(多重纹理格式):

    http://docs.unity3d.com/Documentation/Components/class-Texture2D.html

    网页上的略缩图原理一样,在3D游戏中我们为游戏的贴图生成多重纹理贴图,远处显示较小的物体用小的贴图,显示比较大的物体用精细的贴图。这样能更加有效的减少传输给GPU中的数据。


    8.LOD 、 Per-Layer Cull Distances 、 Occlusion Culling

    LOD (Level Of Detail) 是很常用的3D游戏技术了,其功能理解起来则是相当于多重纹理贴图。在以在屏幕中显示模型大小的比例来判断使用高或低层次的模型来减少对GPU的传输数据,和减少GPU所需要的顶点计算。

    摄像机分层距离剔除(Per-Layer Cull Distances):为小物体标识层次,然后根据其距离主摄像机的距离判断是否需要显示。

    遮挡剔除(Occlusion Culling)其实就是当某个物体在摄像机前被另外一个物体完全挡住的情况,挡住就不发送给GPU渲染,从而直接降低DRAW CALL。不过有些时候在CPU中计算其是否被挡住则会很耗计算,反而得不偿失。

    以下是这几个优化技术的相关使用和介绍:

    Level Of Detail :
    http://docs.unity3d.com/Documentation/Manual/LevelOfDetail.html

    Per-Layer Cull Distances :
    http://docs.unity3d.com/Documentation/ScriptReference/Camera-layerCullDistances.html

    Occlusion Culling :
    http://docs.unity3d.com/Documentation/Manual/OcclusionCulling.html


    9.关于Realtime Shadows(实时阴影)

    实时阴影技术非常棒,但消耗大量计算。为GPU和CPU都带来了昂贵的负担,细节的话参考下面:

    http://docs.unity3d.com/Documentation/Manual/Shadows.html


    10.对GPU优化:采用高效的shader

    a.需要注意的是有些(built-in)Shader是有mobile版本的,这些大大提高了顶点处理的性能。当然也会有一些限制。

    b.自己写的shader请注意复杂操作符计算,类似pow,exp,log,cos,sin,tan等都是很耗时的计算,最多只用一次在每个像素点的计算。不推荐你自己写normalize,dot,inversesqart操作符,内置的肯定比你写的好。

    c.需要警醒的是alpha test,这个非常耗时。

    d.浮点类型运算:精度越低的浮点计算越快。

    在CG/HLSL中--

    float :32位浮点格式,适合顶点变换运算,但比较慢。
    half:16位浮点格式,适合贴图和UV坐标计算,是highp类型计算的两倍。
    fixed: 10位浮点格式,适合颜色,光照,和其他。是highp格式计算的四倍。

    写Shader优化的小提示:
    http://docs.unity3d.com/Documentation/Components/SL-ShaderPerformance.html

    11.另外的相关优化:

    a.对Draw Call Batching的优化
    http://docs.unity3d.com/Documentation/Manual/DrawCallBatching.html

    b.对Rendering Statistics Window的说明和提示:
    http://docs.unity3d.com/Documentation/Manual/RenderingStatistics.html

    c.角色模型的优化建议
    用单个蒙皮渲染、尽量少用材质、少用骨骼节点、移动设备上角色多边形保持在300~1500内(当然还要看具体的需求)、PC平台上1500~4000内(当然还要看具体的需求)。

    http://docs.unity3d.com/Documentation/Manual/ModelingOptimizedCharacters.html


    优化: 

    1. 更新不透明贴图的压缩格式为ETC 4bit,因为android市场的手机中的GPU有多种,
    每家的GPU支持不同的压缩格式,但他们都兼容ETC格式,

    2. 对于透明贴图,我们只能选择RGBA 16bit 或者RGBA 32bit。

    3. 减少FPS,在ProjectSetting-> Quality中的
    VSync Count 参数会影响你的FPS,EveryVBlank相当于FPS=60,EverySecondVBlank = 30;
    这两种情况都不符合游戏的FPS的话,我们需要手动调整FPS,首先关闭垂直同步这个功能,然后在代码的Awake方法里手动设置FPS(Application.targetFrameRate = 45;)
    降低FPS的好处:
    1)省电,减少手机发热的情况;
    2)能都稳定游戏FPS,减少出现卡顿的情况。

    4. 当我们设置了FPS后,再调整下Fixed timestep这个参数,
    这个参数在ProjectSetting->Time中,目的是减少物理计算的次数,来提高游戏性能。

    5. 尽量少使用Update LateUpdate FixedUpdate,这样也可以提升性能和节省电量。
    多使用事件(不是SendMessage,使用自己写的,或者C#中的事件委托)。

    6. 待机时,调整游戏的FPS为1,节省电量。

    7. 图集大小最好不要高于1024,否则游戏安装之后、低端机直接崩溃、原因是手机系统版本低于2.2、超过1000的图集无法读取、导致。
    2.2 以上没有遇见这个情况。
    注意手机的RAM 与 ROM、小于 512M的手机、直接放弃机型适配。

    VSCount 垂直同步
       unity3d中新建一个场景空的时候,帧速率(FPS总是很低),大概在60~70之间。
    一直不太明白是怎么回事,现在基本上明白了。我在这里解释一下原因,如有错误,欢迎指正。
    在Unity3D中当运行场景打开Profiler的时候,我们会看到VSync 这一项占了很大的比重。
    这个是什么呢,这个就是垂直同步,稍后再做解释。
    我们可以关闭VSync来提高帧速率,选择edit->project settings->Quality。

     


    在右侧面板中可以找到VSync Count,把它选成Don't Sync。
     
    这就关闭了VSync(垂直同步),现在在运行场景看看,帧速率是不是提高很多。

    现在来说说什么是垂直同步,要知道什么是垂直同步,必须要先明白显示器的工作原理,
    显示器上的所有图像都是一线一线的扫描上去的,无论是隔行扫描还是逐行扫描,
    显示器都有两种同步参数——水平同步和垂直同步。

    什么叫水平同步?什么叫垂直同步?
    垂直和水平是CRT中两个基本的同步信号,水平同步信号决定了CRT画出一条横越屏幕线的时间,
    垂直同步信号决定了CRT从屏幕顶部画到底部,再返回原始位置的时间,
    而恰恰是垂直同步代表着CRT显示器的刷新率水平。

    为什么关闭垂直同步信号会影响游戏中的FPS数值?
    如果我们选择等待垂直同步信号(也就是我们平时所说的垂直同步打开),
    那么在游戏中或许强劲的显卡迅速的绘制完一屏的图像,但是没有垂直同步信号的到达,
    显卡无法绘制下一屏,只有等85单位的信号到达,才可以绘制。
    这样FPS自然要受到操作系统刷新率运行值的制约。

    而如果我们选择不等待垂直同步信号(也就是我们平时所说的关闭垂直同步),那么游戏中作完一屏画面,
    显卡和显示器无需等待垂直同步信号就可以开始下一屏图像的绘制,自然可以完全发挥显卡的实力。
    但是不要忘记,正是因为垂直同步的存在,才能使得游戏进程和显示器刷新率同步,使得画面更加平滑和稳定。
    取消了垂直同步信号,固然可以换来更快的速度,但是在图像的连续性上势必打折扣。
    这也正是很多朋友抱怨关闭垂直后发现画面不连续的理论原因。

    合并材质球unity 3d中每倒入一次模型就多一个材质球,可我的这些模型都是共用一张贴图的就想共用一个材质球,所以每次都要删除再附上,很麻烦。怎么才能合并这些材质球?
    采用TexturePacking吧
    1、遍历gameobject,取出material,并根据shader来将material分类
    2、调用Unity自带的PackTextures函数来合并每个shader分类中的material所对应的textures(PackTextures函数有缺陷,不过可以将就用)
    3、根据合并的大的texture来更新原有模型的texture、material已经uv坐标值。

    需要注意的是:需要合并的纹理应该是物体在场景中距离相近的,如果物体在场景中的距离较远,
    则不建议合并纹理,因为这样做很有可能非但起不到优化的作用,反而降低了运行效率。 

    mesh合并 
    分为2种方式合并
    1.自带的合并必须勾选静态。
     
    所有被勾选了“Static”的GameObject,其中的Mesh Filter中的mesh都会被合并到 "Combined Mesha (root: scene)" 中


    2.也可以用脚本来合并mesh 

    [C#] 纯文本查看 复制代码
    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 using UnityEngine; using System.Collections;   public class MyClass: MonoBehaviour {     void Start()     {         MeshFilter[] meshFilters = GetComponentsInChildren ();         CombineInstance[]combine = new CombineInstance[meshFilters.Length];           for (int i= 0; i < meshFilters.Length; i++) {             combine[i].mesh = meshFilters [i].sharedMesh;             combine[i].transform = meshFilters[i].transform.localToWorldMatrix;             meshFilters[i].gameObject.active = false;         }               transform.GetComponent().mesh = new Mesh();             transform.GetComponent().mesh.CombineMeshes (combine);             transform.gameObject.active= true;     } }


    1. 先在 Unity 中建立 空物件 ( Empty ) 
    2. 再创建2个 Cube 方块,并放入 空物件底下 (可以改成你自己的模型)
    3. 把 MyClass 代码丟进 空物件上 。
    4. (可选) 建立一个 Material 材质,并且丢进 空物件上
    5. 执行

     


     
    ========================================分割线====================================

    • 角色Material数量
    2-3
    • 骨骼数量
    小于30个
    • 面片数量
    300-1500
    • 一般角色应该没有IK结点
    这是因为角色的动作大多数都是事先设定好的,并不需要经过IK操作来进行实时计算(Rogdoll除外),所以在模型导入时,不要将IK结点一起导入。

     

    2、静态实体

    • 不要附加Animation Component
    在静态实体上附加Animation部件虽然对结果没有影响,但却会增加一定的CPU开销来调用这一组件,所以尽量去掉该组件。
    • 网格顶点数
    小于500
    • UV值范围尽量不要超过(0, 1)区间
    尽量保证UV值不越界,这对于将来的纹理拼合优化很有帮助。

     

    3、地形

    • 地形的分辨率大小
    长宽均尽量小于257。这是因为地形太大,会造成大量顶点数据,给你的内存带宽造成一定的影响,在目前的ios设备中,内存带宽是非常有限的,需要尽量节省。同时,如果用Unity自带的地形,一定也要使用Occlusion Culling,因为Unity的刷地形工具虽然方便,但却是framekiller,刷过之后,你会发现drawcall增加的非常多。
    • 混合纹理数量
    不要超过4。地形的混合操作是很耗时的,应该尽量避免。能合并的纹理尽量合并。

     

    4、纹理

    • 纹理格式
    建议png或tga。不用转成ios硬件支持的PVRTC格式,因为Unity在发布时会帮你自动转的。
    • 纹理尺寸
    长宽小于1024。同时应该尽可能地小,够用就好,以保证纹理对内存带宽的影响达到最小。
    • 支持Mipmap
    建议生成Mipmap。虽然这种做法会增加一些应用程序的大小,但在游戏运行时,系统会根据需求应用Mipmap来渲染,从而减少内存带宽。
    • 检查Alpha值
    如果纹理的alpha通道均为1,则用RGB的24位纹理来代替RGBA的32位纹理。(据说Unity内部会进行自动检测)

     

    5、光源

    • 光源“Important”个数
    建议1个,一般为方向光。“Important”个数应该越小越少。个数越多,drawcall越多。
    • Pixel Light数目
    1-2个。

     

    6、粒子特效

    • 屏幕上的最大粒子数
    建议小于200个粒子。
    • 每个粒子发射器发射的最大粒子数
    建议不超过50个。
    • 粒子大小
    如果可以的话,粒子的size应该尽可能地小。因为Unity的粒子系统的shader无论是alpha test还是alpha blending都是一笔不小的开销。同时,对于非常小的粒子,建议粒子纹理去掉alpha通道。
    • 尽量不要开启粒子的碰撞功能。
    非常耗时。

     

    7、音频

    • 游戏中播放时间较长的音乐(如背景音乐)
    使用.ogg或.mp3的压缩格式。
    • 较短音乐(如枪声)
    使用.wav和.aif的未压缩音频格式。

     

    8、相机

    • 裁剪平面
    将远平面设置成合适的距离。远平面过大会将一些不必要的物体加入渲染,降低效率。
    • 根据不同的物体设置不同的远裁剪平面
    Unity提供了可以根据不同的layer来设置不同的view distance,所以我们可以实现将物体进行分层,大物体层设置的可视距离大些,而小物体层可以设置地小些,另外,一些开销比较大的实体(如粒子系统)可以设置得更小些等等。

     

    9、碰撞

    • 尽量不用MeshCollider
    如果可以的话,尽量不用MeshCollider,以节省不必要的开销。如果不能避免的话,尽量用减少Mesh的面片数,或用较少面片的代理体来代替。

     

    10、其他

    • Drawcall
    尽可能地减少Drawcall的数量。IOS设备上建议不超过100。减少的方法主要有如下几种:Frustum Culling,Occlusion Culling,Texture Packing。Frustum Culling是Unity内建的,我们需要做的就是寻求一个合适的远裁剪平面;Occlusion Culling,遮挡剔除,Unity内嵌了Umbra,一个非常好OC库。但Occlusion Culling也并不是放之四海而皆准的,有时候进行OC反而比不进行还要慢,建议在OC之前先确定自己的场景是否适合利用OC来优化;Texture Packing,或者叫Texture Atlasing,是将同种shader的纹理进行拼合,根据Unity的static batching的特性来减少draw call。建议使用,但也有弊端,那就是一定要将场景中距离相近的实体纹理进行拼合,否则,拼合后很可能会增加每帧渲染所需的纹理大小,加大内存带宽的负担。这也就是为什么会出现“DrawCall降了,渲染速度也变慢了”的原因。

     

    • 非运动物体尽量打上Static标签
    Unity在运行时会对static物体进行自动优化处理,所以应该尽可能将非运行实体勾上static标签。

     

    • 场景中尽可能地使用prefab
    尽可能地使用prefab的实例化物体,以降低内存带宽的负担。检查实体的PrefabType,尽量将其变成PrefabInstance,而不是ModelPrefabInstance。



    ========================================分割线==================================== 

    移动平台相对于PC机,具有体积小,计算弱,带宽少的特点。

    因此做手机游戏的开发,优化的方向,与力度对比PC游戏都有所区别。

     

    必须要做到优化流程,合理利用资源。

    目前在手机上面,还不能够像PC游戏那样追求高质量渲染效果,为了让手机不那么容易发烫,还要控制cpu,gpu,不能让他们全速运算。

     

    材质方面:

    纹理方面,建议使用压缩纹理,

    Android上面使用ETC1,苹果上面使用PVRTC。

     

    UV坐标控制在0到1之间,人物模型面数控制在1500内,骨骼控制在30个以内。

    场景中使用一个主光(不能再多了)。

     

    尽量减少alphaTest和alphaBlend材质的使用。在手机上,这是很杀效率的。

     

    骨骼动画方面:

    在动画方面可以考虑不使用插值,固定的帧率的动画。

    如果要做插值,考虑使用四元数(表示旋转)和向量(表示位移)来做插值。

    四元数做插值速度比矩阵来的快,Slerp提供了平滑插值。



    ========================================分割线==================================== 

    优化的常规技巧
    剖析你的游戏。
    不要花费时间来优化那些晦涩的代码或者缩减图形文件的大小,除非这是你游戏的瓶颈。
    第一次剖析你的游戏将会使你发现你游戏的瓶颈。Apple's Shark是一个很好的用来剖析基于OpenGL的程序的工具。
    再次剖析你的游戏。
    优化之后不要忘记再剖析一次你的游戏,这样可以检查你所做的优化是否达到了预期的效果。
    当然,这样做也可能会使你发现更多的瓶颈。
    流程第一、性能第二。花费时间来使你游戏的创建尽可能地流畅。
    尽可能快地修正游戏中的错误将会使你后期更容易优化你的游戏。
    在Scene View中测试场景。
    这样做将会使你清楚了解这个场景中的物体或者附加在物体上的脚本是否降低了游戏性能。
    如果Scene View反应迟钝,那么有可能是图形方面的原因,如果Scene View反应不迟钝,那么瓶颈可能出在脚本或者物理系统上。
    禁用指定游戏物体。
    在play模式下,尝试禁用并启用游戏物体来排查出游戏慢的原因。

    网格
    如果可能的话,把相邻的物体(网格)合并为一个只有一个材质的物体(网格)。比如,你的游戏中包含一个桌子,上面有一堆东西,你完全可以在3D程序中将它们合并在一起(这可能也需要你将这些物体的纹理合并为一个大的纹理集)。减少需要渲染的物体的数量可以极大地提高游戏性能。

    不要有不必要的网格。
    如果你的游戏场景中有一个人物,那么他应该是一个网格。如果你有一个船,那么它也应该只是一个网格。
    每一个网格只用一种材质。
    使用极少的面数的网格(比如500个多边形以下)。
    最好把你人物的三角面数量控制在1500-2000个之间。
    这个数量可以说是游戏质量和性能之间一个均衡值。如果你的模型有四边形,那么在导入模型的时候,引擎将会把每个四边形变为两个三角形。

    光照
    像素光。
    像素光可以让你的游戏看起来效果很牛逼,但是不要使用过多的像素光。
    在你的游戏中可以使用质量管理器来调节像素光的数量来取得一个性能和质量的均衡点.

    性能占用顺序:聚光灯>点光源>平行光。
    一个好的点亮场景的方法就是先得到你想要的效果,然后看看哪些光更重要;
    在保持光效的前提下看看哪些光可以去掉。

    点光源和聚光灯只影响它们范围内的网格。
    如果一个网格处于点光源或者聚光灯的照射范围之外,并且光源的attenuate开关是打开的,那么这个网格将不会被光源所影响,这样就可以节省性能开销。
    这样做理论上来讲可以使用很多小的点光源而且依然能有一个好的性能,因为这些光源只影响一小部分物体。
    一个网格在有8个以上光源影响的时候,只响应前8个最亮的光源。

    贴图
    在外观不变的前提下,贴图大小越小越好。
    如果你的显卡的显存不够大的话,你游戏中的贴图将会被转存到系统内存中,在显卡调用它们的时候再传到显卡中。
    对于比较新的电脑来说,内存和显卡之间有足够的带宽来达到一个很好的性能;
    如果你很无耻地用了巨多的大图片的话,在低显存的电脑上运行你的游戏的时候,你的游戏必然会挂掉。
    倒是没有必要在图形编辑软件中调整贴图的大小。你可以在unity导入贴图的时候进行调整。

    不要使用低质量的图片。
    在小播放界面的游戏中使用低质量的jpeg图片或者低色彩的png图片亦或是gif图片没什么问题。
    在发布游戏的时候,引擎会自动压缩这些图片,多重压缩和解压将会降低图片的质量,所以最好保持贴图文件的分辨率为原始分辨率。
    这样就会减少多重压缩和解压所导致的图片失真现象。

    Shaders
    多重效果的shader就比看起来样式很单一的shader要更耗费资源。
    同样在一个拥有贴图和光反射的物体上,使用VertexLit Diffuse shader无疑是最省资源的。


    ========================================分割线==================================== 

    在美术制作场景的过程中,会使用到大量的粒子系统。
    比如场景中的火把。在我们的一个地下城场景中,美术们放置了大量的火把。整个场景中的各个地方,有100来个火把。

    unity中,在摄像机范围外的粒子系统虽然不会被绘制。
    但是update是一直持续的。这也就意味着,这100多个火把,不论是否可见都在更新。

    这个设计应该是很不合理的,在我看过的其他引擎中,都会有一个开关,来控制不可见的粒子系统是否需要update。
    有的粒子系统在不可见的时候需要更新,比如爆炸。有的不需要更新,比如火堆火把。

    为了避免不必要的update开销,尤其是最后游戏是要发布到页游平台(web player只能使用一个cpu的核)。
    于是写了一个脚本,控制不可见的粒子系统就不更新。

    该脚本主要是用到了2个MonoBehaviour的函数。
    OnBecameInvisible() 当变为不可见   和   OnBecameVisible() 当变成可见。 

    要这2个函数起作用的前提是,该GameObject绑定了MeshRender组件。
    所以,我们要在粒子系统的GameObject放置在一个GameObject  下,且给该GameObject绑定一个MeshRender 与 MeshFilter。
    MeshFilter中的mesh可以随便找个cube。

    在Start() 的时候,把最GameObject的scale设置为很小,以保证该cube不被看见。
    其实遍历所有的child,把active设置为false。

    在OnBecameVisible 中 遍历所有child,把active设置为true。
    在OnBecameInvisible中 遍历所有child,把active设置为false。


    ========================================分割线==================================== 

    Unity 性能优化 Draw Call 

    Unity(或者说基本所有图形引擎)生成一帧画面的处理过程大致可以这样简化描述:引擎首先经过简单的可见性测试,确定摄像机可以看到的物体,然后把这些物体的顶点(包括本地位置、法线、UV等),索引(顶点如何组成三角形),变换(就是物体的位置、旋转、缩放、以及摄像机位置等),相关光源,纹理,渲染方式(由材质/Shader决定)等数据准备好,然后通知图形API——或者就简单地看作是通知GPU——开始绘制,GPU基于这些数据,经过一系列运算,在屏幕上画出成千上万的三角形,最终构成一幅图像。

    在Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。这一过程是逐个物体进行的,对于每个物体,不只GPU的渲染,引擎重新设置材质/Shader也是一项非常耗时的操作。因此每帧的Draw Call次数是一项非常重要的性能指标,对于iOS来说应尽量控制在20次以内,这个值可以在编辑器的Statistic窗口看到。

    Unity内置了Draw Call Batching技术,从名字就可以看出,它的主要目标就是在一次Draw Call中批量处理多个物体。只要物体的变换和材质相同,GPU就可以按完全相同的方式进行处理,即可以把它们放在一个Draw Call中。Draw Call Batching技术的核心就是在可见性测试之后,检查所有要绘制的物体的材质,把相同材质的分为一组(一个Batch),然后把它们组合成一个物体(统一变换),这样就可以在一个Draw Call中处理多个物体了(实际上是组合后的一个物体)。

    但Draw Call Batching存在一个缺陷,就是它需要把一个Batch中的所有物体组合到一起,相当于创建了一个与这些物体加起来一样大的物体,与此同时就需要分配相应大小的内存。这不仅会消耗更多内存,还需要消耗CPU时间。特别是对于移动的物体,每一帧都得重新进行组合,这就需要进行一些权衡,否则得不偿失。但对于静止不动的物体来说,只需要进行一次组合,之后就可以一直使用,效率要高得多。

    Unity提供了Dynamic Batching和Static Batching两种方式。Dynamic Batching是完全自动进行的,不需要也无法进行任何干预,对于顶点数在300以内的可移动物体,只要使用相同的材质,就会组成Batch。Static Batching则需要把静止的物体标记为Static,然后无论大小,都会组成Batch。如前文所说,Static Batching显然比Dynamic Batching要高效得多,于是,Static Batching功能是收费的……

    要有效利用Draw Call Batching,首先是尽量减少场景中使用的材质数量,即尽量共享材质,对于仅纹理不同的材质可以把纹理组合到一张更大的纹理中(称为Texture Atlasing)。然后是把不会移动的物体标记为Static。此外还可以通过CombineChildren脚本(Standard Assets/Scripts/Unity Scripts/CombineChildren)手动把物体组合在一起,但这个脚本会影响可见性测试,因为组合在一起的物体始终会被看作一个物体,从而会增加GPU要处理的几何体数量,因此要小心使用。

    对于复杂的静态场景,还可以考虑自行设计遮挡剔除算法,减少可见的物体数量同时也可以减少Draw Call。

    总之,理解Draw Call和Draw Call Batching原理,根据场景特点设计相应的方案来尽量减少Draw Call次数才是王道,其它方面亦然。



    Draw Call Batching (绘制调用批处理)

    To draw an object on the screen, the engine has to issue a draw call to the graphics API (OpenGL ES in the case of iOS). Every single draw call requires a significant amount of work on the part of the graphics API, causing significant performance overhead on the CPU side.
    在屏幕上渲染物体,引擎需要发出一个绘制调用来访问图形API(iOS系统中为OpenGL ES)。
    每个绘制调用需要进行大量的工作来访问图形API,从而导致了CPU方面显著的性能开销。

    Unity combines a number of objects at runtime and draws them together with a single draw call. This operation is called "batching". The more objects Unity can batch together, the better rendering performance you will get.
    Unity在运行时可以将一些物体进行合并,从而用一个绘制调用来渲染他们。这一操作,我们称之为“批处理”。
    一般来说,Unity批处理的物体越多,你就会得到越好的渲染性能。

    Built-in batching support in Unity has significant benefit over simply combining geometry in the modeling tool (or using theCombineChildren script from the Standard Assets package). Batching in Unity happensafter visibility determination step. The engine does culling on each object individually, and the amount of rendered geometry is going to be the same as without batching. Combining geometry in the modeling tool, on the other hand, prevents effecient culling and results in much higher amount of geometry being rendered.
    Unity中内建的批处理机制所达到的效果要明显强于使用几何建模工具(或使用Standard Assets包中的CombineChildren脚本)的批处理效果。
    这是因为,Unity引擎的批处理操作是在物体的可视裁剪操作之后进行的。
    Unity先对每个物体进行裁剪,然后再进行批处理,这样可以使渲染的几何总量在批处理前后保持不变。
    但是,使用几何建模工具来拼合物体,会妨碍引擎对其进行有效的裁剪操作,从而导致引擎需要渲染更多的几何面片。

    Materials
    材质
    Only objects sharing the same material can be batched together. Therefore, if you want to achieve good batching, you need to share as many materials among different objects as possible.
    只有拥有相同材质的物体才可以进行批处理。
    因此,如果你想要得到良好的批处理效果,你需要在程序中尽可能地复用材质和物体。

    If you have two identical materials which differ only in textures, you can combine those textures into a single big texture - a process often calledtexture atlasing. Once textures are in the same atlas, you can use single material instead.
    如果你的两个材质仅仅是纹理不同,那么你可以通过 纹理拼合 操作来将这两张纹理拼合成一张大的纹理。
    一旦纹理拼合在一起,你就可以使用这个单一材质来替代之前的两个材质了。

    If you need to access shared material properties from the scripts, then it is important to note that modifyingRenderer.material will create a copy of the material. Instead, you should useRenderer.sharedMaterial to keep material shared.
    如果你需要通过脚本来访问复用材质属性,那么值得注意的是改变Renderer.material将会造成一份材质的拷贝。
    因此,你应该使用Renderer.sharedMaterial来保证材质的共享状态。

    Dynamic Batching
    动态批处理
    Unity can automatically batch moving objects into the same draw call if they share the same material.
    如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行批处理。

    Dynamic batching is done automatically and does not require any additional effort on your side.
    动态批处理操作是自动完成的,并不需要你进行额外的操作。

    Tips:
    提醒:
    1、      Batching dynamic objects has certain overheadper vertex, so batching is applied only to meshes containing less than900 vertex attributes in total.
                 批处理动态物体需要在每个顶点上进行一定的开销,所以动态批处理仅支持小于900顶点的网格物体。

    2、      If your shader is using Vertex Position, Normal and single UV, then you can batch up to 300 verts and if your shader is using Vertex Position, Normal, UV0, UV1 and
                Tangent, then only 180 verts.
                Please note: attribute count limit might be changed in future
                如果你的着色器使用顶点位置,法线和UV值三种属性,那么你只能批处理300顶点以下的物体;
    如果你的着色器需要使用顶点位置,法线,UV0,UV1和切向量,那你只
                能批处理180顶点以下的物体。
                请注意:属性数量的限制可能会在将来进行改变。

    4、      Don't use scale. Objects with scale (1,1,1) and (2,2,2) won't batch.
                不要使用缩放尺度(scale)。分别拥有缩放尺度(1,1,1)和(2,2,2)的两个物体将不会进行批处理。

    5、      Uniformly scaled objects won't be batched with non-uniformly scaled ones.
                统一缩放尺度的物体不会与非统一缩放尺度的物体进行批处理。
               Objects with scale (1,1,1) and (1,2,1) won't be batched. On the other hand (1,2,1) and (1,3,1) will be.
               使用缩放尺度(1,1,1)和 (1,2,1)的两个物体将不会进行批处理,但是使用缩放尺度(1,2,1)和(1,3,1)的两个物体将可以进行批处理。

    6、     Using different material instances will cause batching to fail.
               使用不同材质的实例化物体(instance)将会导致批处理失败。

    7、     Objects with lightmaps have additional (hidden) material parameter: offset/scale in lightmap, so lightmapped objects won't be batched (unless they point to same
               portions of lightmap)
               拥有lightmap的物体含有额外(隐藏)的材质属性,比如:lightmap的偏移和缩放系数等。所以,拥有lightmap的物体将不会进行批处理(除非他们指向lightmap的同一
               部分)。

    8、     Multi-pass shaders will break batching. E.g. Almost all unity shaders supports several lights in forward rendering, effectively doing additional pass for them
               多通道的shader会妨碍批处理操作。比如,几乎unity中所有的着色器在前向渲染中都支持多个光源,并为它们有效地开辟多个通道。

    9、     Using instances of a prefab automatically are using the same mesh and material.
               预设体的实例会自动地使用相同的网格模型和材质。

    Static Batching
    静态批处理

    Static batching, on the other hand, allows the engine to reduce draw calls for geometry of any size (provided it does not move and shares the same material). Static batching is significantly more efficient than dynamic batching. You should choose static batching as it will require less CPU power.
    相对而言,静态批处理操作允许引擎对任意大小的几何物体进行批处理操作来降低绘制调用(只要这些物体不移动,并且拥有相同的材质)。因此,静态批处理比动态批处理更加有效,你应该尽量低使用它,因为它需要更少的CPU开销。

    In order to take advantage of static batching, you need explicitly specify that certain objects are static and willnot move, rotate or scale in the game. To do so, you can mark objects as static using the Static checkbox in the Inspector:
    为了更好地使用静态批处理,你需要明确指出哪些物体是静止的,并且在游戏中永远不会移动、旋转和缩放。想完成这一步,你只需要在检测器(Inspector)中将Static复选框打勾即可,如下图所示:


    Using static batching will require additional memory for storing the combined geometry. If several objects shared the same geometry before static batching, then a copy of geometry will be created for each object, either in the Editor or at runtime. This might not always be a good idea - sometimes you will have to sacrifice rendering performance by avoiding static batching for some objects to keep a smaller memory footprint. For example, marking trees as static in a dense forest level can have serious memory impact.
    使用静态批处理操作需要额外的内存开销来储存合并后的几何数据。在静态批处理之前,如果一些物体共用了同样的几何数据,那么引擎会在编辑以及运行状态对每个物体创建一个几何数据的备份。这并不总是一个好的想法,因为有时候,你将不得不牺牲一点渲染性能来防止一些物体的静态批处理,从而保持较少的内存开销。比如,将浓密森里中树设为Static,会导致严重的内存开销。

    Static batching is only available in Unity iOS Advanced.
    静态批处理目前只支持Unity iOS Advanced。



    备注:最近一直在研究Unity3D的性能优化问题,这段时间可能会多翻译这方面的文章。

    前两天,MadFinger,就是当今iOS与Android上画质最牛逼闪闪的游戏之一——ShadowGun的开发商,令人惊异地放出了一个ShadowGun的样例关卡以及若干可免费使用的Shader,国外同行们的分享精神真的是令人赞叹不已。原文在这里,以下是我的一些摘录和笔记。

    首先是一些优化常识。针对图形方面的优化主要包括三角形数量,纹理所占内存,以及Shader,前两项基本没什么好讲的,针对设备机能的限制制定相应的指标即可,所以Shader就成为了图形性能优化的关键。

    Alpha blending

    在Unity官方文档中讲,由于硬件原因,在iOS设备上使用alpha-test会造成很大的性能开销,应尽量使用alpha-blend代替。这里提到,在同屏使用alpha-blend的面数,尤其是这些面所占屏幕面积的大小,对性能也会造成很大影响。原因是使用alpha-blend的面会造成overdraw的增加,这尤其对低性能设备的影响很大。不过没有购买Pro版,没有Occlusion Culling功能的话,就不必顾虑这一问题了,反正overdraw是必然的。

    复杂的Per-pixel shader

    Per-pixel shader即Fragment shader,顾名思义是要对每个渲染到屏幕上的像素做处理的shader,如果per-pixel shader比较复杂且需要处理的像素很多时,也就是使用该shader的面占屏幕面积很大时,对性能的影响甚至要超过alpha blending。因此复杂的per-pixel shader只适用于小物体。

    下面是对几个Shader的逐一讲解:

    Environment specular maps(Shader Virtual Gloss Per Vertex Additive)
    Specular map通常都是利用贴图的alpha通道来定义物体表面的光滑程度(反光度),这个shader的特点是per-vertex计算反光度的,有着相当不错的效果的同时比per-pixel的shader性能要高得多。这个shader很适用于关卡环境等占很大区域的模型。

    经过优化的动态角色光照和阴影(Light probes和BRDF Shader)
    传统的Lightmaps无法支持动态物体,对此Unity提供了Light probes技术,预先把动态物体的光照信息保存在代理对象(即Light probes)中,运行时动态物体从距离最近的Probe中获取光照信息。

    Unity本身还提供了一个效果非常棒的专为移动设备优化过的角色Shader,支持Diffuse、Specular和Normal maps,并通过一个特殊的脚本生成贴图用于模仿BRDF光照效果。最终产生的效果堪比次时代大作中的角色光影效果。

    雾和体积光(Shader Blinking Godrays)
    目前在移动设备上要开启真正的雾效基本不可行,ShadowGun的方案是通过简单的网格+透明贴图(称为雾面)来模拟雾效。在玩家靠近时,雾面逐渐变淡,同时fog plane的顶点也会移开(即使完全透明的alpha面也会消耗很多渲染时间)。

    使用这个Shader的网格需要经过处理:

    顶点的alpha值用于决定顶点是否可以移动(在例子中0为不可动,1为可动)。
    顶点法线决定移动的方向
    然后Shader通过计算与观察者的距离来控制雾面的淡入/淡出。
    这个Shader还可以用来做体积光和其它一些alpha效果。

    飞机坠毁的浓烟效果(Shader Scroll 2 Layers Sine Alpha-blended)
    通过粒子产生浓烟的代价太高,所以ShadowGun中使用了网格+贴图动画来制作这个效果。通过混合两层贴图并让它们交错移动来产生动画效果。其中顶点alpha值用于让网格的边缘看起来比较柔和,同时使用顶点颜色来模拟从火焰到烟雾的过渡效果。

    带动态效果的天空盒(Shader Scroll 2 Layers Multiplicative)
    通过两张贴图的混合和移动产生云的动态效果。

    旗帜和衣服的飘动效果(Shader Lightmap + Wind)
    同样利用顶点alpha值决定哪些顶点可以移动,然后shader的参数用于调整摆动的方向和速度。
    =======================分割线========================

    一、程序方面
      01、务必删除脚本中为空或不需要的默认方法;
      02、只在一个脚本中使用OnGUI方法;
      03、避免在OnGUI中对变量、方法进行更新、赋值,输出变量建议在Update内;
      04、同一脚本中频繁使用的变量建议声明其为全局变量,脚本之间频繁调用的变量或方法建议声明为全局静态变量或方法;
      05、不要去频繁获取组件,将其声明为全局变量;
      06、数组、集合类元素优先使用Array,其次是List;
      07、脚本在不使用时脚本禁用之,需要时再启用;
      08、可以使用Ray来代替OnMouseXXX类方法;
      09、需要隐藏/显示或实例化来回切换的对象,尽量不要使用SetActiveRecursively或active,而使用将对象远远移出相机范围和移回原位的做法;
      10、尽量少用模运算和除法运算,比如a/5f,一定要写成a*0.2f。
      11、对于不经常调用或更改的变量或方法建议使用Coroutines & Yield;
      12、尽量直接声明脚本变量,而不使用GetComponent来获取脚本;
    iPhone
      13、尽量使用整数数字,因为iPhone的浮点数计算能力很差;
      14、不要使用原生的GUI方法;
      15、不要实例化(Instantiate)对象,事先建好对象池,并使用Translate“生成”对象;
     

    二、模型方面
      01、合并使用同贴图的材质球,合并使用相同材质球的Mesh;
      02、角色的贴图和材质球只要一个,若必须多个则将模型离分离为多个部分;
      02、骨骼系统不要使用太多;
      03、当使用多角色时,将动画单独分离出来;
      04、使用层距离来控制模型的显示距离;
      05、阴影其实包含两方面阴暗和影子,建议使用实时影子时把阴暗效果烘焙出来,不要使用灯光来调节光线阴暗。
      06、少用像素灯和使用像素灯的Shader;
      08、如果硬阴影可以解决问题就不要用软阴影,并且使用不影响效果的低分辨率阴影;
      08、实时阴影很耗性能,尽量减小产生阴影的距离;
      09、允许的话在大场景中使用线性雾,这样可以使远距离对象或阴影不易察觉,因此可以通过减小相机和阴影距离来提高性能;
      10、使用圆滑组来尽量减少模型的面数;
      11、项目中如果没有灯光或对象在移动那么就不要使用实时灯光;
      12、水面、镜子等实时反射/折射的效果单独放在Water图层中,并且根据其实时反射/折射的范围来调整;
      13、碰撞对效率的影响很小,但碰撞还是建议使用Box、Sphere碰撞体;
      14、建材质球时尽量考虑使用Substance;
      15、尽量将所有的实时反射/折射(如水面、镜子、地板等等)都集合成一个面;
      16、假反射/折射没有必要使用过大分辨率,一般64*64就可以,不建议超过256*256;
      17、需要更改的材质球,建议实例化一个,而不是使用公共的材质球;
      18、将不须射线或碰撞事件的对象置于IgnoreRaycast图层;
      19、将水面或类似效果置于Water图层
      20、将透明通道的对象置于TransparentFX图层;
      21、养成良好的标签(Tags)、层次(Hieratchy)和图层(Layer)的条理化习惯,将不同的对象置于不同的标签或图层,三者有效的结合将很方便的按名称、类别和属性来查找;
      22、通过Stats和Profile查看对效率影响最大的方面或对象,或者使用禁用部分模型的方式查看问题到底在哪儿;
      23、使用遮挡剔除(Occlusion Culling)处理大场景,一种较原生的类LOD技术,并且能够“分割”作为整体的一个模型。

    三、其它
      场景中如果没有使用灯光和像素灯,就不要使用法线贴图,因为法线效果只有在有光源(Direct Light/Point Light/Angle Light/Pixel Light)的情况下才有效果。 
    展开全文
  • Android 性能优化四个方面总结

    千次阅读 2018-12-17 16:56:49
    目录一、四个方面二、卡顿优化1、Android系统显示原理2、卡顿根本原因3、性能分析工具(1)Profile GPU Rendering(2)TraceView(3)Systrace UI 性能分析4、优化建议(1)布局优化(2)避免过度绘制(3)启动优化...

    一、四个方面

    可以把用户体验的性能问题主要总结为4个类别:

    • 流畅

    • 稳定

    • 省电、省流量

    • 安装包小

    性能问题的主要原因是什么,原因有相同的,也有不同的,但归根到底,不外乎内存使用、代码效率、合适的策略逻辑、代码质量、安装包体积这一类问题,整理归类如下:
    在这里插入图片描述
    从图中可以看到,打造一个高质量的应用应该以4个方向为目标:快、稳、省、小。

    • :使用时避免出现卡顿,响应速度快,减少用户等待的时间,满足用户期望。

    • :减低 crash 率和 ANR 率,不要在用户使用过程中崩溃和无响应。

    • :节省流量和耗电,减少用户使用成本,避免使用时导致手机发烫。

    • :安装包小可以降低用户的安装成本。

    要想达到这4个目标,具体实现是在右边框里的问题:卡顿、内存使用不合理、代码质量差、代码逻辑乱、安装包过大,这些问题也是在开发过程中碰到最多的问题,在实现业务需求同时,也需要考虑到这点,多花时间去思考,如何避免功能完成后再来做优化,不然的话等功能实现后带来的维护成本会增加。

    二、卡顿优化

    Android 应用启动慢,使用时经常卡顿,是非常影响用户体验的,应该尽量避免出现。卡顿的场景有很多,按场景可以分为4类:UI 绘制、应用启动、页面跳转、事件响应,如图:
    在这里插入图片描述

    这4种卡顿场景的根本原因可以分为两大类:

    • 界面绘制:主要原因是绘制的层级深、页面复杂、刷新不合理,由于这些原因导致卡顿的场景更多出现在UI和启动后的初始界面以及跳转到页面的绘制上。

    • 数据处理:导致这种卡顿场景的原因是数据处理量太大,一般分为三种情况,一是数据在处理UI线程,二是数据处理占用CPU高,导致主线程拿不到时间片,三是内存增加导致GC频繁,从而引起卡顿。

    引起卡顿的原因很多,但不管怎么样的原因和场景,最终都是通过设备屏幕上显示来达到用户,归根到底就是显示有问题,所以,要解决卡顿,就要先了解Android系统的显示原理。

    1、Android系统显示原理

    Android显示过程可以简单概括为:Android应用程序把经过测量、布局、绘制后的Surface缓存数据,通过SurfaceFlinger把数据渲染到显示屏幕上, 通过Android的刷新机制来刷新数据。也就是说应用层负责绘制,系统层负责渲染,通过进程间通信把应用层需要绘制的数据传递到系统层服务,系统层服务通过刷新机制把数据更新到屏幕上

    我们都知道在Android的每个View绘制中有三个核心步骤:Measure、Layout、Draw。具体实现是从 ViewRootImp类的performTraversals() 方法开始执行,Measure和Layout都是通过递归来获取View的大小和位置,并且以深度作为优先级,可以看出 层级越深、元素越多、耗时也就越长

    真正把需要显示的数据渲染到屏幕上,是通过系统级进程中的SurfaceFlinger服务来实现的,那么这个SurfaceFlinger服务主要做了哪些工作呢?如下:

    • 响应客户端事件,创建Layer与客户端的Surface建立连接。

    • 接收客户端数据及属性,修改Layer属性,如尺寸、颜色、透明度等。

    • 将创建的Layer内容刷新到屏幕上。

    • 维持Layer的序列,并对Layer最终输出做出裁剪计算。

    既然是两个不同的进程,那么肯定是需要一个跨进程的通信机制来实现数据传递,在Android显示系统中,使用了Android的匿名共享内存:SharedClient,每一个应用和SurfaceFlinger之间都会创建一个SharedClient ,然后在每个SharedClient中,最多可以创建31个 SharedBufferStack,每个Surface都对应一个SharedBufferStack,也就是一个Window。

    一个SharedClient对应一个Android应用程序,而一个Android应用程序可能包含多个窗口,即Surface。也就是说SharedClient包含的是SharedBufferStack的集合,其中在显示刷新机制中用到了双缓冲和三重缓冲技术。最后总结起来显示整体流程分为三个模块:应用层绘制到缓存区,SurfaceFlinger把缓存区数据渲染到屏幕,由于是不同的进程,所以使用Android的匿名共享内存SharedClient缓存需要显示的数据来达到目的。

    除此之外,我们还需要一个名词:FPS。FPS表示每秒传递的帧数在理想情况下,60FPS就感觉不到卡,这意味着每个绘制时长应该在16ms以内。但是 Android系统很有可能无法及时完成那些复杂的页面渲染操作。Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需的60FPS。如果某个操作花费的时间是24ms ,系统在得到VSYNC信号时就无法正常进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面,这种现象在执行动画或滑动列表比较常见,还有可能是你的Layout太过复杂,层叠太多的绘制单元,无法在16ms完成渲染,最终引起刷新不及时。

    2、卡顿根本原因

    根据Android系统显示原理可以看到,影响绘制的根本原因有以下两个方面:

    • 绘制任务太重,绘制一帧内容耗时太长

    • 主线程太忙,根据系统传递过来的VSYNC信号来时还没准备好数据导致丢帧

    绘制耗时太长,有一些工具可以帮助我们定位问题。主线程太忙则需要注意了,主线程关键职责是处理用户交互,在屏幕上绘制像素,并进行加载显示相关的数据,所以特别需要避免任何主线程的事情,这样应用程序才能保持对用户操作的即时响应。总结起来,主线程主要做以下几个方面工作:

    • UI生命周期控制

    • 系统事件处理

    • 消息处理

    • 界面布局

    • 界面绘制

    • 界面刷新

    除此之外,应该尽量避免将其他处理放在主线程中,特别复杂的数据计算和网络请求等。

    3、性能分析工具

    性能问题并不容易复现,也不好定位,但是真的碰到问题还是需要去解决的,那么分析问题和确认问题是否解决,就需要借助相应的的调试工具,比如查看Layout层次的Hierarchy View、Android系统上带的GPU Profile工具和静态代码检查工具Lint等,这些工具对性能优化起到非常重要的作用,所以要熟悉,知道在什么场景用什么工具来分析。

    (1)Profile GPU Rendering

    在手机开发者模式下,有一个卡顿检测工具叫做:Profile GPU Rendering,如图:
    在这里插入图片描述

    它的功能特点如下:

    • 一个图形监测工具,能实时反应当前绘制的耗时

    • 横轴表示时间,纵轴表示每一帧的耗时

    • 随着时间推移,从左到右的刷新呈现

    • 提供一个标准的耗时,如果高于标准耗时,就表示当前这一帧丢失

    (2)TraceView

    TraceView是Android SDK自带的工具,用来分析函数调用过程,可以对Android的应用程序以及Framework层的代码进行性能分析。它是一个图形化的工具,最终会产生一个图表,用于对性能分析进行说明,可以分析到每一个方法的执行时间,其中可以统计出该方法调用次数和递归次数,实际时长等参数维度,使用非常直观,分析性能非常方便。

    (3)Systrace UI 性能分析

    Systrace是Android 4.1及以上版本提供的性能数据采样和分析工具,它是通过系统的角度来返回一些信息。它可以帮助开发者收集Android关键子系统,如Surfaceflinger、WindowManagerService等Framework部分关键模块、服务、View系统等运行信息,从而帮助开发者更直观地分析系统瓶颈,改进性能。Systrace的功能包括跟踪系统的I/O操作、内核工作队列、CPU负载等,在UI显示性能分析上提供很好的数据,特别是在动画播放不流畅、渲染卡等问题上。

    4、优化建议

    • 布局优化
    • 避免过度绘制
    • 启动优化
    • 合理的刷新机制
    • 其他

    (1)布局优化

    布局是否合理主要影响的是页面测量时间的多少,我们知道一个页面的显示测量和绘制过程都是通过递归来完成的,多叉树遍历的时间与树的高度h有关,其时间复杂度O(h),如果层级太深,每增加一层则会增加更多的页面显示时间,所以布局的合理性就显得很重要。

    那布局优化有哪些方法呢,主要通过 减少层级、减少测量和绘制时间、提高复用性 三个方面入手。总结如下:

    • 减少层级:合理使用RelativeLayout和LinerLayout,合理使用Merge。

    • 提高显示速度:使用ViewStub,它是一个看不见的、不占布局位置、占用资源非常小的视图对象。

    • 布局复用:可以通过标签(include)来提高复用。

    • 尽可能少用wrap_content:wrap_content 会增加布局measure时计算成本,在已知宽高为固定值时,不用wrap_content。

    • 其他:删除控件中无用的属性。

    (2)避免过度绘制

    过度绘制是指在屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的UI结构中,如果不可见的UI也在做绘制的操作,就会导致某些像素区域被绘制了多次,从而浪费了多余的CPU以及GPU源。

    如何避免过度绘制呢,如下:

    • 布局上的优化:移除XML中非必须的背景,移除Window默认的背景、按需显示占位背景图片。

    • 自定义View优化:使用 canvas.clipRect()来帮助系统识别那些可见的区域,只有在这个区域内才会被绘制。

    (3)启动优化

    通过对启动速度的监控,发现影响启动速度的问题所在,优化启动逻辑,提高应用的启动速度。启动主要完成三件事:UI布局、绘制和数据准备。因此启动速度优化就是需要优化这三个过程:

    • UI布局:应用一般都有闪屏页,优化闪屏页的UI布局,可以通过Profile GPU Rendering检测丢帧情况。

    • 启动加载逻辑优化:可以采用分布加载、异步加载、延期加载策略来提高应用启动速度。

    • 数据准备:数据初始化分析,加载数据可以考虑用线程初始化等策略。

    (4)合理的刷新机制

    在应用开发过程中,因为数据的变化,需要刷新页面来展示新的数据,但频繁刷新会增加资源开销,并且可能导致卡顿发生,因此,需要一个合理的刷新机制来提高整体的UI流畅度。合理的刷新需要注意以下几点:

    • 尽量减少刷新次数

    • 尽量避免后台有高的CPU线程运行

    • 缩小刷新区域

    (5)其他

    在实现动画效果时,需要根据不同场景选择合适的动画框架来实现。有些情况下,可以用硬件加速方式来提供流畅度。

    三、内存优化

    在Android系统中有个垃圾内存回收机制,在虚拟机层自动分配和释放内存,因此不需要在代码中分配和释放某一块内存,从应用层面上不容易出现内存泄漏和内存溢出等问题,但是需要内存管理。Android系统在内存管理上有一个Generational Heap Memory模型,内存回收的大部分压力不需要应用层关心,Generational Heap Memory有自己一套管理机制,当内存达到一个阈值时,系统会根据不同的规则自动释放系统认为可以释放的内存,也正是因为Android程序把内存控制的权力交给了Generational Heap Memory,一旦出现内存泄漏和溢出方面的问题,排查错误将会成为一项异常艰难的工作。除此之外,部分Android应用开发人员在开发过程中并没有特别关注内存的合理使用,也没有在内存方面做太多的优化,当应用程序同时运行越来越多的任务,加上越来越复杂的业务需求时,完全依赖Android的内存管理机制就会导致一系列性能问题逐渐呈现,对应用的稳定性和性能带来不可忽视的影响,因此,解决内存问题和合理优化内存是非常有必要的。

    1、Android内存管理机制

    Android应用都是在 Android的虚拟机上运行,应用 程序的内存分配与垃圾回收都是由虚拟机完成的。在Android系统,虚拟机有两种运行模式:Dalvik和ART。

    (1)Java对象生命周期

    在这里插入图片描述
    一般Java对象在虚拟机上有7个运行阶段:

    创建阶段->应用阶段->不可见阶段->不可达阶段->收集阶段->终结阶段->对象空间重新分配阶段

    (2)内存分配

    在Android系统中,内存分配实际上是对堆的分配和释放。当一个Android程序启动,应用进程都是从一个叫做Zygote的进程衍生出来,系统启动 Zygote 进程后,为了启动一个新的应用程序进程,系统会衍生Zygote进程生成一个新的进程,然后在新的进程中加载并运行应用程序的代码。其中,大多数的RAM pages被用来分配给Framework代码,同时促使RAM资源能够在应用所有进程之间共享。

    但是为了整个系统的内存控制需要,Android系统会为每一个应用程序都设置一个硬性的Dalvik Heap Size最大限制阈值,整个阈值在不同设备上会因为RAM大小不同而有所差异。如果应用占用内存空间已经接近整个阈值时,再尝试分配内存的话,就很容易引起内存溢出的错误。

    (3)内存回收机制

    我们需要知道的是,在Java中内存被分为三个区域:Young Generation(新生代)、Old Generation(年老代)、Permanent Generation(持久代)。最近分配的对象会存放在Young Generation区域。对象在某个时机触发GC回收垃圾,而没有回收的就根据不同规则,有可能被移动到Old Generation,最后累积一定时间在移动到Permanent Generation 区域。系统会根据内存中不同的内存数据类型分别执行不同的GC操作。GC通过确定对象是否被活动对象引用来确定是否收集对象,进而动态回收无任何引用的对象占据的内存空间。但需要注意的是频繁的GC会增加应用的卡顿情况,影响应用的流畅性,因此需要尽量减少系统GC行为,以便提高应用的流畅度,减小卡顿发生的概率。

    2、内存分析工具

    做内存优化前,需要了解当前应用的内存使用现状,通过现状去分析哪些数据类型有问题,各种类型的分布情况如何,以及在发现问题后如何发现是哪些具体对象导致的,这就需要相关工具来帮助我们。

    (1)Memory Monitor

    Memory Monitor是一款使用非常简单的图形化工具,可以很好地监控系统或应用的内存使用情况,主要有以下功能:

    • 显示可用和已用内存,并且以时间为维度实时反应内存分配和回收情况。

    • 快速判断应用程序的运行缓慢是否由于过度的内存回收导致。

    • 快速判断应用是否由于内存不足导致程序崩溃。

    (2)Heap Viewer

    Heap Viewer的主要功能是查看不同数据类型在内存中的使用情况,可以看到当前进程中的Heap Size的情况,分别有哪些类型的数据,以及各种类型数据占比情况。通过分析这些数据来找到大的内存对象,再进一步分析这些大对象,进而通过优化减少内存开销,也可以通过数据的变化发现内存泄漏。

    (3)Allocation Tracker

    Memory Monitor和Heap Viewer都可以很直观且实时地监控内存使用情况,还能发现内存问题,但发现内存问题后不能再进一步找到原因,或者发现一块异常内存,但不能区别是否正常,同时在发现问题后,也不能定位到具体的类和方法。这时就需要使用另一个内存分析工具Allocation Tracker,进行更详细的分析,Allocation Tracker可以分配跟踪记录应用程序的内存分配,并列出了它们的调用堆栈,可以查看所有对象内存分配的周期。

    (4)Memory Analyzer Tool(MAT)

    MAT是一个快速,功能丰富的Java Heap分析工具,通过分析Java进程的内存快照HPROF分析,从众多的对象中分析,快速计算出在内存中对象占用的大小,查看哪些对象不能被垃圾收集器回收,并可以通过视图直观地查看可能造成这种结果的对象。

    3、常见内存泄漏场景

    如果在内存泄漏发生后再去找原因并修复会增加开发的成本,最好在编写代码时就能够很好地考虑内存问题,写出更高质量的代码,这里列出一些常见的内存泄漏场景,在以后的开发过程中需要避免这类问题。

    • 资源性对象未关闭:比如Cursor、File文件等,往往都用了一些缓冲,在不使用时,应该及时关闭它们。

    • 注册对象未注销:比如事件注册后未注销,会导致观察者列表中维持着对象的引用。

    • 类的静态变量持有大数据对象

    • 非静态内部类的静态实例

    • Handler临时性内存泄漏:如果Handler是非静态的,容易导致Activity或Service不会被回收。

    • 容器中的对象没清理造成的内存泄漏

    • WebView:WebView存在着内存泄漏的问题,在应用中只要使用一次WebView,内存就不会被释放掉。

    除此之外,内存泄漏可监控,常见的就是用LeakCanary第三方库,这是一个检测内存泄漏的开源库,使用非常简单,可以在发生内存泄漏时告警,并且生成leak tarce分析泄漏位置,同时可以提供Dump文件进行分析。

    4、优化内存空间

    没有内存泄漏,并不意味着内存就不需要优化,在移动设备上,由于物理设备的存储空间有限,Android 系统对每个应用进程也都分配了有限的堆内存,因此使用最小内存对象或者资源可以减小内存开销,同时让GC 能更高效地回收不再需要使用的对象,让应用堆内存保持充足的可用内存,使应用更稳定高效地运行。常见做法如下:

    • 对象引用:强引用、软引用、弱引用、虚引用四种引用类型,根据业务需求合理使用不同,选择不同的引用类型。

    • 减少不必要的内存开销:注意自动装箱,增加内存复用,比如有效利用系统自带的资源、视图复用、对象池、Bitmap对象的复用。

    • 使用最优的数据类型:比如针对数据类容器结构,可以使用ArrayMap数据结构,避免使用枚举类型,使用缓存Lrucache等等。

    • 图片内存优化:可以设置位图规格,根据采样因子做压缩,用一些图片缓存方式对图片进行管理等等。

    四、稳定性优化

    Android应用的稳定性定义很宽泛,影响稳定性的原因很多,比如内存使用不合理、代码异常场景考虑不周全、代码逻辑不合理等,都会对应用的稳定性造成影响。其中最常见的两个场景是:Crash和ANR,这两个错误将会使得程序无法使用,比较常用的解决方式如下:

    • 提高代码质量:比如开发期间的代码审核,看些代码设计逻辑,业务合理性等。

    • 代码静态扫描工具:常见工具有Android Lint、Findbugs、Checkstyle、PMD等等。

    • Crash监控:把一些崩溃的信息,异常信息及时地记录下来,以便后续分析解决。

    • Crash上传机制:在Crash后,尽量先保存日志到本地,然后等下一次网络正常时再上传日志信息。

    五、耗电优化

    在移动设备中,电池的重要性不言而喻,没有电什么都干不成。对于操作系统和设备开发商来说,耗电优化一致没有停止,去追求更长的待机时间,而对于一款应用来说,并不是可以忽略电量使用问题,特别是那些被归为“电池杀手”的应用,最终的结果是被卸载。因此,应用开发者在实现需求的同时,需要尽量减少电量的消耗。

    在Android5.0以前,在应用中测试电量消耗比较麻烦,也不准确,5.0之后专门引入了一个获取设备上电量消耗信息的API:Battery Historian。Battery Historian是一款由Google提供的Android系统电量分析工具,和Systrace一样,是一款图形化数据分析工具,直观地展示出手机的电量消耗过程,通过输入电量分析文件,显示消耗情况,最后提供一些可供参考电量优化的方法。

    除此之外,还有一些常用方案可提供:

    • 计算优化,避开浮点运算等

    • 避免WaleLock使用不当

    • 使用Job Scheduler

    六、安装包大小优化

    应用安装包大小对应用使用没有影响,但应用的安装包越大,用户下载的门槛越高,特别是在移动网络情况下,用户在下载应用时,对安装包大小的要求更高,因此,减小安装包大小可以让更多用户愿意下载和体验产品。

    常用应用安装包的构成,如图所示:
    在这里插入图片描述

    从图中我们可以看到:

    • assets文件夹:存放一些配置文件、资源文件,assets不会自动生成对应的 ID,而是通过AssetManager类的接口获取。

    • res:res是resource的缩写,这个目录存放资源文件,会自动生成对应的ID并映射到 .R文件中,访问直接使用资源ID。

    • META-INF:保存应用的签名信息,签名信息可以验证APK文件的完整性。

    • AndroidManifest.xml:这个文件用来描述Android应用的配置信息,一些组件的注册信息、可使用权限等。

    • classes.dex:Dalvik字节码程序,让Dalvik虚拟机可执行,一般情况下,Android应用在打包时通过Android SDK中的dx工具将Java字节码转换为Dalvik字节码。

    • resources.arsc:记录着资源文件和资源ID之间的映射关系,用来根据资源ID寻找资源。

    减少安装包大小的常用方案:

    • 代码混淆:使用ProGuard代码混淆器工具,它包括压缩、优化、混淆等功能。

    • 资源优化:比如使用Android Lint删除冗余资源,资源文件最少化等。

    • 图片优化:比如利用AAPT工具对PNG格式的图片做压缩处理,降低图片色彩位数等。

    • 避免重复功能的库,使用WebP图片格式

    • 插件化:比如功能模块放在服务器上,按需下载,可以减少安装包大小。

    展开全文
  • Mysql优化方面的面试题

    千次阅读 2018-11-05 12:32:12
    1、MySQL的复制原理以及流程: 基本原理流程,3个线程以及之间的关联; 1. 主:binlog线程——记录下所有改变了数据库数据的语句,放进master上的binlog中; 2. 从:io线程——在使用start slave 之后,负责从...

    前言

    本文是个人在各种地方收集过来,包括自己总结的问题,都参杂在内,适合中级或者中上级开发面试的难度。

     

    1、MySQL的复制原理以及流程:

    基本原理流程,3个线程以及之间的关联;

    1. 主:binlog线程——记录下所有改变了数据库数据的语句,放进master上的binlog中;

    2. 从:io线程——在使用start slave 之后,负责从master上拉取 binlog 内容,放进 自己的relay log中;

    3. 从:sql执行线程——执行relay log中的语句;

    2、MySQL中myisam与innodb的区别,至少5点

    (1)、问5点不同;

    1>.InnoDB支持事物,而MyISAM不支持事物

    2>.InnoDB支持行级锁,而MyISAM支持表级锁

    3>.InnoDB支持MVCC, 而MyISAM不支持

    4>.InnoDB支持外键,而MyISAM不支持

    5>.InnoDB不支持全文索引,而MyISAM支持。

    (2)、innodb引擎的4大特性

    插入缓冲(insert buffer),二次写(double write),自适应哈希索引(ahi),预读(read ahead)

    (3)、2者selectcount(*)哪个更快,为什么

    myisam更快,因为myisam内部维护了一个计数器,可以直接调取。

    3、MySQL中varchar与char的区别以及varchar(50)中的50代表的涵义

    (1)、varchar与char的区别

    char是一种固定长度的类型,varchar则是一种可变长度的类型

    (2)、varchar(50)中50的涵义

    最多存放50个字符,varchar(50)和(200)存储hello所占空间一样,但后者在排序时会消耗更多内存,因为order by col采用fixed_length计算col长度(memory引擎也一样)

    (3)、int(20)中20的涵义

    是指显示字符的长度

    但要加参数的,最大为255,比如它是记录行数的id,插入10笔资料,它就显示00000000001 ~~~00000000010,当字符的位数超过11,它也只显示11位,如果你没有加那个让它未满11位就前面加0的参数,它不会在前面加0

    20表示最大显示宽度为20,但仍占4字节存储,存储范围不变;

    (4)、mysql为什么这么设计

    对大多数应用没有意义,只是规定一些工具用来显示字符的个数;int(1)和int(20)存储和计算均一样;

    4、问了innodb的事务与日志的实现方式

    (1)、有多少种日志;

    错误日志:记录出错信息,也记录一些警告信息或者正确的信息。

    查询日志:记录所有对数据库请求的信息,不论这些请求是否得到了正确的执行。

    慢查询日志:设置一个阈值,将运行时间超过该值的所有SQL语句都记录到慢查询的日志文件中。

    二进制日志:记录对数据库执行更改的所有操作。

    中继日志:

    事务日志:

    (2)、事物的4种隔离级别

    隔离级别

    读未提交(RU)

    读已提交(RC)

    可重复读(RR)

    串行

    (3)、事务是如何通过日志来实现的,说得越深入越好。

    事务日志是通过redo和innodb的存储引擎日志缓冲(Innodb log buffer)来实现的,当开始一个事务的时候,会记录该事务的lsn(log sequence number)号; 当事务执行时,会往InnoDB存储引擎的日志

    的日志缓存里面插入事务日志;当事务提交时,必须将存储引擎的日志缓冲写入磁盘(通过innodb_flush_log_at_trx_commit来控制),也就是写数据前,需要先写日志。这种方式称为“预写日志方式”

    5、问了MySQL binlog的几种日志录入格式以及区别

    (1)、binlog的日志格式的种类和分别

    (2)、适用场景;

    (3)、结合第一个问题,每一种日志格式在复制中的优劣。

    Statement:每一条会修改数据的sql都会记录在binlog中。

    优点:不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能。(相比row能节约多少性能 与日志量,这个取决于应用的SQL情况,正常同一条记录修改或者插入row格式所产生的日志量还小于Statement产生的日志量,但是考虑到如果带条 件的update操作,以及整表删除,alter表等操作,ROW格式会产生大量日志,因此在考虑是否使用ROW格式日志时应该跟据应用的实际情况,其所 产生的日志量会增加多少,以及带来的IO性能问题。)

    缺点:由于记录的只是执行语句,为了这些语句能在slave上正确运行,因此还必须记录每条语句在执行的时候的 一些相关信息,以保证所有语句能在slave得到和在master端执行时候相同 的结果。另外mysql 的复制,像一些特定函数功能,slave可与master上要保持一致会有很多相关问题(如sleep()函数, last_insert_id(),以及user-defined functions(udf)会出现问题).

    使用以下函数的语句也无法被复制:

    * LOAD_FILE()

    * UUID()

    * USER()

    * FOUND_ROWS()

    * SYSDATE() (除非启动时启用了 --sysdate-is-now 选项)

    同时在INSERT ...SELECT 会产生比 RBR 更多的行级锁

    2.Row:不记录sql语句上下文相关信息,仅保存哪条记录被修改。

    优点: binlog中可以不记录执行的sql语句的上下文相关的信息,仅需要记录那一条记录被修改成什么了。所以rowlevel的日志内容会非常清楚的记录下 每一行数据修改的细节。而且不会出现某些特定情况下的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题

    缺点:所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比 如一条update语句,修改多条记录,则binlog中每一条修改都会有记录,这样造成binlog日志量会很大,特别是当执行alter table之类的语句的时候,由于表结构修改,每条记录都发生改变,那么该表每一条记录都会记录到日志中。

    3.Mixedlevel: 是以上两种level的混合使用,一般的语句修改使用statment格式保存binlog,如一些函数,statement无法完成主从复制的操作,则 采用row格式保存binlog,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择 一种.新版本的MySQL中队row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录。至于update或者delete等修改数据的语句,还是会记录所有行的 变更。

    6、问了下MySQL数据库cpu飙升到500%的话他怎么处理?

    (1)、没有经验的,可以不问;

    (2)、有经验的,问他们的处理思路。

    列出所有进程show processlist观察所有进程多秒没有状态变化的(干掉)

    查看超时日志或者错误日志 (做了几年开发,一般会是查询以及大批量的插入会导致cpu与i/o上涨,,,,当然不排除网络状态突然断了,,导致一个请求服务器只接受到一半,比如where子句或分页子句没有发送,,当然的一次被坑经历)

    7、sql优化

    (1)、explain出来的各种item的意义;

    select_type

    表示查询中每个select子句的类型

    type

    表示MySQL在表中找到所需行的方式,又称“访问类型”

    possible_keys

    指出MySQL能使用哪个索引在表中找到行,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用

    key

    显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL

    key_len

    表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度

    ref

    表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

    Extra

    包含不适合在其他列中显示但十分重要的额外信息

    (2)、profile的意义以及使用场景;

    查询到 SQL 会执行多少时间, 并看出 CPU/Memory 使用量, 执行过程中 Systemlock, Table lock 花多少时间等等

    8、备份计划,mysqldump以及xtranbackup的实现原理

    (1)、备份计划;

    这里每个公司都不一样,您别说那种1小时1全备什么的就行

    (2)、备份恢复时间;

    这里跟机器,尤其是硬盘的速率有关系,以下列举几个仅供参考

    20G的2分钟(mysqldump)

    80G的30分钟(mysqldump)

    111G的30分钟(mysqldump)

    288G的3小时(xtra)

    3T的4小时(xtra)

    逻辑导入时间一般是备份时间的5倍以上

    (3)、xtrabackup实现原理

    在InnoDB内部会维护一个redo日志文件,我们也可以叫做事务日志文件。事务日志会存储每一个InnoDB表数据的记录修改。当InnoDB启动时,InnoDB会检查数据文件和事务日志,并执行两个步骤:它应用(前滚)已经提交的事务日志到数据文件,并将修改过但没有提交的数据进行回滚操作。

    9、mysqldump中备份出来的sql,如果我想sql文件中,一行只有一个insert....value()的话,怎么办?如果备份需要带上master的复制点信息怎么办?

    --skip-extended-insert

    [root@helei-zhuanshu ~]# mysqldump -uroot -p helei --skip-extended-insert

    Enter password:

    KEY `idx_c1` (`c1`),

    KEY `idx_c2` (`c2`)

    ) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=latin1;

    /*!40101 SET character_set_client = @saved_cs_client */;

    --

    -- Dumping data for table `helei`

    --

    LOCK TABLES `helei` WRITE;

    /*!40000 ALTER TABLE `helei` DISABLE KEYS */;

    INSERT INTO `helei` VALUES (1,32,37,38,'2016-10-18 06:19:24','susususususususususususu');

    INSERT INTO `helei` VALUES (2,37,46,21,'2016-10-18 06:19:24','susususususu');

    INSERT INTO `helei` VALUES (3,21,5,14,'2016-10-18 06:19:24','susu');

    10、500台db,在最快时间之内重启

    puppet,dsh

    11、innodb的读写参数优化

    (1)、读取参数

    global buffer pool以及 local buffer;

    (2)、写入参数;

    innodb_flush_log_at_trx_commit

    innodb_buffer_pool_size

    (3)、与IO相关的参数;

    innodb_write_io_threads = 8

    innodb_read_io_threads = 8

    innodb_thread_concurrency = 0

    (4)、缓存参数以及缓存的适用场景。

    query cache/query_cache_type

    并不是所有表都适合使用query cache。造成query cache失效的原因主要是相应的table发生了变更

    第一个:读操作多的话看看比例,简单来说,如果是用户清单表,或者说是数据比例比较固定,比如说商品列表,是可以打开的,前提是这些库比较集中,数据库中的实务比较小。 第二个:我们“行骗”的时候,比如说我们竞标的时候压测,把query cache打开,还是能收到qps激增的效果,当然前提示前端的连接池什么的都配置一样。大部分情况下如果写入的居多,访问量并不多,那么就不要打开,例如社交网站的,10%的人产生内容,其余的90%都在消费,打开还是效果很好的,但是你如果是qq消息,或者聊天,那就很要命。 第三个:小网站或者没有高并发的无所谓,高并发下,会看到 很多 qcache 锁 等待,所以一般高并发下,不建议打开query cache

    12、你是如何监控你们的数据库的?你们的慢日志都是怎么查询的?

    监控的工具有很多,例如zabbix,lepus,我这里用的是lepus

    13、你是否做过主从一致性校验,如果有,怎么做的,如果没有,你打算怎么做?

    主从一致性校验有多种工具 例如checksum、mysqldiff、pt-table-checksum等

    14、你们数据库是否支持emoji表情,如果不支持,如何操作?

    如果是utf8字符集的话,需要升级至utf8_mb4方可支持

    15、你是如何维护数据库的数据字典的?

    这个大家维护的方法都不同,我一般是直接在生产库进行注释,利用工具导出成excel方便流通。

    16、你们是否有开发规范,如果有,如何执行的

    有,开发规范网上有很多了,可以自己看看总结下

    17、表中有大字段X(例如:text类型),且字段X不会经常更新,以读为为主,请问

    (1)、您是选择拆成子表,还是继续放一起;

    (2)、写出您这样选择的理由。

    答:拆带来的问题:连接消耗 + 存储拆分空间;不拆可能带来的问题:查询性能;

    如果能容忍拆分带来的空间问题,拆的话最好和经常要查询的表的主键在物理结构上放置在一起(分区) 顺序IO,减少连接消耗,最后这是一个文本列再加上一个全文索引来尽量抵消连接消耗

    如果能容忍不拆分带来的查询性能损失的话:上面的方案在某个极致条件下肯定会出现问题,那么不拆就是最好的选择

    18、MySQL中InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?为什么是这样子的?

    答:InnoDB是基于索引来完成行锁

    例: select * from tab_with_index where id = 1 for update;

    for update 可以根据条件来完成行锁锁定,并且 id 是有索引键的列,

    如果 id 不是索引键那么InnoDB将完成表锁,,并发将无从谈起

    .

    19、如何从mysqldump产生的全库备份中只恢复某一个库、某一张表?

    答案见:https://suifu.blog.51cto.com/9167728/1830651

    20、开放性问题:据说是腾讯的

    一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录。

    1、如果A表TID是自增长,并且是连续的,B表的ID为索引

    select * from a,b where a.tid = b.id and a.tid>500000 limit 200;

    2、如果A表的TID不是连续的,那么就需要使用覆盖索引.TID要么是主键,要么是辅助索引,B表ID也需要有索引。

    select * from b , (select tid from a limit 50000,200) a where b.id = a .tid;

    21、Sql优化

    应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

    应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:

    select id from t where num is null

    用 exists 代替 in 是一个好的选择

    用Where子句替换HAVING 子句 因为HAVING 只会在检索出所有记录之后才对结果集进行过滤

    22、如果发现CPU,或者IO压力很大,怎么定位问题?

    答:
       1、首先我会用top命令和iostat命令,定位是什么进程在占用cpu和磁盘io; 
       2、如果是mysql的问题,我会登录到数据库,通过show full processlist命令,看现在数据库在执行什么sql语句,是否有语句长时间执行使数据库卡住;
       3、执行show innodb engine status命令,查看数据库是否有锁资源争用;
       4、查看mysql慢查询日志,看是否有慢sql;
       5、找到引起数据库占用资源高的语句,进行优化,该建索引的建索引,索引不合适的删索引,或者根据情况kill掉耗费资源的sql语句等

    展开全文
  • 关于 PHP 性能优化

    万次阅读 2016-12-15 09:23:17
    本文写的也是关于PHP性能优化方面的话题,虽然老生常谈,但还是以我的角度来一个总结或分享。 网上关于50条PHP优化的方法,除此之外从架构或环境方面的优化建议等,是非常有益的。下面讲讲我所关注的一些方法或建议...
  • 如何改善和优化ERP流程管理

    千次阅读 2008-11-27 19:01:00
    有很多人就会问了,ERP的流程优化做到什么样的阶段,才成功呢?个人认为,企业流程的改善是没有终点的,其是一个持续完善的过程。不过,从单个流程来看,其大致可以分为三个层次。 一、流程僵化阶段。 流程僵化阶段...
  • Oracle:SQL优化建议

    千次阅读 2018-06-14 13:49:34
    Oracle:SQL优化建议 下述为34条Oracle中SQL的优化建议,仅供参考。 (1)选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的...
  • 团队合作与流程优化 ——新产品研发项目的成功之路 作者:周小桥   作为一种创新活动,新产品研发能力一直被看作是企业乃至国家经济成功至关重要的因素,也是体现企业和国家核心竞争力的关键指标。企业通过新...
  • 一个完整的数据分析流程,应该包括以下几个方面建议收藏此图仔细阅读。 (注:图保存下来,查看更清晰) 作为数据分析师,无论最初的职业定位方向是技术还是业务,最终发到一定阶段后都会承担数据管理的角色...
  • uni app性能优化建议

    千次阅读 2020-03-21 09:22:42
    运行原理 逻辑层和视图层分离,且非H5端通信有折损 uni-app 在非H5端运行时,从架构上分为逻辑层和...逻辑层是运行在一个独立的jscore里的,它不依赖于本机的webview,所以一方面它没有浏览器兼容问题,可以在Andr...
  • 业务流程监控的几点建议

    千次阅读 2017-11-08 13:17:39
    业务流程成熟的一个重要标志是流程可以被准确的并且合适的检测与控制。当企业完成一个BPM项目后,后续有很多工作。其中一项长期的工作就是流程的监控。企业需要制定监控的范围,监控指标,监控的实施等工作。下面...
  • Web前端性能优化的10点建议

    千次阅读 2017-04-06 17:28:24
     一般说来Web前端指网站业务逻辑之前的部分,包括浏览器加载、网站视图模型、图片服务、CDN服务等,主要优化手段有优化浏览器访问、使用反向代理、CDN等。 1. 减少HTTP请求  在浏览器(客户端)和服务器发生通信时,...
  • 文章提供了一种设计良好的蓝牙连接(重连)的流程逻辑,可以极大的提高Android平台上蓝牙设备的连接成功率。
  • 在我之前的博文里,从面试官的角度聊聊培训班对程序员的帮助,同时给培训班出身的程序员一些建议,我已经说明了,我对培训班候选人没有偏见,而且我的面试官同事大多也是这样认为的。在这篇文章里,我将直接从筛选...
  • 基于CUDA的GPU优化建议

    千次阅读 2014-03-31 08:59:06
    可以从硬件和软件两个方面进行优化:硬件方面:动态 warp 形成技术(提供有限的线程重组);动态 warp 子划分,让不同分支的线程重叠执行,意在减小这些分支对性能的影响;软件方面:线程重新组织技术,减少分支;...
  • H5性能测试(优化建议

    千次阅读 2018-01-12 10:36:21
    优化建议是对整个测试结果的一个反馈,也需要结合上述测试的结果,并对结果做一个中肯的评估,所以,这里也对三类数据分别作了优化建议: (1)http资源类优化建议:资源数量大、请求数过多、缓存等; ...
  • 一些Unity 优化建议 整理(为自己)

    千次阅读 2016-07-13 16:08:53
    1、 由于实时对战游戏的数据包数量巨大,早期版本的帧同步策略会导致比较明显的卡顿,通过进行数据包的合并与优化逐渐解决了卡顿问题; 2、 频繁创建和销毁的小兵对象让CPU爆表了,大量的小兵如果采用实时内存的分配...
  • 邀请爱图腾技术副总黄之豪将从先期APP需求调研以及报价原则、APP UE/UI设计流程、APP开发流程计划以及项目实施管理、APP测试标准流程以及相关工具、APP持续集成以及多渠道提交、产品后续迭代等方面与各位分享爱图腾...
  • Android性能优化(4):UI渲染机制以及优化

    千次阅读 多人点赞 2019-11-20 09:38:34
    渲染优化方式2.1 过度绘制优化2.1.1 Show GPU overdraw2.1.2 Profile GPU Rendering2.2 卡顿优化2.2.1 SysTrace2.2.2 TraceView 在从Android 6.0源码的角度剖析View的绘制原理一文中,我们了解到View的绘制流程有...
  • TEB轨迹优化算法-代码解析与参数建议

    千次阅读 多人点赞 2020-03-06 11:41:50
    TEB算法总结 1. 简介 ​ “TEB”全称Time ...在轨迹优化过程中,该算法拥有多种优化目标,包括但不限于:整体路径长度、轨迹运行时间、与障碍物的距离、通过中间路径点以及机器人动力学、运动学以及几何约束的符...
  • (部分内容,框架性的是我已经打好的了) 今晚讲的,主要三方面。虽然之前预告是两方面,但是我想把最重要的那点先讲,也就是思路。 前段时间我的SEO资料站被降权后,我在网站标题里加了一句“SEO最重要的是思路与...
  • 【IPD流程学习 二】IPD主要流程

    千次阅读 2020-02-13 17:52:26
    上一篇博客详细论述了产品开发过程中遇到的问题,看来不光是我自己感受到了,其实大家都有那种很累但是又没产出的感觉,是整体的流程机制出了问题,所以才要搞流程变革,而其中和我们开发人员最密切相关的就是IPD...
  • 有哪些让程序员受益终生的建议

    万次阅读 多人点赞 2019-10-28 07:11:59
    相比面试流程,我当然更相信处了近十年的同学。 在计算机领域有两个方法提升名气: (1)、Github提交MergeRequest,自造轮子 在所有的技术面试环节,github所提交的开源项目,是一个非常能展示实力的存在...
  • 本文主要讲解性能优化中的内存优化,希望你们会喜欢 目录 1. 定义 优化处理 应用程序的内存使用、空间占用 2. 作用 避免因不正确使用内存 &amp; 缺乏管理,从而出现 内存泄露(ML)、内存...
  • 大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才感觉运行速度稍微提高了点,就算手机在...
  • iOS-性能优化的那些事

    千次阅读 多人点赞 2019-05-22 23:18:12
    而且APP性能的优化也不是一朝一夕的事情,在此离别之际,我将详细说明讲解一下我在三年里对APP性能优化方面做过的一些事,大家仁者见仁智者见智,也欢迎大家进群提供宝贵的意见和建议! 这里我...
  • 如何优化MySQL千万级大表,我写了6000字的解读

    万次阅读 多人点赞 2019-10-21 20:03:03
    千万级大表如何优化,这是一个很有技术含量的问题,通常我们的直觉思维都会跳转到拆分或者数据分区,在此我想做一些补充和梳理,想和大家做一些这方面的经验总结,也欢迎大家提出建议。 从一开始脑海里开始也是...
  • 最近有一些刚入行的学妹过来问我,如何才能成为一名合格的设计师,我想...3.设计过程中结合需求,合理优化设计 4.保持有效沟通,输出并跟进设计实现   首先我们要清楚视觉设计在整个产品中的作用和目的是什么,
  • 流程梳理

    万次阅读 2014-04-15 11:06:43
    流程梳理很多CIO和我联系希望我讲讲流程管理、流程和IT结合的事。因为CIO们在推进IT项目时候,不理解业务流程、企业业务流程不清晰、业务流程和IT功能怎么结合使用,这些问题给IT项目的推进带来了很大的阻碍,所以...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 96,372
精华内容 38,548
关键字:

关于流程优化方面的建议