Re: A small game
On Sep 18, 3:48 am, tony_in_da...@yahoo.co.uk wrote:
On Sep 17, 11:32 pm, James Kanze <james.ka...@gmail.com> wrote:
[...]
FWIW, my experience and preference generally coincides with Juha's. I
have seen many corporate C++ systems where logging is out of control:
- developers:
- put logging in during debugging and don't remove it,
- use ERROR, WARN or INFO level so they can see it without
changing to TRACE, DEBUG, DUMP or whatever might actually
be appropriate so they won't have to wade through everyone
else's trace
- some logging is found to be important but it's at TRACE/DEBUG/
DUMP and it's easier to change the process's threshold down
than find and modify all the relevant debug statements, so
production ends up with verbose logging permanently enabled.
That's interesting. My experience is that most professional
systems don't log enough.
Note that unless the file is actually synchronized (which you
can't do with std::ofstream), flushing is actually very fast,
since it basically does nothing more than copy the data from one
buffer to another. The result is that we don't use ofstream for
critical data, since we have to ensure that the writes are
synchronized. For logging, however, it's fine, and the
performance problems we've encountered in logging have always
been due to too many string operations (with their memory
allocations and frees), rather than the time spent in the system
call.
Of course, this all depends on the implementation, as well. The
default library used with Sun CC practically does a flush and a
seek in each <<, regardless of what you do, and that is too
slow. (Truss showed three or more system calls per <<. When
compiled for multi-threading, at any rate.)
Many such systems suffer noticeable and significant
performance degradation due to the I/O overheads.
Personally, I typically write important debugging/trace to
std::cerr which is line oriented anyway, and very rarely use
endl.
There is no "line oriented" (I think you mean line buffered)
output in C++. std::cerr is "unit buffered", which means that
output is flushed after each operation (each << operator). If
performance is an issue with cerr, you might try turning unit
buffering off, then using endl. Or using clog (which normally
outputs to the same destination as cerr, but without the unit
buffering and the tie to cin).
More generally, for logging and tracing, I use a hand built
classes, which outputs through a wrapper which ensures proper
formatting (trace header with timestamp, filename and line
number, following lines in the same trace record indented, trace
record ends with a '\n', etc.) and also ensures thread safety
and one, single atomic write at the end of the trace record.
The actual output is through a streambuf which can forward to
several different physical destinations, depending on severity
and configuration: for critical errors, the "flush" results in
the buffer being sent as email, for example.
I generally detest object streaming functions that choose to
flush on behalf of their caller. Note too: signal handlers
can at least attempt to flush cout/stdout in the event of a
crash.
A signal handler cannot legally call any function on std::cout,
and almost certainly doesn't know about other files. In
practice, a signal handler which calls flush in std::cout could
easily provoke additional problems if the signal arrived when a
thread was in the middle of outputting to std::cout.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34