SDL中文论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 4043|回复: 0
打印 上一主题 下一主题

[Discuss] image::tblit的构造、复制效率

[复制链接]

149

主题

331

帖子

2445

积分

版主

Rank: 7Rank: 7Rank: 7

积分
2445
跳转到指定楼层
楼主
发表于 2016-7-22 10:19:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 ancientcc 于 2016-8-6 21:07 编辑

display渲染的一大任务是分层渲染(drawing_buffer_commit),分层渲染的单元是tblit。由于分层渲染单元很多,而且每次分层渲染都是要重新构造整个drawing_buffer_,这就让凸显一个问题,如果花在tblit的构造、复制时间较多,会影响app的整体效率。

tblit的效率到底是多少,让看一次运行实例,测试机是2015年出的Macbook proc。
测试时tblit中的loc类型是image::locator。

  1. void do_test()
  2. {
  3.         const int size = 1100;
  4.         image::get_image("misc/0.png");
  5.         image::tblit* blit_buf[size];
  6.         for (int loop = 0; loop < 5; loop ++) {
  7.                 std::vector<image::tblit> blits, blits2;
  8.                 uint32_t start_ticks = SDL_GetTicks();
  9.                 // blits.reserve(size);
  10.                 for (int i = 0; i < size; i ++) {
  11.                         blits.push_back(image::tblit("misc/0.png", image::UNSCALED));
  12.                 }
  13.                 uint32_t ticks1 = SDL_GetTicks();
  14.                 blits2 = blits;
  15.                 uint32_t ticks2 = SDL_GetTicks();

  16.                 for (int i = 0; i < size; i ++) {
  17.                         blit_buf[i] = new image::tblit("misc/0.png", image::UNSCALED);
  18.                 }
  19.                 uint32_t ticks3 = SDL_GetTicks();
  20.                 for (int i = 0; i < size; i ++) {
  21.                         delete blit_buf[i];
  22.                 }
  23.                 posix_print("#%i, tblit, push_back: %u, copy: %u, new: %u, delete %u\n", loop,
  24.                         ticks1 - start_ticks, ticks2 - ticks1, ticks3 - ticks2, SDL_GetTicks() - ticks3);

  25.                 start_ticks = SDL_GetTicks();
  26.                 std::vector<surface> surfs, surfs2;
  27.                 start_ticks = SDL_GetTicks();
  28.                 for (int i = 0; i < size; i ++) {
  29.                         surfs.push_back(image::get_image("misc/0.png"));
  30.                 }
  31.                 ticks1 = SDL_GetTicks();
  32.                 surfs2 = surfs;
  33.                 posix_print("#%i, surface, push_back: %u, copy: %u\n", loop, ticks1 - start_ticks, SDL_GetTicks() - ticks1);
  34.         }
  35. }
复制代码

输出

  1. #0, tblit, push_back: 3, copy: 1, new: 7, delete 5
  2. #0, surface, push_back: 1, copy: 0
  3. #1, tblit, push_back: 3, copy: 1, new: 7, delete 6
  4. #1, surface, push_back: 1, copy: 0
  5. #2, tblit, push_back: 3, copy: 0, new: 8, delete 5
  6. #2, surface, push_back: 2, copy: 0
  7. #3, tblit, push_back: 4, copy: 0, new: 8, delete 6
  8. #3, surface, push_back: 1, copy: 0
  9. #4, tblit, push_back: 3, copy: 0, new: 8, delete 5
  10. #4, surface, push_back: 2, copy: 0
复制代码

这就意味着,如果不作任何优化,要渲染1000个单元,那每次drawing_buffer_commit单单花在构造tblit上的时间就要3毫秒(如果image::locator中的modifications_不是空,那将消耗更多时间)。对app场景,一次要渲染1000个单元也是常见的事。

上面还计算了new、delete花费的时间。有人认为std::vector::push_back不得不存在复制构造操作,为提高效率想避免这个操作,于是用指针数组方法,像“image::tblit* buf[1000]”。但从以上结果看到,new、delete要比std::vector的复制构造多耗费时间。相比push_back,例子中new/delete多这么多,这当中有Debug原因,Release时会缩小差距,但相比push_back还是没优势。

如何提高image::tblit复制效率
  • image::tblit中的loc类型改为"image::locator*";
  • 给image::tblit::loc赋值时使用函数image::get_locator。
    1. std::set<locator> locators;
    2. const locator& get_locator(const locator& locator)
    3. {
    4.         std::set<image::locator>::const_iterator it = locators.find(locator);
    5.         if (it != locators.end()) {
    6.                 return *it;
    7.         }
    8.         std::pair<std::set<image::locator>::const_iterator, bool> res = locators.insert(locator);
    9.         return *res.first;
    10. }
    复制代码

  • app只会增加不会删除locators中单元,保证image::tblit中的loc一直有效。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|丽谷软件|libsdl.cn

GMT+8, 2025-5-2 00:41 , Processed in 0.044896 second(s), 19 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表