• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Speed of Quartz (was: optimizing compilers)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Speed of Quartz (was: optimizing compilers)


  • Subject: Re: Speed of Quartz (was: optimizing compilers)
  • From: email@hidden
  • Date: Mon, 4 Feb 2002 20:09:27 -0800

On Monday, February 4, 2002, at 02:21 PM, Erik M. Buck wrote:

On Monday, February 4, 2002, at 11:14 AM, Erik M. Buck wrote:
<a great analysis of long paths taking a long time to render in quartz>

I did my own benchmarks and actually found that the pixel rate for drawing individual line segments (via [NSBezierPath strokeLineFromPoint:toPoint]) was nearly 60 times faster for 500 lines approximately 200 pixels long, with randomly chosen endpoints. I got around 8.6Kpix/sec stroking the full path and around 500Kpix/sec drawing each line segment by itself.

But, this simply isn't an apples to apples comparison. Think about the work that must be done to correctly render a path that has 500 overlapping, anti-aliased, joined, semi-transparent line segments. There are thousands of overlapped lines... probably tens of thousands of intersections... it can't simply render each line in sequence... it has to compute the WHOLE path as a single polygon, otherwise the points that overlapped would get darker each time they crossed... not to mention computing the joins and not having them cause funny rendering... It's miraculous that they end up rendering the correct picture when it eventually finishes... (some 11 seconds later for 500 lines)

It's a hard problem... I don't think you're going to find that the Apple engineers are just slackers and chose a bone-headed O(N*N) algorithm because they aren't smart enough to do better.

Note that if you turn off Anti-aliasing, the full path case improves tremendously... since the algorithm is much simpler.

Here's the data I got (in thousands of pixels per second)
AA no-AA
full path 9 295
segments 500 820

i just did a comparison to x11 running on the same hardware... x11 fills 6.7 million pixels a second drawing 100 pixel long lines, no anti-aliasing, no alpha... so around 8X faster than quartz in the same mode. (note 500 pixel lines in x11 are filled at an astounding 32 million pixels per second!)

Just getting carried away now, I added a simple rect fill test... x11 gets around 40mm pix/sec and quartz (via NSRectFill) gets 63mm pix/sec... so the performance deficit isn't global.

It would be good if someone had the time to port x11perf in its entirety to quartz.

Here's a view you can test this with... really shows the difference between what the two methods have to do.

throw this code in as a custom view class... hook up in IB three checkboxes, one to set/unset antialiasing (target setAA:), one to switch between line segments and the whole path (target setEach:), and another to toggle between 0.1 and 1.0 transparency... you can throw a button in that targets go: to cause the view to redisplay/retime. add a textField and hook it up to results outlet to get the timing results displayed.

I put the project on my iDisk

http://homepage.mac.com/tom_waters/.cv/tom_waters/Public/QuartzBench.tar.gz-binhex.
hqx


#import <AppKit/AppKit.h>

@interface BenchView : NSView {
long pix;
int n;
NSPoint *points;
NSBezierPath *path;
BOOL aa;
BOOL each;
float alpha;
IBOutlet id results;
}
@end
@implementation BenchView

- (void)dealloc
{
NSZoneFree(NSDefaultMallocZone(), points);
[path release];
}

- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
int i;
n = 501;
pix = 0;
path = [[NSBezierPath bezierPath] retain];
[path setLineJoinStyle:NSBevelLineJoinStyle];
points = NSZoneMalloc(NSDefaultMallocZone(), n * sizeof(NSPoint));
for (i = 0; i < n; i++) {
float x = frame.size.width * random() / (float)0x7fffffff;
float y = frame.size.height * random() / (float)0x7fffffff;
points[i] = NSMakePoint(x, y);
if (i > 0) {
NSPoint p = points[i-1];
pix += sqrt((x-p.x)*(x-p.x)+ (y-p.y)*(y-p.y));
[path lineToPoint:points[i]];
} else {
[path moveToPoint:points[0]];
}
}
each = NO;
aa = NO;
alpha = 1.0;
NSLog(@"lines are %d long on average", pix / (n-1));
[NSBezierPath setDefaultLineWidth:0.0];
}
return self;
}

- (IBAction)go:(id)sender
{
[self setNeedsDisplay:YES];
}

- (IBAction)setEach:(id)sender
{
each = [sender intValue];
[self setNeedsDisplay:YES];
}

- (IBAction)setAA:(id)sender
{
aa = [sender intValue];
[self setNeedsDisplay:YES];
}

- (IBAction)setAlpha:(id)sender
{
alpha = [sender intValue] ? 0.1 : 1.0;
[self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)rect {
NSDate *start;
NSTimeInterval drawTime;
int i;

[[NSGraphicsContext currentContext] setShouldAntialias:aa];
[[NSColor whiteColor] set];
NSRectFill(rect);
[[[NSColor blackColor]colorWithAlphaComponent:alpha] set];
start = [NSDate date];
if (each) {
for (i = 0; i < n-1; i++) {
[NSBezierPath strokeLineFromPoint:points[i] toPoint:points[i+1]];
}
} else {
[path stroke];
}
drawTime = -[start timeIntervalSinceNow];
[results setStringValue:[NSString stringWithFormat:@"%g (%g kpix/sec)", drawTime, pix/drawTime/1000]];
}

@end


  • Follow-Ups:
    • Re: Speed of Quartz (was: optimizing compilers)
      • From: "Sven-S. Porst" <email@hidden>
    • Re: Speed of Quartz (was: optimizing compilers)
      • From: email@hidden
References: 
 >Re: Speed of Quartz (was: optimizing compilers) (From: "Erik M. Buck" <email@hidden>)

  • Prev by Date: Re: Mach-O Speed ?!?!?!?!?
  • Next by Date: Re: Microseconds and Carbon
  • Previous by thread: Re: Speed of Quartz (was: optimizing compilers)
  • Next by thread: Re: Speed of Quartz (was: optimizing compilers)
  • Index(es):
    • Date
    • Thread