初识性能优化

简介: 性能优化一词相信大家都经常听到,今天我们就简单的来认识以下性能优化,了解做性能优化的必要性以及优化的分类。

前置知识

  • 有Android开发基础

前言

性能优化一词相信大家都经常听到,今天我们就简单的来认识以下性能优化,了解做性能优化的必要性以及优化的分类。

为什么要进行性能优化

下图来自于 FaceBook,这是他们对 Android 性能以及用户日活跃度两个指标的统计。我们可以清晰的看到性能和用户日活是正相关的,软件的性能越好,那么表现出来的业务数据也会更好。所以说,我们技术上的指标提升,同时也会使得业务指标的提升,这是业务方面我们需要做性能优化的理由。

1.webp.jpg

而从另一个角度——硬件发展的角度来看,我们会发现当代的芯片的性能提升速度其实在是不断的下滑的。无论是 Intel 和 ADM 的x86架构的芯片,还是 ARM 的arm 架构的芯片,近年来都呈现放缓的趋势。

即使ARM平台由于其架构和工艺双重不断迭代的缘故,其性能在最近几年间提升的速度很快,最明显的表现就是我们一代代的手机的处理器之间增强的幅度很大,但是这也无法阻止技术变更的规律,它的优化幅度就是在不断的变弱,直到最后的挤牙膏。

当然多核技术也对芯片性能带来了优化,但是同时也对芯片大小和电池性能有限制,所以这项技术也是处于瓶颈了。

综上所述,从硬件发展的角度来看,硬件的发展逐渐趋于停止,我们需要做好软件的性能优化,才能在未来硬件发展停滞的时候,做好用户体验的提升。

1.webp.jpg

所以说,无论是从业务指标或者是硬件能力上来讲,我们去做好性能优化都是很必要的。

什么是性能优化

性能优化是什么?其实就是要实现三点:快、稳、省。

  • 何为快?
    快就是指,打开App时候很快、打开页面很快、播放视频音乐很快以及滑动得很顺畅。这些都被称之为快,核心要义是指:用户很快能接收到系统的回馈
  • 何为稳?
    稳的意思是,系统很稳定。软件不会出现异常的bug、不会闪退和ANR,这些都是稳的体现。
  • 何为省?
    省的意思是空间和数据的节省。具体体现为安装包的大小、安装后使用所占用的存储空间大小以及网络数据的读取量大小。把这些都给省下来就是省的要义。

基于以上的三点目标,我们其实可以将性能优化简单的分为以下四类

  1. 流畅性优化,响应快,流畅性高
  2. 资源优化,最小的负载带来最大的收益
  3. 稳定性优化,稳定的实现功能,减少不必要的打断
  4. 系统级优化,充分挖掘系统的资源,让APP在有限的资源内能够有更高的流畅性。(较难,较为底层)

上述四类优化在此暂不做详细阐述,上述的稳定性优化是等级最高的,上线之前必须排除所有已知的bug,这是众所周知的。而流畅性优化是较为常见的、开发者闷都会去完善的优化。下面我们就来举一些例子,看一下我们之前的哪些文章中提到的属于流畅性优化。

  • 隐性的滑动冲突
    与滑动冲突的首次邂逅一文中,我们提到了一个较为隐性的滑动冲突,就是下面左图中的上下滑动突变为左右滑动的问题。而解决之后,在同一方向任意滑动都不会出现滑动突变的问题了,这大大的提高了滑动的流畅性,同时也是实现了交互的稳定性。

image.png

  • 启动白屏
    我们知道,如果我们未对自己的项目的APP做白屏优化,那么在APP首次启动的时候,都会出现一个短暂的白屏。这是因为APP首次开启主进程,且通过各类初始化的时候,是需要一定的执行事件的,而这个执行时间就显现出来就是白屏效果。
    而一个没有实际画面的白屏,对于用户来说是一种卡顿、不流畅的体现,所以各大厂家会使用 APP 的 Logo 或者是其他动画形式的做一个启动页。将这种启动页代替白屏就可以在感器上减少卡顿感。
    下面展示我做的一个启动页效果,更详细的文章在极简抖音中的优化点


  • 启动速度优化
    上述的启动页是可以让用户减少卡顿感,但这终究是一个视觉上面的欺骗,但是在数据指标上面,我们的启动时间没有真的减少。对于小型APP来说,未优化的时候启动时间不会很长,但是对于大型APP来说,就会有很大的影响了,让用户等一个启动页等超过2s,用户也会觉得卡顿的。
    所以,我们需要做好启动优化。启动优化的点很多,但是总结为一点就是:减少不必要的初始化。我们可以对各进程做分类加载,把一些加载异步化等等。
    下面附上我做不同进程区别加载的操作,详细解释依旧在极简抖音中的优化点一文中。
public class App extends Application {
    private static Context context;
    private static String sCurProcessName = null;
    private String processName;
    private String packageName;
    /**
     * Set the base context for this ContextWrapper.  All calls will then be
     * delegated to the base context.  Throws
     * IllegalStateException if a base context has already been set.
     *
     * @param base The new base context for this wrapper.
     */
    @Override protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        processName = getCurProcessName(base);
        packageName = getPackageName();
    }
    private boolean isMainProcess() {
        return !TextUtils.isEmpty(packageName) && TextUtils.equals(packageName, processName);
    }
    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        if (isMainProcess()){
            MMKV.initialize(this);
            MMKV.mmkvWithID("MyID", MMKV.SINGLE_PROCESS_MODE, GlobalConstant.MMKV_KEY);
            //载入Dokit监测
            new DoKit.Builder(this)
                    .productId(context.getString(R.string.value_dokit_pid))
                    .build();
            //使用订阅索引,加快编译速度
            EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
            // 抖音授权
            String clientkey = context.getString(R.string.value_client_key);
            DouYinOpenApiFactory.init(new DouYinOpenConfig(clientkey));
            //初始化
            MyUtil.initialize(this);
            //设置UI工具
            RxTool.init(this);
            //网络缓存
            RetrofitCache.getInstance().init(this);
        }else {
            QbSdk.initX5Environment(getContext(), new QbSdk.PreInitCallback() {
                @Override
                public void onCoreInitFinished() {
                    // 内核初始化完成,可能为系统内核,也可能为系统内核
                }
                /**
                 * 预初始化结束
                 * 由于X5内核体积较大,需要依赖网络动态下发,所以当内核不存在的时候,默认会回调false,此时将会使用系统内核代替
                 * @param isX5 是否使用X5内核
                 */
                @Override
                public void onViewInitFinished(boolean isX5) {
                    LogUtil.i("是否使用腾讯内核:" + isX5);
                }
            });
        }
        //设置打印开关
        LogUtil.setIsLog(true);
        //注册Activity生命周期
        registerActivityLifecycleCallbacks(ActivityUtil.getActivityLifecycleCallbacks());
    }
    public static Context getContext() {
        return context;
    }
    private static String getCurProcessName(Context context) {
        ...
    }
    private static String getProcessName(int pid) {
        ...
    }
}
复制代码
  • 多进程预加载
    在Android里面,每打开一个进程就会默认去跑 Application 类,所以如果我们在使用的时候才去开启进程,就会使得页面首次开启的时候较为缓慢。为解决这个问题,我们可以让进程在后台预先开启,这样就能减少我们首次开启多进程功能的启动时间了。
    下面示例是后台启动多进程的代码,详情请参阅极简抖音中的优化点一文。
//在对应的生命周期启用即可
private void startHideService(){
    Intent intent = new Intent(this, PreLoadService.class);
    this.startService(intent);
}
private void stopHideService(){
    Intent intent = new Intent(this, PreLoadService.class);
    this.stopService(intent);
}
复制代码

上述这些都是我们有实现的流畅性优化点,它可以能让我们的APP使用体验更加的极致,同时也是对我们技术的考验。

相信大家学到这里,会了解到了为何需要性能优化且什么是性能优化了,今天的分享就到此结束

相关文章
|
6月前
|
SQL 缓存 Java
系统性能优化总结
系统性能优化总结
91 10
|
Web App开发 SQL 缓存
性能优化
性能优化 前言 以前写过一篇性能优化的笔记前端性能优化小结,那时候算是列了一些优化的点,最近又读了几篇性能优化相关的文章,加上自己动手做了一些实践,相比之前有了更深一点的理解
|
SQL 缓存 NoSQL
服务性能优化总结
服务性能优化总结
142 0
|
并行计算 程序员 Linux
C++服务性能优化的道与术-道篇:阿姆达尔定律
在之前的文章 《2004:当CPU温和地走入那个良夜》 中我讲到了2000年后摩尔定律的终结,CPU时钟频率定格,多核成为CPU发展的新方向,并行计算成为趋势。
258 0
C++服务性能优化的道与术-道篇:阿姆达尔定律
|
数据库 索引 存储