How can I make cout faster?
Asked Answered
P

3

6

Is there any way to make this run faster and still do the same thing?

#include <iostream>

int box[80][20];

void drawbox()
{
    for(int y = 0; y < 20; y++)
    {
        for(int x = 0; x < 80; x++)
        {
            std::cout << char(box[x][y]);
        }
    }
}

int main(int argc, char* argv[])
{
    drawbox();
    return(0);
}

IDE: DEV C++ || OS: Windows

Pap answered 25/1, 2011 at 2:13 Comment(7)
Probably be faster to build up a string and output that once, or once per outer loop, which'd be 1 or 20 couts, rather than 20*80=1600Whitnell
@Marc B: A buffered I/O library is supposed to take care of that for you. Unfortunately, C++ iostreams are dog slow at both buffering and I/O. Look at the questions I've asked if you want to see some nice benchmarks showing just how miserable they are.Endemic
@Ben Voigt - And it's really disappointing. They could be faster than C's stdio library if they had been designed more carefully. :-(Stateless
@Marc B: Why not make that a real answer?Submariner
Buffering helps with the actual I/O itself but function calls are generally not cost-free. Twenty outputs with eighty characters each will almost certainly be faster that sixteen hundred with one character each. Not because it's actually sending those character to a device, just because it's constructing and tearing down stack frames, among other things.Emeryemesis
@Omnifarious: I definitely agree (at least compared to printf which has to parse format strings -- I don't think iostreams could beat the performance of putc and puts although it should have been able to match them).Endemic
@Drew: because I was just guessing. I've never written so much as line 1 of a C++ program in my life.Whitnell
C
4

As Marc B said in the comments, putting the output into a string first should be faster:

int box[80][20];

void drawbox()
{
    std::string str = "";
    str.reserve(80 * 20);

    for(int y = 0; y < 20; y++)
    {
        for(int x = 0; x < 80; x++)
        {
            str += char(box[x][y]);
        }
    }

    std::cout << str << std::flush;
}
Codeclination answered 25/1, 2011 at 2:26 Comment(3)
oh, do preallocate that string. std::string doesn't necessarily have optimized allocation patterns like say std::vector.Endemic
@Ben Voigt: I'd be very disappointed if it was necessary... this definitely sounds like a quality of implementation issue...Whiggism
@ Matthieu M: I doubt that any default string implementation reserves 1600 bytes. Thus it is likely there will be multiple re-allocations before finish writing. Just a good idea to pre-reserve the space required.Talipes
F
2

The obvious solution is to declare the box array differently:

char box[20][81];

Then you can cout a row at a time. If you can't do this for whatever reason, then there's no need to use std::string here -- a char array is faster:

char row[81] ; row[80] = 0 ;
for (int y = 0; y < 20; y++)
  {
  for (int x = 0 ; x < 80 ; x++)
    row[x] = char(box[x][y]) ;
  std::cout << row ;
  // Don't you want a newline here?
  }
Franz answered 25/1, 2011 at 9:1 Comment(1)
That's what I was thinking. No need to dynamically allocate an array that's the same size every time.Path
E
1

Sure, use putchar from stdio.h.

Endemic answered 25/1, 2011 at 2:16 Comment(6)
@Mark: really? Are you sure it's your program that's the bottleneck and not the console window? Can you check if it's faster when output is redirected to a file?Endemic
The issue here is not using C++ vs. C. (And in fact, in his example it would be putchar() from cstdio). The issue is printing data for every character.Kendry
@Bjoern: putchar is buffered, it should be quite fast compared to actually drawing the text on the screen.Endemic
C++ io functions are buffered as well.Aplanatic
@Ed: yes, but they require a function call (not inlined because they are virtual) unless you have a very clever linker and LTO is activated (and even then, it might not work). I don't know if putchar is inline or not.Whiggism
@Matthieu M.: Only overflow() of streambuf is virtual. Most calls to the std::ostream/char version of op<< (a free function) shouldn't involve a virtual function call.Kelleher

© 2022 - 2024 — McMap. All rights reserved.