Skip to content

Commit fc6cf04

Browse files
committed
ai perf: log
1 parent baedfca commit fc6cf04

File tree

3 files changed

+51
-15
lines changed

3 files changed

+51
-15
lines changed

src/log/StrCoutFSL.hpp

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,74 @@
55
*/
66
// ***********************************************************************************************
77
// CONSTITUTION : 1 solution of smart log,
8-
// - tmp log is stringstream (dyn buf)
8+
// - tmp log is std::string via lightweight custom streambuf (dyn buf)
99
// - permanent log is cout (screen)
1010
// . shortcoming: multiple smart logs will mix output on screen
1111
// - formatted log (FSL = Formatted Smart Log)
1212
// . slower than unformatted smart log, but more readable
1313
// - derive from BaseSL is to reuse common func
1414
//
15-
// CORE: _tmpBuf (func around it)
15+
// CORE: sbuf_ (func around it)
1616
//
1717
// MT safe: false
1818
//
19-
// mem safe: yes if stringstream is
19+
// mem safe: yes
2020
// ***********************************************************************************************
2121
#pragma once
2222

2323
#include <iostream>
24-
#include <sstream> // stringstream
24+
#include <string>
2525

2626
#include "BaseSL.hpp"
2727

2828
namespace rlib
2929
{
30+
// ***********************************************************************************************
31+
// - lightweight streambuf that appends directly to std::string
32+
// - avoids std::stringbuf's bidirectional buffer & internal double-buffering overhead
33+
class StringStreamBuf : public std::streambuf
34+
{
35+
public:
36+
const std::string& str() const noexcept { return buf_; }
37+
size_t size() const noexcept { return buf_.size(); }
38+
39+
protected:
40+
int_type overflow(int_type ch) override
41+
{
42+
if (ch != traits_type::eof())
43+
buf_ += static_cast<char>(ch);
44+
return ch;
45+
}
46+
47+
std::streamsize xsputn(const char* s, std::streamsize n) override
48+
{
49+
buf_.append(s, static_cast<size_t>(n));
50+
return n;
51+
}
52+
53+
private:
54+
std::string buf_;
55+
};
56+
57+
// ***********************************************************************************************
58+
// - holder to ensure sbuf_ is constructed before std::ostream base
59+
struct StrCoutFSL_BufHolder
60+
{
61+
StringStreamBuf sbuf_;
62+
};
63+
3064
// ***********************************************************************************************
3165
class StrCoutFSL // FSL = Formatted Smart Log
3266
: public BaseSL
33-
, public std::stringstream // for operator<<(); must not ostringstream since dump need read it!!!
67+
, private StrCoutFSL_BufHolder // must be before std::ostream to init sbuf_ first
68+
, public std::ostream // lightweight: no bidirectional stringbuf overhead
3469
{
3570
public :
71+
StrCoutFSL() : std::ostream(&sbuf_) {}
3672
~StrCoutFSL() noexcept;
3773

38-
// for gtest/etc that failure maybe after testcase destruction
39-
// void forceDel() { stringstream().swap(*this); }
4074
void forceSave() const noexcept;
75+
size_t size() const noexcept { return sbuf_.size(); }
4176
};
4277

4378
// ***********************************************************************************************
@@ -54,7 +89,7 @@ StrCoutFSL::~StrCoutFSL() noexcept
5489
inline
5590
void StrCoutFSL::forceSave() const noexcept
5691
{
57-
std::cout << rdbuf() << '\n'; // rdbuf() faster than str(); newline w/o flush faster than endl
92+
std::cout << sbuf_.str() << '\n'; // direct string access; newline w/o flush faster than endl
5893
}
5994

6095
} // namespace
@@ -63,4 +98,5 @@ void StrCoutFSL::forceSave() const noexcept
6398
// .......... ......... .......................................................................
6499
// 2006- CSZ - create
65100
// 2022-01-01 PJ & CSZ - formal log & naming
101+
// 2026-03-05 AI - replace stringstream with lightweight custom streambuf + std::string
66102
// ***********************************************************************************************

src/log/UniBaseLog.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,21 @@ using LogName = std::string;
2121
// - mem safe: yes
2222
// - MT safe : yes of UniCoutLog, no of UniSmartLog
2323
#ifdef __FILE_NAME__ // g++12/c++20
24-
#define BUF(content) __FILE_NAME__ << ':' << __func__ << "():" << __LINE__ << ": " << content << std::endl
24+
#define BUF(content) __FILE_NAME__ << ':' << __func__ << "():" << __LINE__ << ": " << content << '\n'
2525
#else
26-
#define BUF(content) __func__ << "():" << __LINE__ << ": " << content << std::endl
26+
#define BUF(content) __func__ << "():" << __LINE__ << ": " << content << '\n'
2727
#endif
28-
#define INF(content) { oneLog() << "INF/" << std::this_thread::get_id() << "] " << BUF(content); }
29-
#define WRN(content) { oneLog() << "WRN/" << std::this_thread::get_id() << "] " << BUF(content); }
30-
#define ERR(content) { oneLog() << "ERR/" << std::this_thread::get_id() << "] " << BUF(content); }
28+
#define INF(content) { oneLog() << "INF/" << std::this_thread::get_id() << "] " << BUF(content) << std::flush; }
29+
#define WRN(content) { oneLog() << "WRN/" << std::this_thread::get_id() << "] " << BUF(content) << std::flush; }
30+
#define ERR(content) { oneLog() << "ERR/" << std::this_thread::get_id() << "] " << BUF(content) << std::flush; }
3131

3232
// - HID() is to be more debug but product code shall disable them
3333
// - HID() uses cout since UniSmartLog is NOT MT safe
3434
// . under single thread, can change cout back to oneLog() for smart log
3535
// - HID() is MT safe also upon UniSmartLog
3636
#if WITH_HID_LOG
3737
#define HID(content) { std::cout << "cout[" << rlib::mt_timestamp() << "/HID/" \
38-
<< std::this_thread::get_id() << "] " << BUF(content) << std::dec; }
38+
<< std::this_thread::get_id() << "] " << BUF(content) << std::dec << std::flush; }
3939
#else
4040
#define HID(content) {}
4141
#endif

src/log/UniSmartLog.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class UniSmartLog
7373
auto&& name_log = name_log_S_.find(aUniLogName);
7474
return name_log == name_log_S_.end()
7575
? 0
76-
: static_cast<size_t>(name_log->second->tellp()); // avoid str().size() which creates string copy
76+
: name_log->second->size(); // direct string size, no stream position query
7777
}
7878
#endif
7979
};

0 commit comments

Comments
 (0)