c++ – slow read cin

Question:

By default reading with cin is excruciatingly slow compared to its scanf counterpart… when logic tells us it shouldn't:

  • With cin a direct call is made to the function that knows what the type of the destination variable is.
  • With scanf the function must read the format string (with dozens of possibilities) to know how to interpret the input and then process it.

However, with a simple example it is easy to see that reality is different:

#include <iostream>
#include <chrono>
#include <string>

void cinFunc()
{
  int N;
  for( int i=0; i<100000; i++)
    std::cin >> N;
}

void scanfFunc()
{
  int N;
  for( int i=0; i<100000; i++)
    scanf(" %d",&N);
}


template<typename Func>
void Test(std::string const& title, Func f)
{
  auto start = std::chrono::steady_clock::now();
  f();
  auto end = std::chrono::steady_clock::now();
  auto diff = end - start;
  std::cout << "Test " << title << ":\t" << std::chrono::duration<double, std::milli>(diff).count() << " ms\n";
}

int main()
{
  Test("cin",cinFunc);
  Test("scanf",scanfFunc);
  return EXIT_SUCCESS;
}

The program is run with a file containing 200,000 1-digit integers separated by a space, and the results speak for themselves:

Test cin:       64.7967 ms
Test scanf:     49.855 ms

What is the reason that C++'s own reading is so slow? How can this situation be corrected?

Answer:

By default iostream is synchronized with stdio to ensure that the standard input and output functions of both C and C++ share a single buffer, since without synchronization both would have independent buffers, this would cause problems like:

#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    cout << "Hola";
    printf("mundo");
    cout << "adios";
}

Without synchronization you will never know if you will get Holaadiosmundo or Holamundoadios or adiosholamundo since both printf and cout have different buffers so the order is undefined. Unfortunately the sync issue introduces a significant performance penalty for iostream , but it is possible to disable it if you don't intend to mix stdio and iostream .

ios_base::sync_with_stdio(false);

This would give a significant performance boost even better than stdio .

Scroll to Top