Introdução: O paradoxo da velocidade que explodiu o Stack Overflow
\n\nImagine a situação: você está resolvendo um problema de competição ou processando um arquivo de log de gigabytes. O script em Python termina em 2 segundos. Você o reescreve em C++, esperando uma aceleração de dez vezes, mas… obtém 10 segundos! Uma dor familiar? Foi exatamente essa pergunta que acumulou milhares de visualizações no Stack Overflow e gerou a discussão lendária: «Why is reading lines from stdin much slower in C++ than Python?».
\n\nAparentemente, como o C++ «rápido» pode perder para o Python «lento» em uma operação tão trivial quanto ler linhas? A resposta não está na velocidade da linguagem em si, mas nas configurações padrão e na arquitetura do iostream. Neste artigo, faremos nossa própria investigação, escreveremos código de teste em C++ e Python, mediremos o tempo e, principalmente, aprenderemos a tornar a entrada/saída em C++ verdadeiramente rápida.
\n\nEste artigo não é teoria seca, mas um guia prático para todos que programam em C++ e enfrentam problemas de desempenho de entrada/saída. Vamos nessa!
\n\nO cerne do problema: Por que o iostream «engasga»?
\n\nQuando você escreve std::cin >> data ou std::getline(std::cin, line), o C++ por padrão faz algo que muitos nem imaginam. Ele sincroniza seus fluxos de entrada/saída com os fluxos padrão do C (stdin, stdout). Para quê? Para compatibilidade: você pode usar printf e std::cout simultaneamente no mesmo programa, e a saída não se misturará.
Essa sincronização tem um custo alto. Cada chamada a cin ou cout verifica o estado dos fluxos C, transformando uma operação rápida e bufferizada em uma operação síncrona lenta.
Em Python, é diferente. A função input() e sys.stdin.readline() usam seu próprio buffer, bem otimizado em nível C. Nenhuma sincronização extra — apenas leitura de um bloco de dados do descritor de arquivo. É por isso que a leitura do stdin em Python pode ser mais rápida que em C++ «de fábrica».
Experimento: Teste de velocidade
\n\nVamos verificar isso na prática. Escreveremos um programa simples que lê 1.000.000 de linhas do stdin e não faz nada com elas (apenas as lê). Primeiro em C++ «como está»:
\n\n// slow_cin.cpp\n#include <iostream>\n#include <string>\n\nint main() {\n std::ios::sync_with_stdio(false); // Por enquanto, comentado\n std::cin.tie(nullptr); // E isso também\n\n std::string line;\n while (std::getline(std::cin, line)) {\n // Não faz nada\n }\n return 0;\n}\n\nE agora em Python:
\n\n# fast_python.py\nimport sys\n\ndef main():\n for line in sys.stdin:\n pass\n\nif __name__ == "__main__":\n main()\n\nVamos executar o teste com seq 1000000 | ./slow_cin e seq 1000000 | python3 fast_python.py. O resultado será chocante: C++ sem otimizações pode ser de 5 a 10 vezes mais lento que Python! Mas não se apresse em enterrar o C++ — o problema é resolvido com duas linhas de código.
Solução: Duas linhas mágicas
\n\nTudo o que é necessário para acelerar a entrada/saída em C++ é desabilitar a sincronização e o vínculo dos fluxos. Adicione no início da main():
std::ios::sync_with_stdio(false);\nstd::cin.tie(nullptr);\n\nA primeira linha desabilita a sincronização entre iostream e stdio. A segunda desvincula cin de cout (por padrão, antes de cada operação de entrada, cout descarrega o buffer, o que também retarda o processo). Após isso, seu código C++ começará a funcionar no mesmo nível do Python, e frequentemente mais rápido.
Verificando o resultado
\n\nAgora, descomente essas linhas em nosso teste e execute novamente. Você verá que o desempenho do C++ dispara. Em alguns benchmarks, a diferença chega a ser 10 vezes maior.