直播APP的性能优化-礼物篇

作者: 落影loyinglin | 来源:发表于2016-07-24 15:39 被阅读10148次

    介绍

    记录、总结开发遇到一些问题,大家一起交流学习。
    这次带来,对直播APP性能优化的总结,以QA的形式总结。

    欢迎关注文集-直播Live

    实现方式

    1、Q:礼物动画如何实现?

    A:礼物分小礼物动画和豪华礼物处理;
    序列帧+GCD+layer动画+UIView的Block动画组合使用;

    2、Q:定时器采用CADisplayLink还是NSTimer?

    A:都可以。重点在于添加到的mode,个人采用的是添加到NSRunLoopCommonModes的CADisplayLink。

    3、Q:CADisplayLink对应的屏幕刷新和Xcode的FPS是什么关系?

    A:CADisplayLink对应的是屏幕刷新帧率,一般60FPS;
    xcode的FPS是真实显示的帧率,只要一帧处理的时间超过16ms,显示帧率就不会为60FPS;

    4、Q:小礼物的连击效果如何实现?

    A:逻辑上,礼物连击可以看成多个桶排成的队列,礼物赠送者id+礼物类型相同的放在一个桶内。连击过程中,可以不断往桶里放礼物。如果连击完成,桶里没有礼物,开始放下一个桶的礼物。
    实现上,给礼物数字放大缩小动画设置delegate,在stop回调的时候进行上述的逻辑判断即可。

    5、Q:小礼物的连击数字是[0-9]的文字图片组成的,每次显示都需要拼接图片,如何优化?

    A:用富文本的格式,同时图片用imageNamed的形式加载;如果内存不紧张,可以把富文本根据num缓存,避免多次拼接;

        NSMutableAttributedString * mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:sendGiftNumStr];
        UIImage *giftNumIcon = [UIImage imageNamed:imageName];
        NSTextAttachment *giftXAttachment = [[NSTextAttachment alloc] init];
        giftXAttachment.image = giftNumIcon;
        NSAttributedString *giftXAttributedString = [NSAttributedString attributedStringWithAttachment:giftXAttachment];
        [mutableAttributedString replaceCharactersInRange:NSMakeRange(0, 1) withAttributedString:giftXAttributedString];
    

    图片加载

    1、Q:加载图片iPhone4+iOS7,加载图片,提示:

    Could not load the "gift_plane" image referenced from a nib in the bundle with identifier
    Unable to create unsliced image from csi bitmap data
    Unsupported pixel format in CSI

    A:把Images.xcassets里面的jpg相关的图片换成png。
    The issue is that iOS 7 apps cannot have JPEG images in the CAR file. actool should have copied the JPEG as a loose image into your app's folder. To work around this issue, you should either convert the image to a PNG or include the JPEG as a resource outside of the asset catalog.

    2、Q:直接以引用方式导入的图片,pathForRes查找图片的路径?

    A:方式1
    [UIImage imageNamed:imagePath]imagePath为图片的相对路径;
    方式2:

    imagePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:imageName];
    [UIImage imageWithContentsOfFile:imagePath];
    

    imagePath为图片的相对路径,而且必须附带.png的后缀;

    3、Q:imageWithContentsOfFile加载的图片没有缓存,重复使用的时候会加载多次,是否可以用NSMutableArray存储起来?

    A:不行。可以使用NSCache,步骤如下:

    1、加载cache中的图片; 如果有则返回,没有到步骤2;
    2、加载本地的缓存文件,如果有则返回,没有到步骤3;
    3、从网络下载图片,到步骤4;
    4、存入本地的缓存文件,到步骤5;
    5、放入cache,返回图片;
    

    如果不需要网络下载图片,可以去除3、4步骤,同时可以同步返回;

    如果使用array存储图片,会一直持有引用;NSCache会在内存不足时主动释放,故而加载的时候需先判断是否有缓存文件;

    4、Q:使用序列帧的时候,需要加载很多次图片?

    A:可以把多张图片放到一张图片,加载后通过-CGImageCreateWithImageInRect切割出多张图片;

    内存优化

    1、Q:直播的时候送出一个豪华礼物,为何内存会增加20M?

    A:一个豪华礼物占用的内存包括图片内存+Animation(动画)内存;

    2、Q:美术给出的资源总共加起来才几百k的大小,为何加载到内存会增加这么多?

    A:先查看加载方式,+imageNamed:的方式会添加缓存,但使用完不释放;+imageWithContentsOfFile:的方式不会添加缓存,重复使用会占用多次内存,但使用完会回收;
    其次,通过instruments工具查看,imageio_png_data占用内存过多;查看ipa包的图片资源,发现有三张图片分别为(3910528 + 1761437 + 9104388),大小占用450k;简单计算下,(3910528 + 1761437 + 9104388) * 4 = 25M,确定为三张图片过大;

    3、Q:如何计算出来的图片大小?

    A:图片的颜色空间为RGBA,那么加载到内存的大小=widthheight4bytes;

    性能检测工具

    1、Q:instruments录制按钮显示unable to find a service to record with

    A:检查xcode版本能支持的最大手机版本,没问题的话重启手机和xcode,重新连接。

    2、Q:instruments的Anonymous VM(匿名虚拟内存)是什么?

    A:匿名虚拟内存是系统为程序预留的、可能会立即被重复使用的一部分可用内存。

    3、Q:instruments检查发现除了礼物送频繁后,聊天的UITableView消耗的时间也很长,如何优化?

    A:从cell高度计算、图片加载、布局layout开始优化;
    a.cell高度不会变,可以缓存;
    b.图片加载可以用imageNamed或者cache实现;
    c.尽量避免使用autolayout;
    d.控制每帧刷新数量;
    e.删除过多的历史消息;

    总结

    优化通过压力测试+instruments工具检测出瓶颈,同时检测代码逻辑实现。这些QA都是优化过程中的一些问题和解决方案,如果有建议和疑问欢迎交流。

    相关文章

      网友评论

      • 暖风惜人:有demo嘛
      • 刘宇航iOS:那种送礼物放在脸上的是什么原理求教
        落影loyinglin:@番茄鸡蛋汤圆 可以的。具体可以看看我gl系列的文章
        番茄鸡蛋汤圆:@落影loyinglin 你好,请问这是在采集端和播放端分别做识别并贴图吗?有没有办法能够只在采集端做识别并贴图,然后把贴图写入视频流一并推到服务器。这样播放端就不用再贴图,并且以后看回放的话也能看到当时的这个贴图。
        落影loyinglin:@LYHNevergiveup 人间识别sdk返回一个矩形,在上面贴图
      • 携一两本单色书来:大神,求个demo
      • 暖风惜人:你的git地址有demo嘛,来一发地址
      • 一雨惊尘:最近在做直播项目 看了你的文章 真的很不错 学到了很多
      • 暖风惜人:大神,最近让搞直播的项目,里面突然有很多的礼物动画,是设计看其他的APP决定的,希望能有好的demo可以看,时间紧任务重。
      • Bastionhh:希望有个demo 感谢:smile:
        落影loyinglin:@Bastionhh 有的,等我忙完这阵子。
      • 97341aaa1917:大神 demo 什么时候能上?:pray:
        Bastionhh:希望有个demo 感谢:smile:
        落影loyinglin:@落叶有殇 最近这周忙
      • e1d94c4636d7:一年没搞,感觉已废...林大强如斯
      • 3898f3a07b42:大神 给个demo吧
        暖风惜人:@落影loyinglin 豪华礼物的demo有吗
        hello_kity:@落影loyinglin 大神 豪华礼物的demo做了吗 想参考一下
        落影loyinglin:@泪痕46 正在准备豪华礼物的demo。
      • 火星哒哒007:请问,那个礼物选择界面是怎样搭建的?
        落影loyinglin:@火星哒哒007 工厂模式
        火星哒哒007:@落影loyinglin 谢谢回答,我用的collectionview实现了横向滚动,但是有个问题,我写了差不多十个动画,选择一个动画相当于点击了一次cell,然后响应动画显示,这样我就得写十个判断来根据礼物id执行相应的动画,感觉这样好笨,该怎么实现更合理呢?
        落影loyinglin:@火星哒哒007 用srcollview或者collectionview都可以。
      • angelababa:关于UITableView的优化,想请教一下。
        1.如何控制每帧刷新的数量
        2.我发现tableview消耗cpu的一个操作是scrolltobottom,因为每收到一条消息的时候,默认是reloadData 再 滚动到底部。
        落影loyinglin:@angelababa 对,这是客户端能做。还有一种方案是房间里面划分多个小房间,消息分级等
        angelababa:@落影loyinglin 感觉这两个问题其实都可以用CADisplayLink解决,比如可以CADisplayLink设置frameInterval为3,假设是60fps,也就是2/60 秒去队列里面聚合处理消息。可以这样理解吗
        落影loyinglin:@angelababa 问题1,消息队列配合displaylink。问题2,你可以一次性加载多条消息再reload。
      • akali:为什么要用CGImageCreateWithImageInRect?切割成多张图片,切割图片不消耗性能吗
        落影loyinglin:@akali 切30张出来是要切30次,我的意思是不会每次都切
        akali:@落影loyinglin 如果是30帧的动画,放到一张图片上,为什么切割只会进行一次,没理解
        落影loyinglin:@akali 因为为了方便加载和压缩空间,一张图片包括了多个图片资源;切割只会进行一次;
      • leetb:大神,能否指点小礼物连击这块
        leetb:@落影loyinglin 感谢 :+1:
        落影loyinglin:@leetb 一个队列,每次收到礼物先判断是否为当然播放的小礼物,是就连着放,不是就放队列。小礼物连击结束,就自动到队列取下一个
      • 温开水哈:有所收获
      • Shelin:直播中一些特别炫酷的动画大都是关键帧实现的吗
        angelababa:@落影loyinglin 但是想要做成礼物动态化,基本到最后都是用帧动画
        落影loyinglin:@Shelin 帧动画是最后的解决方案。配合代码可以做出非常酷炫的动画,只要几张图。
        angelababa:@Shelin iOS 不用关键帧
      • 37507d3afaf0:赞一个

      本文标题:直播APP的性能优化-礼物篇

      本文链接:https://www.haomeiwen.com/subject/onwwjttx.html