Commit a38d143d authored by Marco Amagliani's avatar Marco Amagliani

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
{
public:
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 lvl_; //!< deb_level for this function.
int id_; /*!< Unique identifier for this Enter (used in ANCHORS) */
......
......@@ -50,158 +50,91 @@ bool is_html_filename(const char* const str)
namespace Debug {
class FunctionCallSequence
{
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;
}
namespace {
bool pop()
{
if (debs_.size() > 1)
// Replace interior of < > in function name with . for brevity
void compact_name(const char* _func, std::string& _str)
{
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();
return true;
if (cnt == 0) _str.append(".");
++cnt;
}
debs_.clear();
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;
++ptr;
}
}
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
void compact_name(std::string& str) const
{
int cnt = 0;
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;
}
if (_strip_angled)
compact_name(_deb->fnct_, _str);
else
_str.append(_deb->fnct_);
}
// Get single call stack element string
void get(std::string& _str, const bool _strip_angled, bool _with_counts) const
{
if (_strip_angled) compact_name(_str);
else _str.append(name());
_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
_str.append("[");
if (!_with_counts)
_str.append("*");
else
_str.append(std::to_string(_deb->nmbr_));
_str.append("]");
}
void get_indent(std::string& _str, File* _dfile, bool _is_html);
}//namespace
}; // endclass FunctionCallSequence
//////////////////////////////////////////////////////////////////////////
class CallStack
{
std::vector<FunctionCallSequence> calls_;
int depth_;
std::vector<Enter*> calls_;
public:
CallStack() : depth_(0) {}
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(FunctionCallSequence(_func_name, _deb));
++depth_;
calls_.push_back(_deb);
}
void pop()
{
if (!calls_.back().pop())
calls_.pop_back();
--depth_;
calls_.pop_back();
}
const FunctionCallSequence* call(int _up = 0) const
const Enter* call(int _up = 0) const
{
int num = (int)calls_.size();
if (_up < num) return &calls_[num - 1 - _up];
return nullptr;
auto num = calls_.size();
if (_up < num)
return calls_[num - 1 - _up];
else
return nullptr;
}
// Read a particular call stack element
bool read(int _up, const char*& _funcname, int& _count)
{
const FunctionCallSequence* fcs = call(_up);
const Enter* fcs = call(_up);
if (fcs != nullptr)
{
_funcname = fcs->name();
_count = fcs->count(0); // Return most recent deb_enter_count
_funcname = fcs->fnct_;
_count = fcs->nmbr_; // Return most recent deb_enter_count
return true;
}
return false;
......@@ -212,17 +145,11 @@ public:
int get(std::string& _str, bool _with_counts = true) const
{
int num = (int)calls_.size();
for (int i = 0; i < num; ++i)
{
if (i > 0) _str.append("->");
calls_[i].get(_str, true, _with_counts);
}
return num;
}
Enter* prev = nullptr;
for (int i = 0; i < num; prev = calls_[i++])
add_to_string(calls_[i], _str, true, _with_counts, prev);
int depth() const
{
return depth_;
return num;
}
bool get_indent(std::string& _str, File* _dfile, const bool is_html);
......@@ -354,7 +281,6 @@ public:
at_line_start_ = false;
}
if (is_html())
{
// translate the esoteric characters used in IGM DEB_out
......@@ -681,7 +607,7 @@ public:
for (const auto& fltrs : level_selc_map_)
{
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
if (lev < fltrs.first)
lev = fltrs.first;
......@@ -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)
: 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!
global_stream().dfile()->call_stack().add(_fnct, this);
global_stream().dfile()->call_stack().add(this);
nmbr_ = _nmbr++;
......@@ -896,52 +822,6 @@ Stream& Enter::stream()
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)
{
......@@ -957,7 +837,7 @@ bool CallStack::get_indent(std::string& _str, File* _dfile, const bool is_html)
int i0 = 0;
if (!is_html) ++i0; // Don't waste whitespace on first level indent if .txt
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");
return true;
}
......
......@@ -63,6 +63,12 @@ IOutputStream& operator<<(IOutputStream& _os, const Command& _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)
{
return _os << '\"' << _path.string().c_str() << '\"';
......
......@@ -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::Type _cmd_type);
IOutputStream& operator<<(IOutputStream& _ds,
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