I wished to comparison speechmaking traces of drawstring enter from stdin utilizing Python and C++ and was shocked to seat my C++ codification tally an command of magnitude slower than the equal Python codification. Since my C++ is rusty and I'm not but an adept Pythonista, delight archer maine if I'm doing thing incorrect oregon if I'm misunderstanding thing.
(TLDR reply: see the message: cin.sync_with_stdio(false)
oregon conscionable usage fgets
alternatively.
TLDR outcomes: scroll each the manner behind to the bottommost of my motion and expression astatine the array.)
C++ codification:
#include <iostream>#include <time.h>using namespace std;int main() { string input_line; long line_count = 0; time_t start = time(NULL); int sec; int lps; while (cin) { getline(cin, input_line); if (!cin.eof()) line_count++; }; sec = (int) time(NULL) - start; cerr << "Read " << line_count << " lines in " << sec << " seconds."; if (sec > 0) { lps = line_count / sec; cerr << " LPS: " << lps << endl; } else cerr << endl; return 0;}// Compiled with:// g++ -O3 -o readline_test_cpp foo.cpp
Python Equal:
#!/usr/bin/env pythonimport timeimport syscount = 0start = time.time()for line in sys.stdin: count += 1delta_sec = int(time.time() - start_time)if delta_sec >= 0: lines_per_sec = int(round(count/delta_sec)) print("Read {0} lines in {1} seconds. LPS: {2}".format(count, delta_sec, lines_per_sec))
Present are my outcomes:
$ cat test_lines | ./readline_test_cppRead 5570000 lines in 9 seconds. LPS: 618889$ cat test_lines | ./readline_test.pyRead 5570000 lines in 1 seconds. LPS: 5570000
I ought to line that I tried this some nether Mac OS X v10.6.Eight (Snowfall Leopard) and Linux 2.6.32 (Reddish Chapeau Linux 6.2). The erstwhile is a MacBook Professional, and the second is a precise beefy server, not that this is excessively pertinent.
$ for i in {1..5}; do echo "Test run $i at `date`"; echo -n "CPP:"; cat test_lines | ./readline_test_cpp ; echo -n "Python:"; cat test_lines | ./readline_test.py ; done
Test run 1 at Mon Feb 20 21:29:28 EST 2012CPP: Read 5570001 lines in 9 seconds. LPS: 618889Python:Read 5570000 lines in 1 seconds. LPS: 5570000Test run 2 at Mon Feb 20 21:29:39 EST 2012CPP: Read 5570001 lines in 9 seconds. LPS: 618889Python:Read 5570000 lines in 1 seconds. LPS: 5570000Test run 3 at Mon Feb 20 21:29:50 EST 2012CPP: Read 5570001 lines in 9 seconds. LPS: 618889Python:Read 5570000 lines in 1 seconds. LPS: 5570000Test run 4 at Mon Feb 20 21:30:01 EST 2012CPP: Read 5570001 lines in 9 seconds. LPS: 618889Python:Read 5570000 lines in 1 seconds. LPS: 5570000Test run 5 at Mon Feb 20 21:30:11 EST 2012CPP: Read 5570001 lines in 10 seconds. LPS: 557000Python:Read 5570000 lines in 1 seconds. LPS: 5570000
Small benchmark addendum and recap
For completeness, I idea I'd replace the publication velocity for the aforesaid record connected the aforesaid container with the first (synced) C++ codification. Once more, this is for a 100M formation record connected a accelerated disk. Present's the examination, with respective options/approaches:
Implementation | Traces per 2nd |
---|---|
python (default) | Three,571,428 |
cin (default/naive) | 819,672 |
cin (nary sync) | 12,500,000 |
fgets | 14,285,714 |
wc (not just examination) | Fifty four,644,808 |
tl;dr: Due to the fact that of antithetic default settings successful C++ requiring much scheme calls.
By default, cin
is synchronized with stdio, which causes it to debar immoderate enter buffering. If you adhd this to the apical of your chief, you ought to seat overmuch amended show:
std::ios_base::sync_with_stdio(false);
Usually, once an enter watercourse is buffered, alternatively of speechmaking 1 quality astatine a clip, the watercourse volition beryllium publication successful bigger chunks. This reduces the figure of scheme calls, which are usually comparatively costly. Nevertheless, since the FILE*
based mostly stdio
and iostreams
frequently person abstracted implementations and so abstracted buffers, this might pb to a job if some have been utilized unneurotic. For illustration:
int myvalue1;cin >> myvalue1;int myvalue2;scanf("%d",&myvalue2);
If much enter was publication by cin
than it really wanted, past the 2nd integer worth wouldn't beryllium disposable for the scanf
relation, which has its ain autarkic buffer. This would pb to surprising outcomes.
To debar this, by default, streams are synchronized with stdio
. 1 communal manner to accomplish this is to person cin
publication all quality 1 astatine a clip arsenic wanted utilizing stdio
capabilities. Unluckily, this introduces a batch of overhead. For tiny quantities of enter, this isn't a large job, however once you are speechmaking thousands and thousands of strains, the show punishment is important.
Fortuitously, the room designers determined that you ought to besides beryllium capable to disable this characteristic to acquire improved show if you knew what you have been doing, truthful they supplied the sync_with_stdio
methodology. From this nexus (accent added):
If the synchronization is turned disconnected, the C++ modular streams are allowed to buffer their I/O independently, which whitethorn beryllium significantly quicker successful any circumstances.
Conscionable retired of curiosity I've taken a expression astatine what occurs nether the hood, and I've utilized dtruss/strace connected all trial.
C++
./a.out < inSaw 6512403 lines in 8 seconds. Crunch speed: 814050
syscalls sudo dtruss -c ./a.out < in
CALL COUNT__mac_syscall 1<snip>open 6pread 8mprotect 17mmap 22stat64 30read_nocancel 25958
Python
./a.py < inRead 6512402 lines in 1 seconds. LPS: 6512402
syscalls sudo dtruss -c ./a.py < in
CALL COUNT__mac_syscall 1<snip>open 5pread 8mprotect 17mmap 21stat64 29
Once dealing with show-captious purposes, the velocity of enter processing tin beryllium a important bottleneck. It’s a communal reflection that speechmaking enter from stdin successful C++ seems to beryllium importantly slower than doing the aforesaid successful Python. This quality frequently surprises builders, particularly these fresh to some languages. Knowing the causes down this show disparity entails wanting astatine the modular libraries, the inherent quality of the languages, and the emblematic usage circumstances for all. Fto's research the underlying elements that lend to C++'s seemingly slower enter processing from stdin in contrast to Python.
Wherefore Does C++ Look Slower astatine Processing Enter from stdin In contrast to Python?
The cognition that C++ is slower astatine processing enter from stdin in contrast to Python frequently stems from the default configurations and communal utilization patterns of the modular enter/output libraries successful all communication. Successful C++, the iostream room, particularly once utilized with its default settings, introduces overhead that tin importantly contact show. This overhead comes from synchronization with C's modular enter/output streams and the default buffering behaviour. Connected the another manus, Python's enter mechanisms, piece besides having their ain overhead, are frequently utilized successful methods that reduce this contact, oregon payment from underlying optimizations successful the interpreter. So, it's not needfully that C++ is inherently slower, however instead the manner it's generally utilized that leads to this reflection.
Synchronization Overhead successful C++ iostream
1 great contributor to C++'s slower enter processing is the synchronization betwixt C++'s iostream and C's stdio streams. By default, iostream is synchronized with stdio, guaranteeing that operations carried out connected std::cin and std::cout are decently interleaved with operations carried out connected stdin and stdout. Piece this synchronization is utile successful definite eventualities, it introduces a important overhead, arsenic it requires the modular streams to coordinate with all another. Disabling this synchronization tin pb to significant show enhancements. See the contact of this synchronization overhead once dealing with ample inputs, arsenic it turns into a noticeable bottleneck. It is important to retrieve that disabling synchronization tin origin points if you premix C++ iostream and C stdio capabilities.
Methods to Optimize C++ Enter Processing
Piece C++ whitethorn look slower retired-of-the-container, it affords respective methods to optimize enter processing and accomplish show comparable to, oregon equal amended than, Python. These optimizations affect disabling synchronization with C's modular streams, utilizing businesslike buffering methods, and leveraging sooner enter strategies once due. By knowing and making use of these methods, builders tin unlock the actual possible of C++ for advanced-show enter processing. The circumstantial decisions volition be connected the quality of the enter information and the necessities of the exertion, however the broad rules stay the aforesaid: reduce overhead and maximize ratio.
Disabling Synchronization and Optimizing Buffering
To importantly better C++ enter processing velocity, you tin disable the synchronization betwixt iostream and stdio by calling std::ios::sync_with_stdio(mendacious). Moreover, you tin untie std::cin and std::cout by calling cin.necktie(NULL). This prevents std::cout from being flushed all clip std::cin is utilized. Moreover, see utilizing getchar_unlocked() oregon fread() for equal sooner enter, although these strategies necessitate cautious dealing with to debar errors. These strategies bypass the modular iostream mechanisms, offering less-flat entree that tin beryllium sooner. Present's an illustration of however to disable synchronization:
include <iostream> int main() { std::ios::sync_with_stdio(false); std::cin.tie(NULL); int n; std::cin >> n; // Process input return 0; }
Selecting the Correct Enter Methodology
Deciding on the due enter methodology tin dramatically impact show. Piece std::cin is handy, it whitethorn not beryllium the about businesslike prime for ample inputs. Capabilities similar scanf from C's stdio room oregon equal less-flat capabilities similar fread tin supply important speedups. Nevertheless, these strategies necessitate cautious dealing with of enter codecs and mistake circumstances. For case, scanf is mostly sooner than std::cin, however it lacks the kind condition and objection dealing with of iostream. See the commercial-offs betwixt velocity and condition once selecting an enter methodology. To larn much, present is any further speechmaking connected scanf vs cin a comparative investigation successful c++.
Who is listening linked a mounted TCP larboard linked Mac OS X?
Evaluating C++ and Python Enter Strategies
To amended realize the show variations, it's utile to comparison the emblematic enter strategies utilized successful C++ and Python. C++ frequently depends connected std::cin and std::cout from the iostream room, piece Python generally makes use of enter() and record-speechmaking strategies. The array beneath outlines the cardinal variations and show implications of these strategies. Support successful head that the existent show tin change relying connected the circumstantial usage lawsuit and the dimension of the enter.
Characteristic | C++ (iostream) | Python (enter()) |
---|---|---|
Default Synchronization | Synchronized with stdio | Nary synchronization |
Buffering | Buffered | Formation-buffered |
Kind Condition | Kind-harmless | Returns drawstring, requires parsing |
Mistake Dealing with | Exceptions | Exceptions |
Velocity (Unoptimized) | Slower | Sooner |
Velocity (Optimized) | Sooner | Comparable |
Successful abstract, the first slowness of C++ enter processing from stdin, once in contrast to Python, frequently outcomes from default settings instead than inherent limitations. By disabling stdio synchronization, optimizing buffering, and selecting the correct enter strategies, C++ tin accomplish show ranges that both lucifer oregon surpass these of Python. Knowing these nuances empowers builders to compose businesslike and advanced-performing C++ codification. To additional research this subject, see speechmaking much astir accelerated I/O successful C++. This knowing is cardinal for anybody running connected show-delicate purposes.