I'm currently making a game using C++. I eventually needed a logger, but I wasn't satisfied with any of the existing solutions. After a while, I wrote my own header called log.h:
#include <iostream>
#include <iomanip>
#include <string>
#include <ctime>
#include <fstream>
#include <sstream>
class Logger {
private:
std::string logFileName = "log.txt";
bool print = true;
bool save = true;
void log(std::string s, std::string i) {
time_t cuT;
struct tm *loT;
time(&cuT);
loT = localtime(&cuT);
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << loT->tm_hour << ':';
ss << std::setw(2) << std::setfill('0') << loT->tm_min << ':';
ss << std::setw(2) << std::setfill('0') << loT->tm_sec;
ss << i << s << "\n";
if(save) {
std::ofstream of;
of.open(logFileName, std::ios_base::app | std::ios::out);
of << ss.rdbuf();
}
if(print) {
std::cout << ss.str();
}
}
public:
void configure(std::string logFileName_, bool print_, bool save_) {
this->print = print_;
this->save = save_;
this->logFileName = logFileName_;
}
void note(std::string s) {
log(s, " NOTE: ");
}
void error(std::string s) {
log(s, " ERROR: ");
}
void warn(std::string s) {
log(s, " WARNING: ");
}
};
My library can print the current time as well as other information to the console and save this data into a file. But I did a couple of benchmarks and it turns out that my logging program is a lot slower compared to the normal std::cout.
Since speed is crucial for games, I wanted to ask whether there are ways to optimize my program or, if necessary, to improve it.
1 Answer 1
Some things to note;
- When doing time related things in C++, use
std::chrono
, notclock()
. - Your log will not work if it's used in multiple files. Instead of being in a .h file, put the definition of the logger in a cpp file and build both together.
- Use include guards for header files
#ifndef LOG_H
#define LOG_H
// Code
#endif
- Define constructors and use them properly and get rid of configure.
Log(std::string fileName, bool printToConsole, bool saveToFile) :
logFileName(fileName),
print(printToConsole),
save(saveToFile)
{
}
- Do not use underscores for naming things. General rules for c++ are class names are PascalCase and functions are camelCase.
- std::cout is slow, consider using sprintf to make it faster.
- Don't write to a file every time you call log. Opening files and writing to them is slow. Consider writing to the file on a timestamp or aggregating a few logs before writing them.
-
3\$\begingroup\$ To build on #7, try storing the logs in some sort of buffer. You could flush the buffer after a certain size, and this is common in loggers, but it's worth noting that if your program crashes, anything in the buffer disappears. Most logging systems also flush the buffer after a certain time interval too, just to minimize the likelihood of that happening to any particular message. Doing that though will probably involve adding another thread to run the pump, but it would be a good exercise. \$\endgroup\$Brendan Wilson– Brendan Wilson2020年10月20日 22:17:26 +00:00Commented Oct 20, 2020 at 22:17
-
\$\begingroup\$ An alternative to #7: do write every log to file, but keep the file on a few orders of magnitude faster RAM disk (which can be periodically copied to hard disk). If the program crashes, the RAM disk will not be affected and you can still see all your logs. If the system crashes (a much less likely event) you loose the logs since the last backup. \$\endgroup\$Pietro– Pietro2024年03月13日 13:01:36 +00:00Commented Mar 13, 2024 at 13:01
const std::string&
to avoid copy 2) add the constructor, which callconfigure
function \$\endgroup\$