Spring Code Optimization

Spring Code Optimization

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

Post Reply
Sheekel
Posts: 1391
Joined: 19 Apr 2005, 19:23

Spring Code Optimization

Post by Sheekel »

I was reading some source that John Carmack had released .. I think it was the common file handling code included in the Quake1 tools source code. And I noticed that he was doing something I had never thought of when processing files. He would read the entire file into memory, process that glob of RAM and then free it when he was done. I had never considered that, and at the time, was very cool to discover. There's only one file read operation (albeit a large one, but still, only one), and the rest of the processing takes place in RAM so it's really fast.

And how exactly do you read the file into a glob of RAM? Like so... here is a small chunk of my Tfile base class..



int TFile::LoadFile(CString* _pcsFilename)
{
FILE* l_pfile;
int l_iLength; l_pfile = ::fopen(*_pcsFilename, "rb"); if(!l_pfile) {
m_pbBuffer = NULL;
return -1;
} // Read the file into RAM.
//
l_iLength = GetFileLength(l_pfile);
m_pbBuffer = new byte[l_iLength + 1];
::ZeroMemory(m_pbBuffer, l_iLength + 1);
::fread(m_pbBuffer, 1, l_iLength, l_pfile);
::fclose(l_pfile); return l_iLength;
}int TFile::GetFileLength(FILE* _pfile)
{
int l_iSavPos, l_iEnd; l_iSavPos = ::ftell(_pfile);
::fseek(_pfile, 0, SEEK_END);
l_iEnd = ::ftell(_pfile);
::fseek(_pfile, l_iSavPos, SEEK_SET); return l_iEnd;
}





FYI : m_pbBuffer is a byte* member variable.

That's really it. You open the file, allocate a chunk of RAM that matches the file size, and read it into that buffer. Now if you take a byte* and start walking through that chunk of data, it's just like you were walking through the file itself by reading byte at a time. Except much faster...

When processing the data, I use a byte* to walk through the file data in RAM ... the file is over when the value that variable points to is NULL. So I loop something like this...



byte* l_pbuffer = m_pbBuffer;while(*l_pbuffer) { // Do something with the data here

l_pbuffer++;
}



I read that on a coding website...

Does spring utilise this technique? A better one? Is it possible? Would it improve Spring? Is it worth attempting to implement?
User avatar
jcnossen
Former Engine Dev
Posts: 2440
Joined: 05 Jun 2005, 19:13

Post by jcnossen »

There is probably a dozen buffers between spring and the actual HD, so I doubt it will change a lot. However there is a small performance increase in directly accessing the contents of the file, instead of calling the file IO functions a lot for small chunks.

I really agree there is a lot to optimize in spring, but this isn't the best way I think. Optimization of actual in-game code would be more important IMO.

PS: Don't read too much of Q1 source, you might start thinking putting *EVERYTHING* in globals is the right way to program ;)
[offtopic] I've looked at it as well and he uses a very different way of programming. Quite interesting, he seems to use a really state-based approach of handling algorithms...

Standard OO way in C would be

Code: Select all

Bitmap* bmp = read_bitmap("file.bmp");
However carmack does

Code: Select all

read_bitmap("file.bmp");  // stores bitmap data into a global "bm" structure.

/* use bm structure here */
Funny thing is, he's really the only person who has made complex games like that... and it's actually faster because you continuously save CPU time that is otherwise spend to push/pop arguments onto the stack.

Sorry for my rant... it kinda fits in "optimization" though ;)
Chocapic
Posts: 556
Joined: 16 Oct 2005, 03:35

Post by Chocapic »

well all that depends on how often that function is called too.
If its call very often that would be a very nice optimization to make!
Post Reply

Return to “Engine”