Jump to content

  • Log In with Google      Sign In   
  • Create Account

Asynchronous I/O vs resource loading thread.


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 3DModelerMan   Members   -  Reputation: 1071

Like
0Likes
Like

Posted 14 September 2012 - 02:00 PM

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?

Sponsor:

#2 frob   Moderators   -  Reputation: 22787

Like
1Likes
Like

Posted 14 September 2012 - 04:29 PM

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.

Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I write about assorted stuff.


#3 3DModelerMan   Members   -  Reputation: 1071

Like
0Likes
Like

Posted 14 September 2012 - 05:33 PM

Yeah, I was thinking mostly in the context of a Skyrim type of game with open world exploration.

#4 alnite   Crossbones+   -  Reputation: 2133

Like
1Likes
Like

Posted 14 September 2012 - 05:55 PM

Yeah, I was thinking mostly in the context of a Skyrim type of game with open world exploration.

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.

#5 Hodgman   Moderators   -  Reputation: 31943

Like
4Likes
Like

Posted 14 September 2012 - 10:29 PM

The resource loading thread can prioritize one asset over another, which a simple overlapped I/O call wouldn't do.

That's apples and oranges.
You can implement prioritisation in both schemes:
main thread loop:
  push requests to loading thread

loading thread loop:
  sort requests list by priority
  blocking load top priority resource
main thread loop:
  add requests to list
  if( !load in progress )
	sort requests list by priority
	async load top priority resource

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?

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:
token StartAsyncRead( void* buffer, int size );
bool IsAsyncReadDone(token);
Then the blocking API is basically just:
void BlockingRead( void* buffer, int size )
{
  token id = StartAsyncRead( buffer, size );
  while( !IsAsyncReadDone(id) ) { Sleep(); }
}
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 (fopen/fread etc) are portable across different OSs, whereas if you use the OS's optimal loading API (e.g. CreateFile/ReadFileEx/etc), then you've got to re-write your file loading code when you switch to another OS.

Edited by Hodgman, 14 September 2012 - 10:39 PM.


#6 tanzanite7   Members   -  Reputation: 1378

Like
1Likes
Like

Posted 15 September 2012 - 11:34 AM

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.

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, 15 September 2012 - 11:35 AM.


#7 3DModelerMan   Members   -  Reputation: 1071

Like
0Likes
Like

Posted 15 September 2012 - 05:34 PM

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.

#8 Hodgman   Moderators   -  Reputation: 31943

Like
2Likes
Like

Posted 16 September 2012 - 09:01 PM


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.

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?

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 ReadFileEx + SleepEx is generally preferred over ReadFile 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.

#9 tanzanite7   Members   -  Reputation: 1378

Like
0Likes
Like

Posted 17 September 2012 - 01:14 PM

Thanks for the digging. Appreciated.

#10 swiftcoder   Senior Moderators   -  Reputation: 10440

Like
1Likes
Like

Posted 17 September 2012 - 01:51 PM

I've never heard of I/O completion ports on anything but Windows though I could be wrong

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 libevent exists.

Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS