NET:Concepts:Frame Locking

From Lavish Software Wiki
Revision as of 06:02, 10 April 2007 by CyberTech (talk | contribs)
Jump to navigation Jump to search

Overview

Frame locking is a term used to describe the act of preventing the host application (e.g. game) from continuing to process information while a section of code executes, by acquiring frame lock. Generally, a frame lock is non-exclusive. This means that other threads will continue to run, and may also have frame lock acquired. The only behavior implied by a frame lock is that the host application will not do any processing that may cause objects in use to disappear. This complements standard thread synchronization functionality. A frame lock must be explicitly released before the frame can continue.

Without acquiring frame lock, there is no guarantee that the executing thread can safely use any objects from the host application. Therefore, APIs are expected to use frame locking internally to enforce safety, and applications are expected to use frame locking to enforce safety across multiple API calls when necessary (for example, when calling one function to acquire an object, and subsequently using the object in such a way that it must be done within the current frame).

Exclusive Locks

Exclusive locking blocks any other thread attempting to acquire frame lock, until the exclusive lock is released -- it does not suspend execution of the other threads, only blocks frame lock attempts. This generally should not be used, as it may deadlock the application if the exclusive locking thread must wait on a resource in use in another thread that attempts a frame lock. Standard thread synchronization should be used instead.

Frame wait

A frame wait will cause a thread to yield execution until the following frame. This can be used instead of System.Threading.Sleep(0) to indicate the shortest yield possible, only continuing when the current frame has ended and the next begun. Frame lock can be implicitly acquired during frame wait.

Frame Locking API

Frame locking API in .NET is implemented in LavishVMAPI.Frame. Equivalent functions with the same names as those in LavishVMAPI.Frame are found in ISInterface for Inner Space extensions.

Commentary

Source: Lax (http://www.isxwow.net/forums/viewtopic.php?f=15&t=791&p=5247&hilit=Frame.Lock#p5247])

The reason it goes slower without explicit frame locking in your code, is that without it, you're relying 100% on the 
API to perform the frame locking for you.

It has to be done in order to ensure synchronization with the game, so the API does it internally on a per-call basis. The 
problem with relying on the API to  do it for you, is that consecutive function calls may take place on the following frame, 
instead of the current one. Without frame locking, 60 individual function calls may end up taking 60 individual frames, with 
an elapsed time of 1 second at 60 fps, instead of all being done in one frame, with an elapsed time counted in milliseconds 
or better (even if the function calls are consecutive). To improve efficiency, you want to strategically lock when doing sections 
of calls that should be in the same frame.

A lot of people seem to want to avoid frame locking, with the belief that it's going to hurt their game performance. To avoid 
it, they cache a lot of data in a frame lock, and make use of it outside of frame lock, entering back into frame lock when the 
game must again be manipulated (e.g. to perform an action in the game). To some degree, this is a great idea. But, probably not 
for the right reason. Locking and unlocking is not going to alter performance very much, and doesn't slow down the game. 

Locking just means that your thread is going to wait for the game to be ready for you, not blocking the game wherever it happens 
to be (thusly why n individual calls may end up taking n frames). The real performance hurt comes from reusing the same LavishScript 
API calls to obtain data, regardless of frame locking. In other words, if you have to keep using Me.X, it is helpful to cache it in 
.NET because this removes LavishScript parsing as well as the managed to unmanaged to managed marshaling and context changes. But it 
doesn't help so much to cache rarely used but constantly changing data (because then you're still doing the hard work, but perhaps 
for nothing). In other words, optimizing out additional LavishScript calls is much more beneficial than optimizing out an additional 
frame lock, any way you look at it.

See Also