From f8304a59f3b8d4f2620b626af03cdb23af88fded Mon Sep 17 00:00:00 2001 From: Carl Worth <cworth@cworth.org> Date: Tue, 15 Jul 2008 15:21:28 -0700 Subject: [PATCH] Add New Job Old Tricks post --- src/exa/i965/new_job_old_tricks.mdwn | 118 ++++++++++++++++++ .../new_job_old_tricks/vertex_buffers.png | Bin 0 -> 14350 bytes 2 files changed, 118 insertions(+) create mode 100644 src/exa/i965/new_job_old_tricks.mdwn create mode 100644 src/exa/i965/new_job_old_tricks/vertex_buffers.png diff --git a/src/exa/i965/new_job_old_tricks.mdwn b/src/exa/i965/new_job_old_tricks.mdwn new file mode 100644 index 0000000..5b3c99b --- /dev/null +++ b/src/exa/i965/new_job_old_tricks.mdwn @@ -0,0 +1,118 @@ +[[meta title="A new job, but old performance fixes"]] + +[[tag exa performance i965]] + +Many readers have heard already, but it will be news to some that I +recently changed jobs. After just short of 4 years with Red Hat, I've +now taken a job working for Intel, (in its Open-source Technology +Center). It was hard to leave Red Hat---I have only fond memories of +working there, and I will always be grateful to Red Hat for first +helping me launch a career out of working on Free Software. + +Fortunately, as far as my free-software work is concerned, much of it +will be unaffected by the job change. In fact, since I've been looking +at X/2D/Intel driver graphics performance for the last year already, +this job change should only help me do *much* *more* of that. And as +far as [cairo](http://cairographics.org) goes, I'll continue to +maintain it, but I haven't been doing much feature development there +lately anyway. Instead, the most important thing I feel I could do for +cairo now is to continue to improve X 2D performance. And that's an +explicit job requirement in my new position. So I think the job change +will be neutral to positive for anyone interested in my free-software +efforts. + +As my first task at Intel, I took the nice HP 2510p laptop I was given +on the first day, (which has i965 graphics of course), installed Linux +on it, then compiled everything I needed for doing X development. I +would have saved myself some pain if I had used these [build +instructions](http://wiki.x.org/wiki/Development/git). I've since +repeated that exercise with the instructions, and they work quite +well, (though one can save some work by using distribution-provided +development packages for many of the dependencies). + +Also, since I want to do development with +[GEM](http://lwn.net/Articles/283793/), I built the drm-gem branches +of the mesa, drm, and xf86-video-intel modules. That's as simple as +doing "git checkout -b drm-gem origin/drm-gem" after the "git clone" +of those three modules, (building the master branch of the xserver +module is just fine). That seemed to build and run, so I quickly +installed it as the X server I'm running regularly. I figured this +would be great motivation for myself to fix any bugs I +encountered---since they'd impact everything I tried to do. + +Well, it didn't take long to find some performance bugs. Just +switching workspaces was a rather slow experience---I could literally +watch xchat repaint its window with a slow swipe. (Oddly enough, +gnome-terminal and iceweasel could redraw similarly-sized windows much +more quickly.) And it didn't take much investigation to find the +problem since it was something I had [found +before](http://cworth.org/exa/i965/synchronous_composite/), a big, +blocking call to i830WaitSync in every composite operation. My old +favorite, "x11perf -aa10text" was showing only 13,000 glyphs per +second. + +I had done some work to alleviate that before, and Dave Airlie had +continued that until the call was entirely eliminated at one +point. That happened on the old "intel-batchbuffer" branch of the +driver. Recall that in January Eric and I had been disappointed to +[report](http://cworth.org/talks/lca_2008/) that even after a recent +2x improvement, the intel-batchbuffer branch was only at 109,000 +glyphs per second compared to 186,000 for XAA. + +Well, that branch had about a dozen, large, unrelated changes in it, +and poor Eric Anholt had been stuck with the job of cleaning them up +and landing them independently to the master branch, (while also +writing a new memory manager and porting the driver to it). + +So here was one piece that just hadn't been finished yet. The driver +was still just using a single vertex buffer that it allocates +upfront---and a tiny buffer---just big enough for a single rectangle +for a single composite operation. And so the driver was waiting for +each composite operation to finish before reusing the bugger. And the +change to GEM had made this problem even more noticeable. And Eric +even had a partially-working patch to fix this---simply allocating a +much larger vertex buffer and only doing the sync when wrapping around +after filling it up. He had just been too busy with other things to +get back to this patch. So this was one of those times when it's great +to have a fresh new co-worker appear in the next cubicle asking how he +could help. I took tested Eric's patch, broke it up into tiny pieces +to test them independently, and Eric quickly found what was needed to +fix it, (an explicit flush to avoid the hardware caching vertex-buffer +entries that would be filled in on future composite calls). + +So, with that in place the only thing left to decide was how large of +a vertex buffer to allocate upfront. And that gives me an excuse to +put in a performance plot: + +[[img vertex_buffers.png]] + +So the more the better, (obviously), until we get to 256 composite +operations fitting into a single buffer. Then we start losing +performance. So on the drm-gem branch, this takes performance from +13,000 glyphs/second to 100,000 glyphs/second for a 7.7x +speedup. That's a nice improvement for a simple patch, even if the +overall performance isn't astounding yet. It is at least fast enough +that I can now switch workspaces without getting bored. + +So I went ahead and applied these patches to the master branch as +well. Interestingly, without any of the drm-gem branches, and even +with the i830WaitSync call on every composite operation, things were +already much better than in the GEM world. I measured 142,000 +glyphs/second before my patch, and 208,000 glyphs/second after the +patch. So only a 1.5x speedup there, but for the first time ever I'm +actually measuring EXA text rendering that's faster than XAA text +rendering. Hurrah! + +And really, this is still just getting started. The patch I've +described here is still just a bandaid. The real fix is to eliminate +the upfront allocation and reuse of buffers. Instead, now that we have +a real memory manager, (that's the whole point of GEM), we can +allocated buffer objects as needed for vertex buffer, (and for surface +state objects, etc.). That's the work I'll do next and it should let +us finally see some of the benefits of GEM. Or if not, it will point +out some of the remaining issues in GEM and we'll fix those right +up. Either way, performance should just keep getting better and +better. + +Stay tuned for more from me, and look forward to faster performance +from every Intel graphics driver release. diff --git a/src/exa/i965/new_job_old_tricks/vertex_buffers.png b/src/exa/i965/new_job_old_tricks/vertex_buffers.png new file mode 100644 index 0000000000000000000000000000000000000000..3f44cdb4176c2a08c837f86fc1e379e6112b802b GIT binary patch literal 14350 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 literal 0 HcmV?d00001 -- 2.45.2