Articles posted January 2007 Older >>

Benchmarking With 64 Bits

I've been wanting to do some more extensive benchmarking, and now that I have a modern machine, I figured it was a good time. Some interesting things I wanted to understand were:

Well, here are the results (yes, you'll probably want to click to see it right):

A few interesting observations from here:

The -mt switch definitely helps with benchmarks, no doubt about it! But benchmarks are testing an unrealistic scenario: running faster than the game should. It is worth point out that it does also help a little bit with games that have trouble pushing full frame rate, but only by about 5%. This makes sense, since there is a little bit to be gained just from avoiding the blit on the primary CPU.

Comparing gcc versus Visual Studio, I have to say Visual Studio definitely comes out on top pretty consistently. The biggest exceptions were Ridge Racer and Star Wars, which both took a 10% dive under MSVC. On the flip side, Primal Rage and Sexy Parodius were 20% faster under MSVC. (I sense R. Belmont's conflicting feelings over this result.) Interestingly, the gcc binary was about 1.5MB smaller than the MSVC binary with the same optimizations.

Link time code generation (enabled in MAME by setting MAXOPT=1 when building using the MSVC toolset) had only a minor performance benefit on average. And the benefit on the 64-bit builds was even less than that on the 32-bit builds. However, it did reduce the size of the 32-bit binary by about 5MB! And the 64-bit binary got 3.5MB smaller.

Finally, the 64-bit question: yes, absolutely, with the MSVC toolset, the 64-bit builds were consistently faster -- and in a few cases significantly faster -- than the 32-bit builds. There were a few black eyes for the 64-bit builds, but they are all cases where the lack of a MIPS recompiler for 64-bit put the games at a significant disadvantage. Killer Instinct in particular utterly crawls without the recompiler (they use a lot of lwl/lwr/swl/swr instructions which are worst case for the memory system). The Seattle and Vegas games, on the other hand, were slower, but not nearly as slow as I would have expected. Even with a super simple 64-bit drc, they should smoke the 32-bit versions. You'll also note that Raiden Fighters Jet crashes on the 64-bit builds -- guess we're not fully 64-bit clean yet!

One thing that seems pretty consistent is that the 64-bit builds do really well on games that do 3D rendering. I can only attribute this to having more registers to play with in the innermost rasterization loops. Ridge Racer was an impressive 50% faster in the 64-bit build. Radikal Bikers was 30% faster.

Solving the Windows Vista Build Issues

Finally! I've worked my way through the remining mingw build issues. Below is a summary of the issues and steps for working around all of them. Turns out only one of the bugs is an actual mingw bug. The rest have to do with other parts of the environment.

The first problem I encountered was that the built-in paths within the mingw environment were no longer working. This is an actual mingw bug that has been tracked down to a change in the way the Microsoft standard C libraries handle invalid parameters. Older versions of the DLL would not check invalid parameters and go down potentially untested code paths with them. The versions in Vista do stricter parameter checking. Some calls made by the mingw tools pass invalid parameters to one of the functions and fail, causing the internal paths to quit working.

The symptom of this problem is that you can't run gcc because it can't find some of its subcomponents in the internal paths. Furthermore, even if you work around that issue, gcc can't find the standard include paths when compiling, nor can it find the standard lib paths when linking. To fix this, I updated the MAME makefile a while back with some hacks, but it turns out that a simple environment variable change will solve the real problem. However, neither solution solves the search path problem, so you must also configure your PATH variable to include the mingw\libexec\gcc\mingw32\3.4.2 path in your build tools.

In summary:

Fix #1: Set the environment variable GCC_EXEC_PREFIX to point to the root of your mingw install.
Fix #2: Add %GCC_EXEC_PREFIX%\libexec\gcc\mingw32\3.4.2 to your search PATH.

Edit: I got a response from someone who said this didn't work. Turns out that GCC_EXEC_PREFIX only works if it points to a directory immediately off the root of your hard disk for some reason. So c:\mingw works fine, but c:\tools\mingw won't. You may have to alter the locations of your mingw directory to make this work.

The second problem I encountered is that I would often see "Cannot fork" errors during the build. I originally thought these errors were coming from the make utility, but eventually I determined that it was the sh.exe that was the problem. See, when make launches subprocesses to run its commands, it needs a command-line shell environment to run them in, in case the commands redirect output (since that requires support of a shell). By default, GNU make under Windows will look for sh.exe and use that to launch commands. If sh.exe isn't present, then it will create a batch file and use cmd.exe, which is the Windows shell. As an experiment, I went ahead and deleted the copy of sh.exe in the mingw/bin directory and sure enough, things started working again without errors.

But I wasn't quite done yet. On my new C2D machine, I wanted to take advantage of both cores by compiling with the -j 2 option. Unfortunately, make doesn't support the -j option when using batch files and cmd.exe. So I needed sh.exe, but obviously couldn't stick with the one I had. I tried the one from both msys and cygwin, and neither of them worked as-is in the mingw environment. So then I thought, well, all sh.exe is required to do is run the specified command. I already wrote a tool similar to that for builing with the Visual Studio compilers. So I adopted vconv.c into a sh.c, which is a new, minimal sh.exe implementation that works and allows multi-threaded builds. So,

Fix #3: Replace the sh.exe in mingw/bin with the version here.

And that's it! So really it comes down to 2 bugs: one in mingw caused by stricter parameter checking, and one in the ancient version of sh.exe that I was including with the build environment.

New Machine to Play With

I finally broke down in all my Core 2 Duo envy and bought me a new desktop machine. I used to have a nice 3GHz P4 desktop that I used whenever I needed to do desktop-y things (long downloads, compute-intensive work, automated MAME testing, etc.) but that machine got converted into a server once my previous server went belly up. I'd been struggling along with doing some tasks on a spare 933MHz P3, but the motherboard only supported 512MB of RAM, and it was just generally not exactly a fast machine.

Now, I know I'll get laughed at for buying a stock machine from Dell, since you can't overclock them easily, and I know the C2D is an overclockers dream. But hey, I just don't have the time for it. And, for only $1000, I can't complain too much: 2.4GHz C2D, 2GB RAM, 250GB hard disk. The one thing I didn't realize when I got the machine (it's a Dimension 9200) is that it is legacy free -- about time! I almost skipped ordering the keyboard and mouse because I have a bucketful of each sitting at home. But since the new machine required USB peripherals, I added yet another keyboard and mouse to my collection. :)

Of course the first thing I did when it arrived was wipe off the installed OS with all of the craplets and installed a fresh copy of Vista 64-bit. One of my motivations for upgrading was to have a 64-bit machine that I can eventually write a decent MIPS DRC on. One thing I will say that has impressed me about installing 64-bit Vista, versus previous 64-bit versions of Windows: the 64-bit drivers are finally there in enough quantity that most everything just works out of the box. And even what doesn't work is often available online.

Assuming you can get online. I was installing it away from my wired network, so I popped in a wireless NIC, but apparently those drivers aren't available in-box in Vista. So I lugged it upstairs, plugged it into the wired network (fortunately the onboard NIC drivers were present), then had Vista search online for drivers, which it found, downloaded, and installed for the wireless NIC. Then lugged it back downstairs. Mind you, if I hadn't been deathly ill that day, the lugging part wouldn't have been a big deal. :)

With two Vista machines now, I have even more incentive to figure out the build issues. I developed a workaround for the "Can't fork" bug mentioned in my previous post, which I'll talk about in another post here. This meant I was at least able to compile and build using the MSVC toolset. So of course, I had to build a 64-bit native version of MAME, since I kept hearing that 64-bit native builds weren't significantly faster than 32-bit builds, which I found surprising given how superior the 64-bit ABI and ISA are.

Well, using Visual Studio 2005 compile tools, I have to say the improvement between 64-bit native and running 32-bit was surprisingly large. It bought an extra 15% in Cruisin' USA (was about 75% of full speed in-game on 32-bit, and close to 90% in-game on 64-bit). And even more siginificant gains on Ridge Racer (from about 35% on 32-bit to about 50% on 64-bit). Some other slow games (like Driver's Edge) also showed definite gains. I'll probably do some more formal benchmarking later, but overall it's nice to see some of these games run faster than a crawl.

Cleaning Up Drivers

Over the past year, I've done some driver "cleanup" work. This generally involves picking apart a driver, revisiting all the assumptions using whatever information is available, and updating it to take advantage of newer features in MAME that have been introduced since it was first written. To do this work, I keep a checklist of things to do, just to make sure I've covered all the bases. This list is constantly updated, but I figured I would share it, since it is a good set of guidelines when updating a driver or writing a new one from scratch.







Actually, that's quite a lot of stuff. I'm sure I've missed a thing or two in some of my recent driver updates, but some examples that are pretty up to date include: ccastles.c, cloud9.c, missile.c, turbo.c, zaxxon.c.

Some Laserdisc Progress

After a bit of a hiatus with the holidays and fun power outages, I've been back making some progress on the laserdisc support. I now have the basic CHD format spec'ed out and implemented. And I have modified chdman.exe to support two new commands: -createav, which takes an AVI file plus an optional metadata file and compresses them to a CHD; and -extractav, which takes a CHD file and extracts it to an AVI file and a metadata file.

(And yes, the AVI reader/writer is cross-platform code, so it will work on non-Windows platforms as well. I also have a mostly complete QuickTime reader/writer, but am not sure if it is worth the effort to complete it. Though plugging the two together would produce an AVI <-> QuickTime conversion program, which would be useful!)

I'm happy to say that with a little bit of work using a test capture, I am now actually capable of displaying video from within MAME. There's still a lot of work to do yet to get the rest of the way, but this is a good step forward. Next up will be synchronizing frame and track numbers (you'll note the numerical discrepancy in the screenshot), wiring up the sound, improving performance, further enhancing chdman.exe with some additional I/O options, and all the while working with the great group of folks I've been talking to in order to get great quality source captures.

More to come as it all comes together!