Sign in to follow this  
3DModelerMan

Asynchronous I/O vs resource loading thread.

Recommended Posts

I've been messing around with asynchronous I/O (Win32 overlapped file I/O) and I was wondering. What are the advantages of asynchronous I/O over having a resource loading thread that just reads from the hard drive with regular synchronous I/O techniques in a different thread?

Share this post


Link to post
Share on other sites
Depends on the architecture of your game.

If you load everything at start you won't see much difference. The bottleneck will still be loading the resources.

Some games support streaming of assets during play. In that situation a loading thread can mean much faster general-case because you can continue running the game without those assets, and swap them in as they arrive. The resource loading thread can prioritize one asset over another, which a simple overlapped I/O call wouldn't do.

Share this post


Link to post
Share on other sites
[quote name='3DModelerMan' timestamp='1347665620' post='4980222']
Yeah, I was thinking mostly in the context of a Skyrim type of game with open world exploration.
[/quote]
Then it'd be best to use an I/O thread.

Otherwise, you'd see hiccups when you hit certain boundaries in the game. You can see that a lot in older games from the 80s.

Share this post


Link to post
Share on other sites
[quote name='frob' timestamp='1347661758' post='4980208']The resource loading thread can prioritize one asset over another, which a simple overlapped I/O call wouldn't do.[/quote]That's apples and oranges.
You can implement prioritisation in both schemes:[code]main thread loop:
push requests to loading thread

loading thread loop:
sort requests list by priority
blocking load top priority resource[/code][code]main thread loop:
add requests to list
if( !load in progress )
sort requests list by priority
async load top priority resource[/code][quote name='3DModelerMan' timestamp='1347652813' post='4980154']
What are the advantages of asynchronous I/O over having a resource loading thread that just reads from the hard drive with regular synchronous I/O techniques in a different thread?[/quote]You should word it the other way around: what are the advantages of using an extra thread + blocking I/O, vs using no extra threads an async I/O.

The answer is that you've only added extra overhead, because the blocking I/O API is just a wrapper around the asynchronous I/O API.
e.g. say the async API looked like:
[code]token StartAsyncRead( void* buffer, int size );
bool IsAsyncReadDone(token);[/code]Then the blocking API is basically just:[code]void BlockingRead( void* buffer, int size )
{
token id = StartAsyncRead( buffer, size );
while( !IsAsyncReadDone(id) ) { Sleep(); }
}[/code]So by using an extra thread, you've taken a naturally asynchronous operation, then wrapped it in a blocking abstraction, and then wrapped that abstraction in a thread to again make it asynchronous!

One reason to use a blocking I/O API, is because the C blocking file API ([i]fopen/fread etc[/i]) are portable across different OSs, whereas if you use the OS's optimal loading API ([i]e.g. CreateFile/ReadFileEx/etc[/i]), then you've got to re-write your file loading code when you switch to another OS. Edited by Hodgman

Share this post


Link to post
Share on other sites
[quote name='Hodgman' timestamp='1347683391' post='4980286']
You should word it the other way around: what are the advantages of using an extra thread + blocking I/O, vs using no extra threads an async I/O.
[/quote]
Rumor has it that async IO (in windows) does block when there are X amount of requests in flight - making a separate thread can be of help when such rare hiccups are undesirable. Heard it some years ago, but never tested it out myself (afaicr it was sufficiently reputable source - so i did not bother). No idea whether it was some win version specific or what.

Anyone having some insights there? Is it bonkers nowadays? Was it true at some point at all? Edited by tanzanite7

Share this post


Link to post
Share on other sites
I'm going to go with a resource loading thread. It would be more portable across platforms anyways (I've never heard of I/O completion ports on anything but Windows though I could be wrong), and I think loading asynchronously would more than make up for the call overhead on Windows. Obviously I'd need to benchmark both ways, but I'll try a seperate thread first.

Share this post


Link to post
Share on other sites
[quote name='tanzanite7' timestamp='1347730491' post='4980429']
[quote name='Hodgman' timestamp='1347683391' post='4980286']
You should word it the other way around: what are the advantages of using an extra thread + blocking I/O, vs using no extra threads an async I/O.
[/quote]
Rumor has it that async IO (in windows) does block when there are X amount of requests in flight - making a separate thread can be of help when such rare hiccups are undesirable. Heard it some years ago, but never tested it out myself (afaicr it was sufficiently reputable source - so i did not bother). No idea whether it was some win version specific or what.

Anyone having some insights there? Is it bonkers nowadays? Was it true at some point at all?
[/quote]I found the MS KB article about this issue -- http://support.microsoft.com/kb/156932 -- it mostly applies to NT/2K, but some applies to XP as well. It seems that putting your "async" file read commands onto a non-time critical thread might be a good idea.
It looks like [url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365468(v=vs.85).aspx"]ReadFileEx[/url] + SleepEx is generally preferred over [url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx"]ReadFile[/url] as for async reads -- it doesn't contain the warning about the possibility of synchronous behaviour, but can fail if the internal queue is full.

Share this post


Link to post
Share on other sites
[quote name='3DModelerMan' timestamp='1347752077' post='4980505']
I've never heard of I/O completion ports on anything but Windows though I could be wrong[/quote]
Sun OS has I/O completion ports, linux has epoll, Mac OS/BSD have kqueue. All fulfill roughly the same purpose.

Of course, you probably don't want to write separate back-ends for all those alternatives, which is why [url="http://libevent.org"]libevent[/url] exists.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this