I have to disagree. There is nothing magical going on in C++ classes if you refrain from using polymorphism. Last year I ported the low level parts of my engine from C to C++, introducing classes for Piece, Move, and Board, carefully watching for performance regression. There were none, until I replaced some low level macro's with inline functions. I accepted those as I wanted to get rid of the macro's. The performance dropped a small percentage (I don't remember what, but it was less than 5%). Probably even these could have been avoided by watching the generate assembly, I suspect there were some casting operations added under water.diep wrote:It's silly to even start an engine in C++, as you need to be hell of a C++ programmer to even 'make' it to the same speed in nps as a much worse programmer can do in C.
A logging facility
Moderators: hgm, Rebel, chrisw
-
- Posts: 201
- Joined: Thu Mar 22, 2007 7:12 pm
- Location: Netherlands
Re: A logging facility
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: A logging facility
Here's the key issue, however. Why use a specific language if you intentionally avoid the features that make it unique? Simply because instead of this:Jan Brouwer wrote:I have to disagree. There is nothing magical going on in C++ classes if you refrain from using polymorphism. Last year I ported the low level parts of my engine from C to C++, introducing classes for Piece, Move, and Board, carefully watching for performance regression. There were none, until I replaced some low level macro's with inline functions. I accepted those as I wanted to get rid of the macro's. The performance dropped a small percentage (I don't remember what, but it was less than 5%). Probably even these could have been avoided by watching the generate assembly, I suspect there were some casting operations added under water.diep wrote:It's silly to even start an engine in C++, as you need to be hell of a C++ programmer to even 'make' it to the same speed in nps as a much worse programmer can do in C.
MakeMove(board, move)
you can write it as
board.MakeMove(move)?
whoop-de-do.
If you like C++, use it. If you like C, it works just as well. And there is less risk of using features that are not exactly conducive to efficiency. Templates come to mind. AKA "code bloat". It's a matter of personal taste.
Here's the Print() function from Crafty:
void Print(int vb, char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
if (vb & display_options)
vprintf(fmt, ap);
fflush(stdout);
if (time_limit > -99 || tc_time_remaining[root_wtm] > 6000 || vb == 4095) {
va_start(ap, fmt);
if (log_file)
vfprintf(log_file, fmt, ap);
if (log_file)
fflush(log_file);
}
va_end(ap);
}
only reason it is so long are (a) using the va_arg stuff since this is a function that can have a variable number of arguments, just like the real printf() function. (b) I also avoid writing to the log file if the target time gets very small, (c) as well as add a check to see whether something should be sent to stdout, or just to the log-file, controlled with the "display command" inside Crafty. THis has not changed in 15 years now. And likely never will.
I don't see anything any more clever in stockfish than what I am doing here when it gets to the level of "efficiency" which was mentioned in the original post. Couldn't do that in Cray Blitz since fortran didn't support it, so I ended up duplicating every output statement, one for the console, one for the log file.
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: A logging facility
Ditto for mine if you look at the code. What you log and what you don't can be altered during a game trivially. And when the target time drops way down, mine automatically disables logging since any I/O has associated overhead that becomes significant when you want to search with a couple of milliseconds as the target time.Rein Halbersma wrote:I think Boost.Iostreams offers similar functionality, but also takes care of all the buffering stuff for you. E.g. tee_devicemcostalba wrote:The point is doing it _without_ writing a custom Print() function or whatever else. And without changing any existing line and with zero overhead (your Print() function is something added above the standard functions). Please don't take it personally, but I think you have not understood the topic, but believe me it is a very interesting piece of code otherwise I would had not dedicated a specific post here.bob wrote: I even wrote a Print() function
http://www.boost.org/doc/libs/1_47_0/li ... s/tee.html
What is really nice in your code is that your Logger class can toggle this behavior at runtime and *from the outside*, as you point out.
-
- Posts: 4185
- Joined: Tue Mar 14, 2006 11:34 am
- Location: Ethiopia
Re: A logging facility
You can do it from shell
But most of the time what I log is different from what I print to gui/screen so I prefer the other solution mentioned in this thread.
Code: Select all
./scorpio 2>&1 | tee -a log.txt
-
- Posts: 201
- Joined: Thu Mar 22, 2007 7:12 pm
- Location: Netherlands
Re: A logging facility
Exactly, board.MakeMove(move) is much more pleasing to the eye!bob wrote: Here's the key issue, however. Why use a specific language if you intentionally avoid the features that make it unique? Simply because instead of this:
MakeMove(board, move)
you can write it as
board.MakeMove(move)?
whoop-de-do.
And
MakeMovePrivateHelper(move)
is even better than
MakeMovePrivateHelper(board, move)
Agreed.If you like C++, use it. If you like C, it works just as well. And there is less risk of using features that are not exactly conducive to efficiency. Templates come to mind. AKA "code bloat". It's a matter of personal taste.
Turning the C code into C++ forced more structure on the program, there was all kind of arbitrary coupling that had to be resolved.
I like how the code reads much better now.
-
- Posts: 2684
- Joined: Sat Jun 14, 2008 9:17 pm
Re: A logging facility
The ony thing missing by my fancy logging facility is that it only logs std::cout, but not the commands sent by the gui, aka std::cin.
Now this limitation is no more:
https://github.com/mcostalba/Stockfish/ ... bc77175f07
It took me a couple of hours to understand how to do it because this time there was no code to copy but this makes the effort even more rewarding.....
Now this limitation is no more:
https://github.com/mcostalba/Stockfish/ ... bc77175f07
It took me a couple of hours to understand how to do it because this time there was no code to copy but this makes the effort even more rewarding.....
-
- Posts: 4185
- Joined: Tue Mar 14, 2006 11:34 am
- Location: Ethiopia
Re: A logging facility
Great you renamed your toy class to Tee... without giving me credit
At least mention there is an easier alternative to what now seems a self-serving QUESTION/ANSWER.
At least mention there is an easier alternative to what now seems a self-serving QUESTION/ANSWER.
-
- Posts: 2684
- Joined: Sat Jun 14, 2008 9:17 pm
Re: A logging facility
Ok, this is the final version, cleaned up a lot and with added direction indicators (">>" and "<<") so to easily understand from the log file which are the commands sent by GUI and which are the lines sent by engine. The Logger class is fully self contained, it doesn't need any external code, you can simply cut 'n paste the following whenever you want, as long as is a GPL code
To start / stop logging of your engine you just need:
As you can see Logger::start() is static method so you even don't need to instantiate the class. Tested on both MSVC and gcc.
P.S: This code is GPL, the original code is not but this version is completely different and substantially enhanced, totally written by me and added to Stockfish.
Code: Select all
class Logger {
Logger() : in(cin.rdbuf(), file), out(cout.rdbuf(), file) {}
~Logger() { start(false); }
struct Tie: public streambuf { // MSVC requires splitted streambuf for cin and cout
Tie(streambuf* b, ofstream& f) : buf(b), file(f) {}
int sync() { return file.rdbuf()->pubsync(), buf->pubsync(); }
int overflow(int c) { return log(buf->sputc((char)c), "<< "); }
int underflow() { return buf->sgetc(); }
int uflow() { return log(buf->sbumpc(), ">> "); }
int log(int c, const char* prefix) {
static int last = '\n';
if (last == '\n')
file.rdbuf()->sputn(prefix, 3);
return last = file.rdbuf()->sputc((char)c);
}
streambuf* buf;
ofstream& file;
};
ofstream file;
Tie in, out;
public:
static void start(bool b) {
static Logger l;
if (b && !l.file.is_open())
{
l.file.open("io_log.txt", ifstream::out | ifstream::app);
cin.rdbuf(&l.in);
cout.rdbuf(&l.out);
}
else if (!b && l.file.is_open())
{
cout.rdbuf(l.out.buf);
cin.rdbuf(l.in.buf);
l.file.close();
}
}
};
Code: Select all
Logger::start(true); // To start logging
....
Logger::start(false); // To stop logging
P.S: This code is GPL, the original code is not but this version is completely different and substantially enhanced, totally written by me and added to Stockfish.
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: A logging facility
I used to do that many years ago. But I used a few ANSI sequences to highlight a move and such, and I also use \r to overwrite a line over and over as I display each root move searched. That's all ugly stuff to log, because when you vi the file, it looks horrible. Hence my Print() function that decides what doesn't need to be logged vs what does...Daniel Shawul wrote:You can do it from shellBut most of the time what I log is different from what I print to gui/screen so I prefer the other solution mentioned in this thread.Code: Select all
./scorpio 2>&1 | tee -a log.txt
-
- Posts: 482
- Joined: Thu Oct 16, 2008 4:23 am
- Location: Milky Way
Re: A logging facility
oh my... don't you guys get tired of this kind of language wars?bob wrote:And there is less risk of using features that are not exactly conducive to efficiency. Templates come to mind. AKA "code bloat". It's a matter of personal taste.
This is a very known pattern:
Assembly guys bashing C language -->
C guys bashing C++ (vide Linus Torvalds vs some random c++ dude famous thread in the internet) -->
C++ guys bashing Java -->
Java guys bashing Scala, Python, Erlang, ....
I'd very much prefer get my ass off the couch and try learning something new..
But I'd say this:
Code: Select all
x = std::abs(y);
Code: Select all
x = labs(y); // or
x = cabs(y); // or
x = labs(y); // whatever ....
...
Ben-Hur Carlos Langoni Junior
http://sourceforge.net/projects/redqueenchess/
http://sourceforge.net/projects/redqueenchess/