flutter疑难杂症之记一次release模式和debug模式的性能差距

最近遇到一个问题,来来回回花了好几天才解决,在此记录一下。

 

需求是这样的,项目中要用到图片播放,每秒钟大概有十几张图片展示,而图片的传输是通过原始的socket tcp传输的。

由于这些tcp流是服务器推送的,涉及到拆包和拼包,具体来说服务器可能一个tcp流包含多张图片,所以要对每张图片进行拆包,而它每个流可能不完整,需要等到下一次的流进行拼接然后再处理。

 

bug是我在调试的时候debug模式没有任何问题,图片播放流畅,当我发布版本测试的时候release模式下,图片的播放就开始卡顿了。

 

一脸懵逼,为啥release模式下性能反而更低呢?

 

后来仔细分析加日志发现一个大秘密:

release模式下socket.listen的ondata回调List数据是debug模式的三四倍,release模式下list的length平均为1800000,而debug模式下list的length最大不超过600000, 这样看起来release模式的性能还是会高很多。

 

但是问题来了,上文说过,业务涉及到拆包拼包,所以我对list进行了操作,sublist拆包,addAll拼包,在如此大的量级下,这两个api及其耗时,平均处理每张图片需要220多毫秒,因此会导致播放图片卡顿。而在debug模式下,由于报文比较少,这两个api相对没有那么耗时,所以处理的速度比较快,基本上包来了瞬间就拆分处理完了,因此才有一种debug版本性能反而比release版本性能高的假象。

 

既然问题的原因已经发现了,那么解决起来就比较简单了,不论什么模式,我只要将每个报文控制在一个合理的范围内,那么效率自然就高了。但是苦于没有找到像c语言那样设置tcp接收缓冲区大小的api,因此,我不得不对报文进行一个拆分处理,每个报文拆分成1024 * 256这么长的一小段(这个长度实验了好久,跟具体业务有关),用for循环去处理,运行发现图片在release模式下也能够流畅的运行了。。

 

为了更加直观的看到性能差距,我写了一个测试代码。

import 'package:flutter/material.dart';

class TestPage extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Container(child: FlatButton(onPressed: (){
      handleList();
      handleList2();
    }, child: Center(child: Text("onPress"),)), color: Colors.green,);
  }


  void handleList(){
    List list = createList(2000000);
    List lastRemain = List();
    int perLength = 100001;
    int count = 0;
    print("***************************************************");
    int startTime = DateTime.now().millisecondsSinceEpoch;
    lastRemain.addAll(list);
    while(true){
      if(lastRemain.length < perLength){
        break;
      }
      List cur = lastRemain.sublist(0, perLength);
      lastRemain = lastRemain.sublist(cur.length);
      count++;
    }
    print("count = $count  cost = ${DateTime.now().millisecondsSinceEpoch - startTime}");
  }

  void handleList2(){
    List list = createList(2000000);
    int length = list.length;
    List lastRemain = List();
    int segLength = 1024 * 256;
    int perLength = 100001;
    int count = 0;
    print("------------------------------------------");
    int startTime = DateTime.now().millisecondsSinceEpoch;
    for(int i = 0; i < length; i += segLength) {
      List seg = list.sublist(i, i+segLength>length?length:i+segLength);
      lastRemain.addAll(seg);
      while(true){
        if(lastRemain.length < perLength){
          break;
        }
        List cur = lastRemain.sublist(0, perLength);
        lastRemain = lastRemain.sublist(cur.length);
        count++;
      }
    }
    print("count = $count  cost = ${DateTime.now().millisecondsSinceEpoch - startTime}");
    print("***************************************************");
  }

  List createList(int n){
    List list = List();
    for(int i=0; i

代码比较简单,但是也能说明问题。handleList是我们直接处理大包,handleList2是我们将大包拆分为中包然后再处理,perLength 假设是每张图片的大小,我们的任务是每次得到一张图片,如果不足一张,那么留给下次拼包处理。

运行代码:

I/flutter (10901): ***************************************************
I/flutter (10901): count = 19  cost = 770
I/flutter (10901): ------------------------------------------
I/flutter (10901): count = 19  cost = 225
I/flutter (10901): ***************************************************
I/flutter (10901): ***************************************************
I/flutter (10901): count = 19  cost = 653
I/flutter (10901): ------------------------------------------
I/flutter (10901): count = 19  cost = 227
I/flutter (10901): ***************************************************
I/flutter (10901): ***************************************************
I/flutter (10901): count = 19  cost = 720
I/flutter (10901): ------------------------------------------
I/flutter (10901): count = 19  cost = 220
I/flutter (10901): ***************************************************

结果能够说明问题。

如果我们将原始报文增加到6000000会怎样呢?来看看结果吧:

I/flutter (14229): ***************************************************
I/flutter (14229): count = 59  cost = 6449
I/flutter (14229): ------------------------------------------
I/flutter (14229): count = 59  cost = 943
I/flutter (14229): ***************************************************
I/flutter (14229): ***************************************************
I/flutter (14229): count = 59  cost = 6283
I/flutter (14229): ------------------------------------------
I/flutter (14229): count = 59  cost = 932
I/flutter (14229): ***************************************************
I/flutter (14229): ***************************************************
I/flutter (14229): count = 59  cost = 6147
I/flutter (14229): ------------------------------------------
I/flutter (14229): count = 59  cost = 924
I/flutter (14229): ***************************************************

 

虽然这次的bug这样解决了,但是感觉flutter在某些情况下性能上还是会成为一个瓶颈,因为我在原生的ios上面没有发现这个bug。

 

flutter很好,路还很长,让我们一起奋斗前行!

 

 

你可能感兴趣的:(flutter)