Commit a38d143d authored by Marco Amagliani's avatar Marco Amagliani
Browse files

performance improvement. The debug system added a meaningful slowdown for test...

performance improvement. The debug system added a meaningful slowdown for test exectution storing the call stack. This submission avoids some useless memory allocation and improves meaningfully the test speed.
Fixes https://jira.autodesk.com/browse/REFORM-188 .

[git-p4: depot-paths = "//ReForm/ReForm/main/Base/": change = 14211]
parent a1d43491
...@@ -56,6 +56,7 @@ class Enter ...@@ -56,6 +56,7 @@ class Enter
{ {
public: public:
const char* flnm_; //!< File name for this DEB_enter const char* flnm_; //!< File name for this DEB_enter
const char* fnct_; //!< Function name for this DEB_enter
int nmbr_; //!< deb_nmbr for this function. int nmbr_; //!< deb_nmbr for this function.
int lvl_; //!< deb_level for this function. int lvl_; //!< deb_level for this function.
int id_; /*!< Unique identifier for this Enter (used in ANCHORS) */ int id_; /*!< Unique identifier for this Enter (used in ANCHORS) */
......
...@@ -50,158 +50,91 @@ bool is_html_filename(const char* const str) ...@@ -50,158 +50,91 @@ bool is_html_filename(const char* const str)
namespace Debug { namespace Debug {
class FunctionCallSequence namespace {
{
std::string func_name_;
std::vector<Enter*> debs_; // These may not have sequential counts when multithreaded.
public:
FunctionCallSequence(const char* _func_name, Enter* _deb)
: func_name_(_func_name)
{
debs_.push_back(_deb);
}
~FunctionCallSequence() {}
bool add(const char* _func_name, Enter* _deb)
{
if (func_name_ == _func_name)
{
debs_.push_back(_deb);
return true;
}
return false;
}
bool pop() // Replace interior of < > in function name with . for brevity
{ void compact_name(const char* _func, std::string& _str)
if (debs_.size() > 1) {
int cnt = 0;
const char* ptr = _func;
while (ptr && (*ptr != '\0'))
{
char c = *ptr;
if (c == '>') --cnt;
if (cnt == 0) _str.append(1, c);
if (c == '<')
{ {
debs_.pop_back(); if (cnt == 0) _str.append(".");
return true; ++cnt;
} }
debs_.clear(); ++ptr;
return false;
}
int number_calls() const
{
if (!this) return 0;
return (int)debs_.size();
}
int count(int i = 0) const
{
int num = number_calls();
if (i < num) return debs_[num - 1 - i]->nmbr_;
return -1;
} }
}
const char* name() const // Add to the string the call stack element string
void add_to_string(const Enter* _deb, std::string& _str,
const bool _strip_angled, const bool _with_counts,
const Enter* _prev)
{
if (_prev == nullptr || strcmp(_prev->fnct_, _deb->fnct_) != 0)
{ {
return func_name_.c_str(); // Writes the function name if it is not the same as previous
} // function in the call stack.
if (_prev != nullptr)
_str.append("->");
// Replace interior of < > in function name with . for brevity if (_strip_angled)
void compact_name(std::string& str) const compact_name(_deb->fnct_, _str);
{ else
int cnt = 0; _str.append(_deb->fnct_);
const char* ptr = func_name_.c_str();
while (ptr && (*ptr != '\0'))
{
char c = *ptr;
if (c == '>') --cnt;
if (cnt == 0) str.append(1, c);
if (c == '<')
{
if (cnt == 0) str.append(".");
++cnt;
}
++ptr;
}
} }
// Get single call stack element string _str.append("[");
void get(std::string& _str, const bool _strip_angled, bool _with_counts) const if (!_with_counts)
{ _str.append("*");
if (_strip_angled) compact_name(_str); else
else _str.append(name()); _str.append(std::to_string(_deb->nmbr_));
_str.append("["); _str.append("]");
if (_with_counts) }
{
int num = number_calls();
int prev = -2;
int seq_cnt = 0;
for (int i = 0; i < num; ++i)
{
int cnt = debs_[i]->nmbr_;
if (cnt != prev + 1)
{
char buffer[64];
if (seq_cnt > 0)
{
_str.append("-");
sprintf_s(buffer, sizeof(buffer), "%i", prev);
_str.append(buffer);
}
if (i > 0) _str.append(",");
sprintf_s(buffer, sizeof(buffer), "%i", cnt);
_str.append(buffer);
seq_cnt = 0;
}
else
++seq_cnt;
prev = cnt;
} // endfor i
} // endif _with_counts
else
_str.append("*");
_str.append("]");
} // endfunc get
void get_indent(std::string& _str, File* _dfile, bool _is_html); }//namespace
}; // endclass FunctionCallSequence
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
class CallStack class CallStack
{ {
std::vector<FunctionCallSequence> calls_; std::vector<Enter*> calls_;
int depth_;
public: public:
CallStack() : depth_(0) {} CallStack() {}
~CallStack() {} ~CallStack() {}
void add(const char* _func_name, Enter* _deb) void add(Enter* _deb)
{ {
if (calls_.empty() || !calls_.back().add(_func_name, _deb)) calls_.push_back(_deb);
calls_.push_back(FunctionCallSequence(_func_name, _deb));
++depth_;
} }
void pop() void pop()
{ {
if (!calls_.back().pop()) calls_.pop_back();
calls_.pop_back();
--depth_;
} }
const FunctionCallSequence* call(int _up = 0) const const Enter* call(int _up = 0) const
{ {
int num = (int)calls_.size(); auto num = calls_.size();
if (_up < num) return &calls_[num - 1 - _up]; if (_up < num)
return nullptr; return calls_[num - 1 - _up];
else
return nullptr;
} }
// Read a particular call stack element // Read a particular call stack element
bool read(int _up, const char*& _funcname, int& _count) bool read(int _up, const char*& _funcname, int& _count)
{ {
const FunctionCallSequence* fcs = call(_up); const Enter* fcs = call(_up);
if (fcs != nullptr) if (fcs != nullptr)
{ {
_funcname = fcs->name(); _funcname = fcs->fnct_;
_count = fcs->count(0); // Return most recent deb_enter_count _count = fcs->nmbr_; // Return most recent deb_enter_count
return true; return true;
} }
return false; return false;
...@@ -212,17 +145,11 @@ public: ...@@ -212,17 +145,11 @@ public:
int get(std::string& _str, bool _with_counts = true) const int get(std::string& _str, bool _with_counts = true) const
{ {
int num = (int)calls_.size(); int num = (int)calls_.size();
for (int i = 0; i < num; ++i) Enter* prev = nullptr;
{ for (int i = 0; i < num; prev = calls_[i++])
if (i > 0) _str.append("->"); add_to_string(calls_[i], _str, true, _with_counts, prev);
calls_[i].get(_str, true, _with_counts);
}
return num;
}
int depth() const return num;
{
return depth_;
} }
bool get_indent(std::string& _str, File* _dfile, const bool is_html); bool get_indent(std::string& _str, File* _dfile, const bool is_html);
...@@ -354,7 +281,6 @@ public: ...@@ -354,7 +281,6 @@ public:
at_line_start_ = false; at_line_start_ = false;
} }
if (is_html()) if (is_html())
{ {
// translate the esoteric characters used in IGM DEB_out // translate the esoteric characters used in IGM DEB_out
...@@ -681,7 +607,7 @@ public: ...@@ -681,7 +607,7 @@ public:
for (const auto& fltrs : level_selc_map_) for (const auto& fltrs : level_selc_map_)
{ {
if (fltrs.second.select_file(_flnm) || if (fltrs.second.select_file(_flnm) ||
fltrs.second.select_function(call_stack_.call()->name())) fltrs.second.select_function(call_stack_.call()->fnct_))
{// continue this iteration until the maximum allowed level if found {// continue this iteration until the maximum allowed level if found
if (lev < fltrs.first) if (lev < fltrs.first)
lev = fltrs.first; lev = fltrs.first;
...@@ -822,11 +748,11 @@ void error(const std::string& _err, const Base::CodeLink& _lnk) ...@@ -822,11 +748,11 @@ void error(const std::string& _err, const Base::CodeLink& _lnk)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
Enter::Enter(const char* const _flnm, const char* const _fnct, Enter::Enter(const char* const _flnm, const char* const _fnct,
int& _nmbr, int& _lvl) int& _nmbr, int& _lvl)
: flnm_(_flnm), outs_(0), lns_(0) : flnm_(_flnm), fnct_(_fnct), outs_(0), lns_(0)
{// TODO: for thread-safety we will need to make the constructor body atomic! {// TODO: for thread-safety we will need to make the constructor body atomic!
global_stream().dfile()->call_stack().add(_fnct, this); global_stream().dfile()->call_stack().add(this);
nmbr_ = _nmbr++; nmbr_ = _nmbr++;
...@@ -896,52 +822,6 @@ Stream& Enter::stream() ...@@ -896,52 +822,6 @@ Stream& Enter::stream()
return ds; return ds;
} }
void FunctionCallSequence::get_indent(std::string& _str, File* _dfile, bool _is_html)
{
int num = number_calls();
for (int i = 0; i < num; ++i)
{
Enter* deb = debs_[i];
if (_is_html)
{
/* HTML indent element is <L> with span title the name and count
of the function and with < linking to the entry anchor (if present) and
> linking to the exit anchor (will be present).
L is the first letter of the module name */
char hovert[1024];
sprintf_s(hovert, sizeof(hovert), "%s[%i]", func_name_.c_str(), deb->nmbr_);
int col = 0xFFFFFF;
char buffer[1024];
sprintf_s(buffer, sizeof(buffer), "<FONT COLOR=\"#%06X\">.", col);
_dfile->hover(_str, std::string(hovert), true);
_str.append(buffer);
std::string cstk;
//impl->call_stack().get(cstk);
if ((deb->outs_ > 0) && _dfile->link_to(_str, deb->id_, "enter", cstk, true))
{
_str.append("&lt;");
_dfile->link_to(_str, deb->id_, "enter", cstk, false);
}
else _str.append("&lt;");
_str.append(deb->flnm_, 1);
if (_dfile->link_to(_str, deb->id_, "exit", cstk, true))
{
_str.append("&gt;");
_dfile->link_to(_str, deb->id_, "exit", cstk, false);
++deb->lns_;
}
_dfile->hover(_str, std::string(hovert), false);
_str.append("</FONT>");
} // endif html
else _str.append(" ");
}
}
bool CallStack::get_indent(std::string& _str, File* _dfile, const bool is_html) bool CallStack::get_indent(std::string& _str, File* _dfile, const bool is_html)
{ {
...@@ -957,7 +837,7 @@ bool CallStack::get_indent(std::string& _str, File* _dfile, const bool is_html) ...@@ -957,7 +837,7 @@ bool CallStack::get_indent(std::string& _str, File* _dfile, const bool is_html)
int i0 = 0; int i0 = 0;
if (!is_html) ++i0; // Don't waste whitespace on first level indent if .txt if (!is_html) ++i0; // Don't waste whitespace on first level indent if .txt
for (int i = i0; i < num; ++i) for (int i = i0; i < num; ++i)
calls_[i].get_indent(_str, _dfile, is_html); _str.append(" ");
if (is_html) _str.append(":&nbsp;</FONT>\n"); if (is_html) _str.append(":&nbsp;</FONT>\n");
return true; return true;
} }
......
...@@ -63,6 +63,12 @@ IOutputStream& operator<<(IOutputStream& _os, const Command& _co) ...@@ -63,6 +63,12 @@ IOutputStream& operator<<(IOutputStream& _os, const Command& _co)
return _os.print(_co); return _os.print(_co);
} }
IOutputStream& operator<<(IOutputStream& _os, const Command::Type _cmd_type)
{
return _os.print(Command(_cmd_type));
}
IOutputStream& operator<<(IOutputStream& _os, const boost::filesystem::path& _path) IOutputStream& operator<<(IOutputStream& _os, const boost::filesystem::path& _path)
{ {
return _os << '\"' << _path.string().c_str() << '\"'; return _os << '\"' << _path.string().c_str() << '\"';
......
...@@ -73,6 +73,8 @@ IOutputStream& operator<<(IOutputStream& _ds, const std::string& _s); ...@@ -73,6 +73,8 @@ IOutputStream& operator<<(IOutputStream& _ds, const std::string& _s);
IOutputStream& operator<<(IOutputStream& _ds, const Command& _co); IOutputStream& operator<<(IOutputStream& _ds, const Command& _co);
IOutputStream& operator<<(IOutputStream& _ds, const Command::Type _cmd_type);
IOutputStream& operator<<(IOutputStream& _ds, IOutputStream& operator<<(IOutputStream& _ds,
const boost::filesystem::path& _path); const boost::filesystem::path& _path);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment