DragonTorchSlash
DragonTorchSlash

Reputation: 15

Faster File Operations C++

So I am making a renderer in c++ and opengl for a class of mine. I am making an animation program for extra credit that will change values in a text file right before my renderer reads them in each frame. My problem is that this section of code isn't writing fast enough

while (clock() < time_end)
    {
        timeStep = clock() + fps * CLOCKS_PER_SEC;
        for(int k=0; k < currOps.size(); k++)
        {
            // increase/decrease each set once for the current timestep
            // a case for each operation
            int pos = currAxis[k];
            if(currOps[k] == "loc")
            {
                opsFile[8+pos] = patch::to_string(atof(opsFile[8+pos].c_str()) + locScale[pos-1]*timeAdjust);
                //edit this value by loc adjust
            }
            else if(currOps[k] == "rot")
            {
                opsFile[4+pos] = patch::to_string(atof(opsFile[4+pos].c_str()) + rotScale[pos-1]*timeAdjust);
                //edit this value by rot adjust
            }
            else if(currOps[k] == "scl")
            {
                opsFile[pos] = patch::to_string(atof(opsFile[pos].c_str()) + sclScale[pos-1]*timeAdjust);
                //edit this value by scl adjust
            }
        }
        currFile.close(); //save file and restart so we don't append multiple times
        currFile.open(files[location[0]].c_str(), ofstream::out); // so we can write to the file after closing
        for(int j=0; j <opsFile.size(); j++)
        {
            // update the file
            currFile << opsFile.at(j);
            currFile << "\n";
        }

        while(clock() < timeStep)
        {
            //wait for the next time steps
        }
    }

Specifically currFile operations at the end. If I take the currFile operations out it will run at the desired fps. FPS is set to .033 so that it does 30 fps. Also it will run fast enough when fps = 0.1. Any optimizations would be great. If need to see any other part of my code let me know and I will upload. The whole thing is around 170 lines. currOps, files, and opsFile are vectors of strings sclScale, rotScale, and locScale are vectors of doubles currAxis is vectors of ints

Upvotes: 1

Views: 360

Answers (2)

Nim
Nim

Reputation: 33655

Here are some general changes which may help:

  1. I would convert the curOps to an enum rather than a string (save you the string comparisons.) Looks like you should pre-process that container and build a sequence of enums (then your code in the loop becomes a switch)
  2. Don't use vector<string> for curOps, simply read the floats from the file and write the floats out - this will save you all those pointless conversions to and from string. If you wanted to take it further, convert the file to binary (if you are allowed by the exercise), and store a simple structure which contains the floats you need and use memory mapped files (you don't need boost for that, it's straight forward just using mmap!)

Before going down the mmap route - try the float read/write from file. For example, let's say that each "row" in your file corresponds to something like the following:

struct transform {
  double x, y, z;
};

struct op {
  transform scale, rot, loc;
};

Declare a bunch of stream in/out operators for these (for example:

std::ostream& operator<<(std::ostream& os, const transform& tx) {
  return os << tx.x << ' ' << tx.y << ' ' << tx.z;
}
std::istream& operator>>(std::istream& is, transform& tx) {
  return is >> tx.x >> tx.y >> tx.z;
}

(a similiar set will be required for op)

Now your vector is std::vector<op>, which you can easily stream in and out from your file, for example, to read:

op i;
while(file >> i) { curOps.push_back(i); }

To write:

for (auto o : curOps) file << o << '\n';

If this is still not enough, then mmap (btw - it's possible on windows too: Is there a memory mapping api on windows platform, just like mmap() on linux?)

Upvotes: 3

Ben Voigt
Ben Voigt

Reputation: 283634

Try using the functions in stdio.h instead. iostreams are terribly inefficient.

In your case all you will need is fseek() ... fputs(). Avoiding reopening the file each time should actually help quite a lot.

Upvotes: 0

Related Questions