草庐IT

performance - drawRect 性能

coder 2023-09-24 原文

我需要在 iPad 上绘制 50 万到一百万个多边形。经过实验,如果那样的话,我只能得到 1 fps。这只是一个例子,我的真实代码有一些大小合适的多边形。

这里有几个问题:

  1. 为什么我不必将 Quartz 框架添加到我的项目中?
  2. 如果许多多边形重复,我能否利用 View 或它们是否太重等?
  3. 任何替代方案,QTPaint 都可以处理这个问题,但会占用 gpu。有QT或者ios之类的吗?
  4. Opengl 可以提高这种类型的 2d 性能吗?

示例 drawrect:

//X Y Array of boxes

- (void)drawRect:(CGRect)rect
{
    int reset = [self pan].x;
    int markX = reset;
    int markY = [self pan].y;
    CGContextRef context = UIGraphicsGetCurrentContext();
    for(int i = 0; i < 1000; i++)//1,000,000
    {
        for(int j = 0; j < 1000; j++)
        {
            CGContextMoveToPoint(context, markX,  markY);
            CGContextAddLineToPoint(context, markX, markY + 10);
            CGContextAddLineToPoint(context, markX + 10, markY + 10);
            CGContextAddLineToPoint(context, markX + 10, markY);
            CGContextAddLineToPoint(context, markX, markY);
            CGContextStrokePath(context);
            markX+=12;
        }
        markY += 12;
        markX = reset;
    }

}

平移只是用平移手势在屏幕上四处移动方框阵列。任何帮助或提示将不胜感激。

最佳答案

你的例子的关键问题是它没有优化。每当调用 drawRect: 时,设备都会渲染所有 1,000,000 个正方形。更糟糕的是,它在循环中对这些 API 进行了 6,000,000 次调用。如果您想以适度的 30fps 刷新此 View ,即每秒调用 180,000,000 次。

对于您的“简单”示例,绘图区域的大小为 12,000px × 12,000px;您可以在 iPad 显示屏上显示的最大区域为 768×1024(假设全屏纵向)。因此,代码在可见区域 之外绘制时浪费了大量 CPU 资源。 UIKit 有一些方法可以相对轻松地处理这种情况。

当管理明显大于可见区域的内容时,您应该将绘制限制在可见区域。 UIKit 有几种处理方法; UIScrollView 与由 CATiledLayer 支持的 View 相结合是您最好的选择。

步骤:

免责声明:这是对您上面的示例代码的特别优化

  • 创建一个新的View Based Application iPad 项目
  • 添加对 QuartzCore.framework 的引用
  • 创建一个新类,比如 MyLargeView,它是 UIView 的子类,并添加以下代码:

:

#import <QuartzCore/QuartzCore.h>

@implementation MyLargeView
- (void)awakeFromNib {
    CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
    tiledLayer.tileSize = CGSizeMake(512.0f, 512.0f);
}

// Set the layer's class to be CATiledLayer.
+ (Class)layerClass {
    return [CATiledLayer class];
}

- (void)drawRect:(CGRect)rect {
    // Drawing code
    // only draws what is specified by the rect parameter

    CGContextRef context = UIGraphicsGetCurrentContext();

    // set up some constants for the objects being drawn        
    const CGFloat width  = 10.0f;           // width of rect
    const CGFloat height = 10.0f;           // height of rect
    const CGFloat xSpace = 4.0f;            // space between cells (horizontal)
    const CGFloat ySpace = 4.0f;            // space between cells (vertical)
    const CGFloat tWidth = width + xSpace;  // total width of cell
    const CGFloat tHeight = height + ySpace;// total height of cell

    CGFloat xStart = floorf(rect.origin.x / tWidth);     // first visible cell (column)
    CGFloat yStart = floorf(rect.origin.y / tHeight);    // first visible cell (row)
    CGFloat xCells = rect.size.width / tWidth + 1;       // number of horizontal visible cells
    CGFloat yCells = rect.size.height / tHeight + 1;     // number of vertical visible cells

    for(int x = xStart; x < (xStart + xCells); x++) {
        for(int y = yStart; y < (yStart + yCells); y++) {
            CGFloat xpos = x*tWidth;
            CGFloat ypos = y*tHeight;

            CGContextMoveToPoint(context, xpos,  ypos);
            CGContextAddLineToPoint(context, xpos, ypos + height);
            CGContextAddLineToPoint(context, xpos + width, ypos + height);
            CGContextAddLineToPoint(context, xpos + width, ypos);
            CGContextAddLineToPoint(context, xpos, ypos);
            CGContextStrokePath(context);
        }
    }
}


@end
  • 编辑 View Controller nib 并将 UIScrollView 添加到 View
  • 向 UIScrollView 添加一个 UIView 并确保它填充 UIScrollView
  • 将类更改为 MyLargeView
  • 将 MyLargeView 的框架大小设置为 12,000×12,000
  • 最后,打开 View Controller .m 文件并添加以下覆盖:

:

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    UIScrollView *scrollView = [self.view.subviews objectAtIndex:0];
    scrollView.contentSize = CGSizeMake(12000, 12000);
}

如果您查看 drawRect: 调用,它只会绘制到 rect 参数指定的区域,这将对应于图 block 大小 (512×512 ) 对于我们在 awakeFromNib 方法中配置的 CATiledLayer。这将缩放到 1,000,000×1,000,000 像素的 Canvas 。

要查看的替代方案是 ScrollViewSuite example ,特别是 3_Tiling

关于performance - drawRect 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6069104/

有关performance - drawRect 性能的更多相关文章

  1. ruby-on-rails - Resque - 类的未定义方法 'perform' - 2

    我目前对后台队列不太满意。我正在尝试让Resque工作。我已经安装了redis和Resquegem。Redis正在运行。一个worker正在运行(rakeresque:workQUEUE=simple)。使用Web界面,我可以看到工作人员正在运行并等待工作。当我运行“rakeget_updates”时,作业已排队但失败了。我已经用defself.perform和defperform试过了。发条.raketask:get_updates=>:environmentdoResque.enqueue(GetUpdates)end类文件(app/workers/get_updates.rb)c

  2. Ruby 的数字方法性能 - 2

    我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

  3. ruby - Ruby 性能中的计时器 - 2

    我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

  4. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

  5. ruby - 如何找到我的 Ruby 应用程序中的性能瓶颈? - 2

    我编写了一个Ruby应用程序,它可以解析来自不同格式html、xml和csv文件的源中的大量数据。我如何找出代码的哪些区域花费的时间最长?有没有关于如何提高Ruby应用程序性能的好资源?或者您是否有任何始终遵循的性能编码标准?例如,你总是用加入你的字符串吗?output=String.newoutput或者你会使用output="#{part_one}#{part_two}\n" 最佳答案 好吧,有一些众所周知的做法,例如字符串连接比“#{value}”慢得多,但是为了找出您的脚本在哪里消耗了大部分时间或比所需时间更多,您需要进行分

  6. STM32的HAL和LL库区别和性能对比 - 2

    LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L

  7. ruby - GC.disable 的任何性能缺点? - 2

    是否存在GC.disable会降低性能的情况?只要我使用的是真正的RAM而不是交换内存,就可以这样做吗?我正在使用MRIRuby2.0,据我所知,它是64位的,并且使用的是64位的Ubuntu:ruby2.0.0p0(2013-02-24revision39474)[x86_64-linux]Linux[redacted]3.2.0-43-generic#68-UbuntuSMPWedMay1503:33:33UTC2013x86_64x86_64x86_64GNU/Linux 最佳答案 GC.disable将禁用垃圾回收。像rub

  8. ruby-on-rails - Rails with angular 与 Rails pure(查看性能) - 2

    我尝试在Internet上搜索有关使用angularJS进入RubyonRails项目与RubyonRailspure的View性能的信息。我的问题是因为2个月前我开始使用纯AngularJS,现在我需要将AngularJS集成到一个新项目中,但需要展示使用带有RubyonRails的AngularJS呈现View的性能如何,并消除对RubyonRails的负担.例如:带Rails的Angular:使用RubyonRails获取数据(从数据库或GET请求),将信息发送到file.js.erb并使用AngularJS操作数据并显示带有解析数据的View。纯粹的Rails:(自然流程)使用

  9. ruby-on-rails - 在 Rails 3 应用程序中使用 require_dependency 对性能有何影响? - 2

    我觉得我理解require和require_dependency之间的区别(来自Howarerequire,require_dependencyandconstantsreloadingrelatedinRails?)。但是,我想知道如果我使用一些不同的方法(参见http://hemju.com/2010/09/22/rails-3-quicktip-autoload-lib-directory-including-all-subdirectories/和Bestwaytoloadmodule/classfromlibfolderinRails3?)来加载所有文件会发生什么,所以我们:

  10. arrays - Ruby 中的并行分配性能 - 2

    设置一个临时变量来交换数组中的两个元素似乎比使用并行赋值更有效。谁能帮忙解释下?require"benchmark"Benchmark.bmdo|b|b.reportdo40000000.times{array[1],array[2]=array[2],array[1]}endendBenchmark.bmdo|b|b.reportdo40000000.timesdot=array[1]array[1]=array[2]array[2]=tendendend结果:usersystemtotalreal4.4700000.0200004.490000(4.510368)usersyste

随机推荐