Here are a few findings on Multi-Read Exclusive-Write Synchronizer from a recent upgrade of DWScript‘s GlobalVar functions.
I ran some comparisons between a plain Critical Section, Delphi’s TMultiReadExclusiveWriteSynchronizer and Windows Slim Reader/Writer Lock, of which an implementation was added to the dwsXPlatform unit.
Workload consisted of four threads performing a certain amount of read accesses for a one write access. Tests were run on a Delphi XE compiled executable, Windows 2008 R2 quad-core machine.
The CriticalSection case doesn’t discriminate between reads and writes, this was the existing implementation.
The other tests case would attempt to leverage the multi-read single-write aspects.
Test Case: 3 reads for 1 write
- Critical Section: 5.5 seconds
- Windows SRW: 3 seconds
- SysUtils TMREWS: 40 seconds
Test Case: 31 reads for 1 write
- CriticalSection: 5.8 seconds
- Windows SRW: 3.4 seconds
- SysUtils TMREWS: 45 seconds
During the test, CriticalSection usage was hovering just above 50% of 4 cores, Windows SRW was at 100% of 4 cores, and SysUtils TMREWS was using 85% of cores (50% of which being Kernel time).
The slightly longer runtimes in the second case come from reads being slightly more expensive than writes.
I implemented Slim Read/Write Locks in the TMultiReadSingleWrite class (dwsXPlatform unit), since that API is only available on Vista and above, the class includes a fallback to a plain old Critical Section.
One limitation of the SRW implementation to keep in mind is that it’s not re-entrant, ie. a thread can block itself if it tries to acquire or promote the same lock. This is unlike CriticalSection or TMREWS, which are re-entrant. In practice, this unlikely to be a limiting factor as proper implementations will typically not be re-entrant.
A slightly more problematic limitation is that SRW Locks don’t benefit from dead-lock diagnostics that Windows API Critical Sections benefit from. So if you dead-lock, you’re on your own.
With all those limitations in mind, SRW Locks are indeed slim and fast. Where TMultiReadExclusiveWriteSynchronizer could only be beneficial in extreme-corner cases, SRW Locks will be beneficial in many (most?) scenarios.
Note that the SRW API is loaded and detected in the DWScript implementation “by feature” rather than “by version”, ie. the code checks for the presence of the API, rather than the Windows version.