Dina Pop
Dina Pop

Reputation: 1

Memory and time issue when reading/writing from a file

I am trying to solve a school problem and I did that, but it should run faster and on less memory if possible - can you please help me achieve that?

Problem statement: Read a natural number N and a string from a file, and output in another file the same string N number of times.

Example of input file: 3 dog

Example of output file: dog dog dog

Restrictions: 1 ≤ n ≤ 50, and the length of the line to be read is maximum 1,000,000

Time limit: 0.27 seconds

This is what I tried (but run time exceeds the limit):

#include<fstream>

using namespace std;

ifstream cin("afisaren.in"); 
ofstream cout("afisaren.out");

short n; 
char s[1000005];

int main() {
    cin >> n;
    cin >> s;
    while(n) {
        cout << s << '\n';
        n--;
    }
    cin.close();
    cout.close();
    return 0; 
}

Upvotes: 0

Views: 212

Answers (2)

Angramme
Angramme

Reputation: 164

I'm not a c++ expert but I had a similar problem when I used c++ style file streams, after googling a bit, I tried switching to c-style file system and it boosted my performance a lot because c++ file streams copy file contents into internal buffer and that takes time, you can try it c-style but usually it is not recommended to use c in c++.

Upvotes: 0

markus-nm
markus-nm

Reputation: 865

Generally when given this type of problem, you should profile your own code to see which part of the code is consuming what amount of time. This can mostly be done by adding a few calls to a timekeeping-function before and after code execution, to see how long it was executing. However this is not so easy with your code, since one of the biggest problems (optimisation-wise) is your char s[1000005]; line. The memory will be allocated before executing your main() function, which is operating system dependant (or rather depends on the libc and compiler used).

So first, do not use pre-allocated char-arrays. You're using C++! Why not simply read the text into a std::(w)string or any of the C++-classes which will do dynamic memory allocation (and not crash your program if line-length does exceed 1,000,000).

And second, the c++ std::streams usually perform a flush-to-disk every time a line-ending character is written. This is highly inefficient unless your text is exactly the same size as the block-size of the underlying file-system. To optimize this, create a memory object (i.e. std::string) and copy your text into it for k times, where k = fs-block-size / text-length. fs-block-size will most likely be 1024, 2048 or 4096 bytes. There are system-calls to find that out, but performance will usually not be affected too much when writing twice (or 4x) the fs-block-size, so you can safely assume it to be 4096 for close-to-or-maximum-performance.

Since the maximum number of repetitions is 1 < n < 50, and line length is 1,000,000 (approx. 1 MiB if ASCII), maximum file size for the output will be 50,000,000 characters. You could also write everything into memory and then write everything in one call to write(). This would probably be the most efficient way in terms of disk-activity, but obviously not regarding memory consumption.

Upvotes: 1

Related Questions