<< Pinscape Resources Home

PinAffinity

One of the best performance tweaks I've found for virtual pinball is "CPU affinity". It's also one of the least known, probably because there aren't a lot of good tools for it. PinAffinity is my attempt to fix that by offering a simple tool tailored to virtual pin cabs, designed to be extremely simple to set up, and completely automatic once configured.

CPU affinity optimizations aren't about increasing your "FPS" (frame rate) numbers. Your frame rate probably won't increase after tweaking affinities, although it might if you're using an older CPU and you're close to maxing it out. But even a machine with plenty of CPU power can see some benefit, because FPS numbers only tell part of the story.

The big thing that affinity optimization can help with is "stutter". Stutter is a sort of jerky motion that you see on the video display, sporadically, especially when the machine is under a lot of load. In a pinball emulator, you might see this during a multiball mode, or when a lot of lighting effects are firing. You might also hear audio glitching at these times.

Stutter can show up sporadically even if you have a fast machine with high average FPS rates. Stutter happens during momentary spikes in load, so it can be hard to get rid of using the normal performance tuning techniques, which are all about improving overall throughput. Making your machine faster overall is always good, but stutter isn't so much about overall speed as about instantaneous responsiveness. And that's where CPU affinity can help. Affinity optimization can reduce stutter by reducing thread scheduling latency, allowing video game threads to respond more quickly when they have work ready to do. This is especially important for video animation, because animation has to keep with the video refresh cycle schedule in order to look smooth and consistent. CPU affinity tuning can reduce the competition for CPU resources from other running programs, which can in turn allow VP to keep in closer sync with real time as it does its physical computations and graphics rendering.

Downloads

Use the "X-bit" version that matches your Windows operating system type. If you're not sure what you have, open your "System" control panel and look at the "System type" field. It should say something like "64-bit Operating System".

Installation and basic use

Just download it and unzip the files into a folder on your disk. There's no need for a Setup program or registry settings or anything like that; it's all self-contained in the one folder.

Double-click the program's .exe file to run it. This will bring up a window showing running processes on your system. The program is pre-configured with the current Visual Pinball files set to "Pinball" mode. You can set the modes for other running programs by right-clicking them and selecting Set CPU Affinity Type from the menu. You can also set the type for a program that's not currently running using the Add Program menu command. All changes are saved immediately and will be restored the next time you run the program.

When you first install the program, you should check that the affinity settings are working. To do this, run a game in Visual Pinball, and while the game is running, go back to the PinAffinity window and check the CPU affinity column for the VP executable you're running (e.g., VPinballX.exe if you're using VP 10). If things are working, the Affinity column should show something like "-+++". If it says "Unable", it means that Windows blocked the affinity change due to privilege restrictions that apply to certain system processes. If you want PinAffinity to control those blocked processes, see Admin Mode below.

For more instructions, see the README file included with the download.

Automatic startup

You'll probably want to set up PinAffinity so that it automatically launches every time you start your system. There are several ways to do this. The right way for you depends on whether or not you want to run in Admin Mode:

User mode: If you only want to run PinAffinity with normal "User" level privileges, launching at startup is easy. Simply create a Windows Shortcut for PinAffinity in your Start Menu > Programs > Startup folder. Do not enable the Run as Administrator setting in the "Properties" dialog (for either the Shortcut or for the .exe file itself) if you use a Startup shortcut. Windows security rules prohibit that, and Windows will simply ignore the Startup shortcut.

Admin mode: The designers of Windows didn't want to encourage you to launch random software in Admin mode, so they didn't make it easy. But it can be done. Here's the procedure:

  • Run Windows Task Scheduler (use Windows+S to search for it)
  • Click Create Task in the Actions pane
  • On the General tab, enter a name (say, "Run PinAffinity")
  • Click the box "Run with the highest privileges"
  • On the Triggers tab, click New
  • In the "Begin the task" drop-down at the top, select "At log on"
  • Click OK
  • On the Actions tab, click New
  • Click Browse and select PinAffinity.exe
  • In the "Add arguments" box, type /MINIMIZE
  • Click OK
  • Click OK in the main dialog

Admin Mode

By default, Windows doesn't allow PinAffinity to modify the affinity settings for system processes (internal programs started by Windows itself) or for programs launched by other users. When you see "Unable" in the affinity setting column for a process, that means that the process is protected against alteration by PinAffinity.

You can get around this by running PinAffinity in "Administrator Mode", which gives the program elevated privileges as though it were a system process itself. By default, Windows runs most software with "User" privileges, which restricts access to some internal system resources, including the ability to mess around with system processes. This is in part to protect your system against malware, and in part to protect against simple programming errors by otherwise benign programs. Most programs don't need special privileges to do their jobs, so they won't even notice the restrictions. But the nature of PinAffinity's work does require Admin rights if you want the program to be able to control affinities for system processes.

Should you run PinAffinity in Admin mode? If you want the maximum optimization benefit, the answer is yes. But if you're uncomfortable giving elevated privileges to random open-source software like this, you'll still get much of the benefit running in regular User mode.

Duration of affinity changes

The CPU affinity changes are only in effect while PinAffinity is actually running. No permanent changes are made to your system, and all normal Windows defaults are restored as soon as the program exits. That means you have to leave PinAffinity running while playing VP games for its optimizations to work. You should minimize the PinAffinity window while running VP games, to eliminate the overhead of redrawing the window. The window minimizes to a "system tray" icon for reduced desktop clutter; just click the icon to bring the window back.

About CPU affinities

CPU affinity is a feature built into Windows that lets you tell the operating system to assign a particular program to a particular group of CPU cores. Most modern PC CPU chips have multiple cores, which means that they actually consist of multiple CPUs within the same chip, each of which can run its own separate program at the same time that other programs are running on the other cores.

Windows normally lets all programs on your system share all of the available cores more or less equally. CPU affinity lets you override this default equal rationing by telling Windows to run certain programs only on certain of the cores.

On a pin cab, we can use this to partition the PC's cores into two groups: a "Pinball" group, and "everything else". Programs in the pinball group run on one set of cores, and everything else runs on a separate set of cores. That more or less eliminates competition from other programs for the "pinball" cores, which lets the pinball software run more smoothly.

This might not seem all that useful if you have a fast CPU. VP probably isn't coming close to 100% CPU saturation on your machine, after all. But CPU usage percentage isn't the only thing that matters: another important factor is the scheduling latency in the Windows thread scheduler. For video game software like VP, it's critical to get access to a CPU the instant there's work to do. Video games have to do their computing in real time because they have to respond to outside events (flipper button presses, for example). The Windows scheduler is optimized for overall throughput, so it tries to balance load across programs. As a result, Windows doesn't always allow a program run instantly when it has work to do. Programs normally have to wait their turn. If all of the CPU cores are busy with other work when VP is ready to render a frame, Windows might not let VP run in time for the next video refresh, and this can lead to visible motion artifacts like "stutter".

So if you're wondering why you sometimes get stutter on a machine where VP is only using 8% CPU, this is probably at least part of it, and installing PinAffinity might help. Affinity settings help by reducing the number of other programs competing for the cores that VP is using, so there's less of that waiting in line for other programs to finish their work.

Other CPU affinity tools

I wrote PinAffinity because I couldn't find a suitable existing tool to recommend in the performance optimization chapter of my new Pinscape Build Guide. However, that doesn't mean there's nothing else that can do the job. There are some other tools that can handle this; I just didn't think they'd make good recommendations because of drawbacks relating to availability and/or ease of use. With those caveats in mind, here are some other options....

The best third-party option I've been able to find is Process Hacker version 3. The name makes me rather queasy about setting it loose with Administrator privileges, but setting aside the unfortunate name, it's a solid open-source Task Manager replacement, with features that exceed the venerable Process Explorer from SysInternals. The key thing that PH3 can do, relevant to our purposes here, is to store affinity settings persistently by process name, and apply them automatically to new processes as they're launched, just like PinAffinity does. Unfortunately, PH3 is cumbersome for this use because it doesn't have a global default affinity setting; you have to go through all of the running processes to do the initial setup, which is tedious to say the least. Note that you need version 3 for the persistent affinity feature; version 2 doesn't have it. And version 3 isn't officially released as of this writing - it appears to be a very long-running work in progress. It's somewhat hidden on the Process Hacker web sites, too; you have to find the "Nightly Build" section, which is only linked from the "Download" page. The whole Web site is said to be in beta, so I don't want to offer any deep links into it lest they be reorganized away by the time you read this.

Another option is a freeware tool called PriFinitty [sic on the doubled "t"]. You'll notice I'm not hyperlinking to it, which we'll come to shortly. I was actually using this on my own cab for a long time, and I would have recommended it despite its cumbersome user interface, but it turns out I can't, because it's no longer available. PriFinitty was free but closed-source, and the developer seems to have lost interest in it a long time ago and erased all official traces from the Web. Thus the lack of a hyperlink. There are some vestigial copies that people have cached on other sites, so you might still be able to find an old version with a little googling. But I don't think there's much point given the uncertain provenance of the cached copies, the lack of ongoing maintenance, and the fact that it doesn't seem to work at all on Windows versions past Win 7.

Windows Task Manager and SysInternals' Process Explorer both have the ability to set CPU affinities for a running process, but that's not sufficient for our purposes, because they don't let you set affinities persistently. They only let you set affinities on live process instances. That's obviously unworkable for our use case.