Add CPU wait

This commit is contained in:
lsv 2024-09-29 15:58:35 +05:00
parent 6e70c87f3e
commit fd61d111d5
6 changed files with 434 additions and 228 deletions

View file

@ -197,7 +197,8 @@ wxColour getColorFromString(const wxString& str) {
unsigned long tmp;
int scanned = wxSscanf(strcolor, "%lx", &tmp);
if (scanned == 1) {
wxColour c(strc);
wxColour c;
c.Set((tmp>>16) & 0xFF | (tmp & 0x00FF00)| (tmp & 0xFF)<<16);
if (c.IsOk()) return c;
}
}

View file

@ -38,11 +38,12 @@ EVT_KILL_FOCUS(SimpleTransientPopup::OnKillFocus)
wxEND_EVENT_TABLE()
SimpleTransientPopup::SimpleTransientPopup(wxWindow* parent, bool scrolled, wxTopActivity* small_ctl, wxPoint p,wxString title)
:wxFrame(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxFRAME_TOOL_WINDOW | wxCLOSE_BOX | wxTINY_CAPTION)
:wxFrame(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxFRAME_NO_TASKBAR | wxRESIZE_BORDER | wxCLOSE_BOX | wxMAXIMIZE_BOX |wxTINY_CAPTION)
{
m_panel = new wxScrolledWindow(this, wxID_ANY);
//m_panel = new wxScrolledWindow(this, wxID_ANY);
m_panel = new wxPanel(this, wxID_ANY);
m_panel->SetBackgroundColour(*wxLIGHT_GREY);
wxBoxSizer* sizerF = new wxBoxSizer(wxVERTICAL);
m_panel->Bind(wxEVT_MOTION, &SimpleTransientPopup::OnMouse, this);
WaitSample* w = NULL;
int agg, right_g;
@ -50,8 +51,11 @@ SimpleTransientPopup::SimpleTransientPopup(wxWindow* parent, bool scrolled, wxTo
wxSize top_sz = wxSize(1000, 500);
top = new wxTopActivity(m_panel, w, top_sz);
top->setViewRange(agg, right_g);
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
topSizer->Add(top, 0, wxCENTRE | wxALL, 5);
// wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
wxFlexGridSizer* topSizer = new wxFlexGridSizer(1);
topSizer->AddGrowableCol(0);
topSizer->AddGrowableRow(0);
topSizer->Add(top, 1, wxEXPAND, 5);
int style = 0;
dvc = new topDataViewCtrl(m_panel, wxID_ANY,
wxDefaultPosition,
@ -59,14 +63,15 @@ SimpleTransientPopup::SimpleTransientPopup(wxWindow* parent, bool scrolled, wxTo
style,
top
);
topSizer->Add(dvc, 0, wxEXPAND|wxALL, 2);
//dvc->SetMinSize(wxSize(-1,60));
m_index_list_model = new MyIndexListModel(w);
dvc->AssociateModel(m_index_list_model.get());
dvc->BuildColumn(0);
dvc->CalcRowsDataView(true, true);
m_taskTimer.Start(100);
m_taskTimer.Bind(wxEVT_TIMER, &SimpleTransientPopup::OnTimerEvent, this);
topSizer->Add(dvc, 0, wxCENTRE | wxALL, 2);
//dvc->AppendTextColumn("Pid", 0);
//dvc->AppendTextColumn("String2", 1);
wxPoint posScreen;
@ -87,30 +92,23 @@ SimpleTransientPopup::SimpleTransientPopup(wxWindow* parent, bool scrolled, wxTo
if (p.x + top_sz.x > sizeScreen.x) p.x = sizeScreen.x - top_sz.x - 20;
if (p.y + top_sz.y > sizeScreen.y) p.y = sizeScreen.y - top_sz.y - 20;
Move(p);
if (scrolled)
{
// Add a big window to ensure that scrollbars are shown when we set the
// panel size to a lesser size below.
topSizer->Add(new wxPanel(m_panel, wxID_ANY, wxDefaultPosition,
wxSize(600, 900)));
}
//topSizer->Add(new wxPanel(m_panel, wxID_ANY, wxDefaultPosition, wxSize(600, 900)));
m_panel->SetSizer(topSizer);
if (scrolled)
{
// Set the fixed size to ensure that the scrollbars are shown.
m_panel->SetSize(300, 300);
// And also actually enable them.
m_panel->SetScrollRate(10, 10);
}
else
{
//this->SetSizer(topSizer);
// Use the fitting size for the panel if we don't need scrollbars.
topSizer->Fit(m_panel);
}
SetClientSize(m_panel->GetSize());
m_panel->Layout();
//topSizer->Fit(m_panel);
sizerF->Add(m_panel, 1, wxCENTRE | wxALL| wxEXPAND, 2);
SetSizer(sizerF);
Layout();
//SetSize(m_panel->GetSize());
// SetClientSize(m_panel->GetSize());
// Layout();
Fit();
SetMinSize(wxSize(500, 350));
}
SimpleTransientPopup::~SimpleTransientPopup()
@ -124,6 +122,10 @@ SimpleTransientPopup::~SimpleTransientPopup()
void SimpleTransientPopup::OnSize(wxSizeEvent& event)
{
//wxLogMessage("%p SimpleTransientPopup::OnSize", this);
//Fit();
//m_panel->Layout();
Layout();
// Fit();
event.Skip();
}
@ -233,9 +235,10 @@ void wxTopActivity::SetFilter(long long qid) {
void wxTopActivity::render(wxDC& dc)
{
wxColour c;
dc.SetBrush(*wxGREY_BRUSH);
// wxRect r=dc.GetWindow()->GetClientRect();
//dc.SetBrush(*wxGREY_BRUSH);
dc.SetBrush(ws->GetColorGui(Color_GUI::BG));
//dc.SetPen();
dc.SetTextForeground(ws->GetColorGui(Color_GUI::LABEL));
wxRect r = GetClientRect();
wxSize sz = r.GetSize();
//dc.DrawRectangle(0, 0, r.width, r.height);
@ -525,8 +528,8 @@ void wxTopActivity::render(wxDC& dc)
t.height = yy - t.y + 3;
if (LegengWidth > 0) dc.DrawRectangle(t.x, t.y, t.width, yy - t.y + 3);
dc.SetBrush(*wxGREY_BRUSH);
dc.SetPen(*wxBLACK_PEN);
dc.SetBrush(ws->GetColorGui(Color_GUI::BG));
dc.SetPen(ws->GetColorGui(Color_GUI::LABEL));
dc.DrawRectangle(a.x, a.y, a.width, a.height);
wxTimeSpan maxY = yAxis[0];
wxLongLong t_maxYms = maxY.GetMilliseconds();
@ -546,12 +549,12 @@ void wxTopActivity::render(wxDC& dc)
y = a.y + a.height - i * (a.height / nlab);
dc.DrawText(txt, x - dx.x - 4, y - dx.y / 2);
fl += delta;
dc.SetPen(*wxBLACK_PEN);
dc.SetPen(ws->GetColorGui(Color_GUI::LABEL));
wxPoint p1(a.x, y);
wxPoint p2(a.x - 3, y);
dc.DrawLine(p1, p2);
{
wxDCPenChanger npen(dc, wxPen(*wxLIGHT_GREY, 1, wxPENSTYLE_LONG_DASH));
wxDCPenChanger npen(dc, wxPen(ws->GetColorGui(Color_GUI::GRID_LINE), 1, wxPENSTYLE_LONG_DASH));
p2.x = a.x + a.width - 2;
p1.x += 1;
if (i != 0) dc.DrawLine(p1, p2);
@ -566,7 +569,7 @@ void wxTopActivity::render(wxDC& dc)
int Nlabel = (a.width - 1) / xAareaW;
int stepx = (xAareaW / width_sample);
if (stepx == 0) stepx = 1;
dc.SetPen(*wxBLACK_PEN);
dc.SetPen(ws->GetColorGui(Color_GUI::LABEL));
wxRect rd;
wxPoint ptest;
for (int i = stepx / 2; i < xAxis.size() && LegengWidth > 0; i = i + stepx)
@ -622,7 +625,7 @@ void wxTopActivity::render(wxDC& dc)
p.y = p.y - pixY;
up_poly.push_back(wxPoint(p));
if (width_sample > 19 && i > 0) {
wxDCPenChanger npen(dc, wxPen(*wxLIGHT_GREY, 1, wxPENSTYLE_DOT_DASH));
wxDCPenChanger npen(dc, wxPen(ws->GetColorGui(Color_GUI::GRID_LINE), 1, wxPENSTYLE_DOT_DASH));
dc.DrawLine(wxPoint(p.x, down_poly[i].y - 1), wxPoint(p.x, a.y + 1));
}
wxPoint dis = mouse - p;
@ -705,6 +708,7 @@ void wxTopActivity::render(wxDC& dc)
sa = smp->at(ps++);
if (sa.btime >= (start_t + m_agg_int)) break;
long long q = sa.qid;
if (sa.wait_id >= m_count_wait) continue; // new wait append
if (m_qid_filter != -1 && m_qid_filter != q) continue;
int idx = -1;
for (int i = 0; i < qid_.size(); i++) {
@ -717,6 +721,7 @@ void wxTopActivity::render(wxDC& dc)
qid_wait_id_SUM.push_back(wait);
}
qid_wait_id_SUM[idx][sa.wait_id] += sa.samples;
key3 k{ q,sa.wait_id,sa.pid };
sum_all[sa.wait_id] += sa.samples;
@ -742,26 +747,6 @@ void wxTopActivity::render(wxDC& dc)
int nwy = a.y + 5;
wxRect pp(nwx, nwy, w_panel, h_panel);
if (m_fix_detail_idx == -1)
dc.SetPen(*wxBLACK_PEN);
else
dc.SetPen(*wxBLUE_PEN);
dc.SetBrush(*wxGREY_BRUSH);
dc.DrawRectangle(pp);
// Title
ypos = pp.y + 3;
{
wxDCFontChanger nfont(dc, dc.GetFont().Bold());
dt -= wxTimeSpan(0, 0, m_agg_int / 1000);
wxString tit = dt.Format("%d %H:%M:%S ") + wxString::Format("[period: %ds]", m_agg_int / 1000);
title_sz = dc.GetTextExtent(tit);
wxPoint p;
p.y = ypos;
p.x = pp.x + pp.width / 2 - title_sz.x / 2;
dc.DrawText(tit, p);
ypos += title_sz.y + VERT_SPC;
}
key3 prev{ -1,-1,-1 };
std::map<key3, int> qid_wait_countPID; //count(pid) GROUP (qid,wait)
for (const auto& pair : qid_wait_pid_count) {
@ -774,153 +759,204 @@ void wxTopActivity::render(wxDC& dc)
}
++qid_wait_countPID[prev];
}
wxFont f = dc.GetFont();
f.SetPointSize(f.GetPointSize() - 1);
wxString sql;
int itog = 0;
std::vector<int> map_sum_all = sort_vec_map(sum_all, itog);
int period = ws->getPeriod();
int total = itog;
if (total != 0) {
{
wxDCFontChanger nfont(dc, dc.GetFont());
wxSize normal_sz = dc.GetTextExtent("H");
int max_title_sz_x = 0;
for (int level = 1; level < 3; ++level) {
wxFont f = dc.GetFont();
f.SetPointSize(f.GetPointSize() - 1);
// panel
if (m_fix_detail_idx == -1)
dc.SetPen(ws->GetColorGui(Color_GUI::LABEL));
else
dc.SetPen(*wxBLUE_PEN);
for (int i = 0; i < map_sum_all.size(); i++) {
int wait_index = map_sum_all[i];
long long w_sum = (100 * sum_all[wait_index] / total);
float sek = (period * sum_all[wait_index]) / 1000.0;
if (sek < 1) continue;
wxString w_name = ws->GetName(wait_index, WAIT_NAME);
wxString w_grp = ws->GetName(wait_index, WAIT_GRP);
wxString pr = w_name + wxString::Format(" %lld%%(%.1fs)", w_sum, sek);
long clr = ws->GetColorByWaitName(w_grp);
c.Set(clr);
dc.SetBrush(c);
p.x = pp.x + 3;
p.y = ypos;
dc.DrawRectangle(p.x, p.y, title_sz.GetHeight(), title_sz.GetHeight());
p.x = p.x + title_sz.GetHeight() + 3;
wxString bgproc;
int v = -1;
// background wait
int sum_bg_w = 0;
for (const auto& pair : qid_wait_pid_BG_sum) {
key3 k = pair.first;
if (k.w == wait_index) {
v = pair.second * period;
sum_bg_w += v;
int bt = -1;
//if (pid_btype.find(k.pid)!= pid_btype.end()) bt= pid_btype.at(k.pid);
bt = k.pid;
wxString txt;
if (bt >= 0) txt = ws->GetBackendTypeNameShort(bt);
w_sum = v;
float f = (float)w_sum / 1000;
if (f < 0.1) continue;
if (!bgproc.IsEmpty()) bgproc += ',';
bgproc += wxString::Format("%s(%.1fs)", txt, (float)f);
//title_sz = dc.GetTextExtent(txt + pr);
//p.x = p.x + title_sz.GetHeight() + 3;
// p.y = ypos;
// dc.DrawText(txt + pr, p);
// ypos = p.y + title_sz.GetHeight() + 1;
dc.SetBrush(ws->GetColorGui(Color_GUI::BG));
dc.DrawRectangle(pp);
// Title
ypos = pp.y + 3;
{
wxDCFontChanger nfont(dc, dc.GetFont().Bold());
wxDateTime dttmp = dt;
dttmp -= wxTimeSpan(0, 0, m_agg_int / 1000);
wxString tit = dttmp.Format("%d %H:%M:%S ") + wxString::Format("[period: %ds]", m_agg_int / 1000);
title_sz = dc.GetTextExtent(tit);
wxPoint p;
p.y = ypos;
p.x = pp.x + pp.width / 2 - title_sz.x / 2;
dc.DrawText(tit, p);
ypos += title_sz.y + VERT_SPC;
}
}
if (!bgproc.IsEmpty()) {
float f = (100 * sum_bg_w / (sum_all[wait_index] * period));
bgproc = wxString::Format("BG[%d%%]: ", (int)f) + bgproc;
}
title_sz = dc.GetTextExtent(pr + bgproc);
//
for (int i = 0; i < map_sum_all.size(); i++) {
int wait_index = map_sum_all[i];
long long w_sum = (100 * sum_all[wait_index] / total);
float sek = (period * sum_all[wait_index]) / 1000.0;
if (sek < 1) continue;
wxString w_name = ws->GetName(wait_index, WAIT_NAME);
wxString w_grp = ws->GetName(wait_index, WAIT_GRP);
wxString pr = w_name + wxString::Format(" %lld%%(%.1fs)", w_sum, sek);
long clr = ws->GetColorByWaitName(w_grp);
c.Set(clr);
dc.SetBrush(c);
p.x = pp.x + 3;
p.y = ypos;
dc.DrawRectangle(p.x, p.y, normal_sz.GetHeight(), normal_sz.GetHeight());
p.x = p.x + normal_sz.GetHeight() + 3;
wxString bgproc;
int v = -1;
// background wait
int sum_bg_w = 0;
for (const auto& pair : qid_wait_pid_BG_sum) {
key3 k = pair.first;
if (k.w == wait_index) {
v = pair.second * period;
sum_bg_w += v;
int bt = -1;
//if (pid_btype.find(k.pid)!= pid_btype.end()) bt= pid_btype.at(k.pid);
bt = k.pid;
wxString txt;
if (bt >= 0) txt = ws->GetBackendTypeNameShort(bt);
w_sum = v;
float f = (float)w_sum / 1000;
if (f < 0.1) continue;
if (!bgproc.IsEmpty()) bgproc += ',';
bgproc += wxString::Format("%s(%.1fs)", txt, (float)f);
//title_sz = dc.GetTextExtent(txt + pr);
//p.x = p.x + title_sz.GetHeight() + 3;
// p.y = ypos;
// dc.DrawText(txt + pr, p);
// ypos = p.y + title_sz.GetHeight() + 1;
dc.DrawText(pr + bgproc, p);
ypos = p.y + title_sz.GetHeight() + 2;
{
wxDCFontChanger nfont(dc, f);
// detail client
std::vector<key3> sortv;
for (const auto& pair : qid_wait_pid_FG_sum) {
key3 k = pair.first;
if (k.w == wait_index) {
v = pair.second * period;
k.sum = v;
if (v < 100) continue;
bool ff = true;
for (int p = 0; p < sortv.size(); p++) {
if (sortv[p].sum < v) {
sortv.insert(sortv.begin() + p, k);
ff = false;
break;
}
}
if (ff) sortv.push_back(k);
}
}
for (int j1 = 0; j1 < sortv.size(); j1++) {
key3 k = sortv[j1];
if (k.w == wait_index) {
v = k.sum;
wxString txt;
w_sum = v;
float fsek = (float)w_sum / 1000;
if (fsek < 0.1) continue;
unsigned long long ull = k.qid;
int h = ull >> 32;
int l = ull & 0xFFFFFFFF;
wxString tqid = wxString::Format("%llx", ull);
k.pid = -1;
int cnt = qid_wait_countPID[k];
if (!bgproc.IsEmpty()) {
float f = (100 * sum_bg_w / (sum_all[wait_index] * period));
bgproc = wxString::Format("BG[%d%%]: ", (int)f) + bgproc;
}
title_sz = dc.GetTextExtent(pr + bgproc);
bgproc = wxString::Format("%s ( %.1fs ) [%d]", tqid, (float)fsek, cnt);
title_sz = dc.GetTextExtent(bgproc);
//p.x = p.x + title_sz.GetHeight() + 3;
p.y = ypos;
wxRect r(p.x, p.y, title_sz.GetWidth(), title_sz.GetHeight());
if (r.Contains(mouse)) {
wxDCFontChanger nfont(dc, f.Bold());
dc.DrawText(bgproc, p);
if (m_click == 0) {
// hint sql
sql = ws->GetQueryByQid(k.qid);
}
if (m_click == 2) { // RightUp
// set filter qid
if (wxTheClipboard->Open())
{
wxDataObjectComposite* dataobj = new wxDataObjectComposite();
dataobj->Add(new wxTextDataObject(tqid));
wxTheClipboard->SetData(dataobj);
wxTheClipboard->Close();
dc.DrawText(pr + bgproc, p);
ypos = p.y + normal_sz.GetHeight() + 1;
if (max_title_sz_x < (p.x + title_sz.GetWidth())) max_title_sz_x = p.x + title_sz.GetWidth(); // max width
{
wxDCFontChanger nfont(dc, f);
// detail client
std::vector<key3> sortv;
for (const auto& pair : qid_wait_pid_FG_sum) {
key3 k = pair.first;
if (k.w == wait_index) {
v = pair.second * period;
k.sum = v;
if (v < 100) continue;
bool ff = true;
for (int p = 0; p < sortv.size(); p++) {
if (sortv[p].sum < v) {
sortv.insert(sortv.begin() + p, k);
ff = false;
break;
}
}
m_click = 0;
if (ff) sortv.push_back(k);
}
if (m_click == 1) { // LeftUp
// set filter qid
m_click = 0;
m_filter_detail = tqid;
m_qid_filter = k.qid;
m_regroup = true;
return;
}
}
else
dc.DrawText(bgproc, p);
ypos = p.y + title_sz.GetHeight() + 1;
for (int j1 = 0; j1 < sortv.size(); j1++) {
key3 k = sortv[j1];
if (k.w == wait_index) {
v = k.sum;
wxString txt;
w_sum = v;
float fsek = (float)w_sum / 1000;
if (fsek < 0.1) continue;
unsigned long long ull = k.qid;
int h = ull >> 32;
int l = ull & 0xFFFFFFFF;
wxString tqid = wxString::Format("%llx", ull);
k.pid = -1;
int cnt = qid_wait_countPID[k];
bgproc = wxString::Format("%s ( %.1fs ) [%d]", tqid, (float)fsek, cnt);
title_sz = dc.GetTextExtent(bgproc);
//p.x = p.x + title_sz.GetHeight() + 3;
p.y = ypos;
wxRect r(p.x, p.y, title_sz.GetWidth(), title_sz.GetHeight());
if (r.Contains(mouse) && level == 2) {
wxDCFontChanger nfont(dc, f.Bold());
dc.DrawText(bgproc, p);
if (m_click == 0) {
// hint sql
sql = ws->GetQueryByQid(k.qid);
}
if (m_click == 2) { // RightUp
// set filter qid
if (wxTheClipboard->Open())
{
wxDataObjectComposite* dataobj = new wxDataObjectComposite();
dataobj->Add(new wxTextDataObject(tqid));
wxTheClipboard->SetData(dataobj);
wxTheClipboard->Close();
}
m_click = 0;
}
if (m_click == 1) { // LeftUp
// set filter qid
m_click = 0;
m_filter_detail = tqid;
m_qid_filter = k.qid;
m_regroup = true;
return;
}
}
else
dc.DrawText(bgproc, p);
ypos = p.y + title_sz.GetHeight() + 1;
if (max_title_sz_x < (p.x + title_sz.GetWidth())) max_title_sz_x = p.x + title_sz.GetWidth(); // max width
}
}
}
}
if (!sql.IsEmpty() && level == 2) {
FSQL::FormatterSQL f(sql);
if (f.ParseSql(0) == 0) {
wxRect r(a.x, a.y, 0, a.height);
if (mouse.x > (a.x + a.width / 2)) r.width = mouse.x - a.x;
else { r.width = a.x + a.width - mouse.x - 50; r.x = mouse.x + 50; }
f.Formating(dc, r);
}
}
}
}
if (!sql.IsEmpty()) {
FSQL::FormatterSQL f(sql);
if (f.ParseSql(0) != 0) {
wxRect r(a.x, a.y, 0, a.height);
if (mouse.x > (a.x + a.width / 2)) r.width = mouse.x - a.x;
else { r.width = a.x + a.width - mouse.x - 50; r.x = mouse.x + 50; }
f.Formating(dc, r);
}
}
// resize
if (level == 1) {
if (max_title_sz_x > pp.x + pp.width) {
pp.width = max_title_sz_x - pp.x;
}
if (ypos > pp.y + pp.height) pp.height = ypos - pp.y;
if (ypos > sz.y) {
wxFont fsmall = dc.GetFont();
pp.y = 0;
float kf = (sz.y - pp.y) / (float)(ypos - pp.y);
if (kf < 0.5) kf = 0.5;
int newSize = fsmall.GetPointSize() * kf;
fsmall.SetPointSize(newSize);
//int width, height;
//wxBitmap emptyBitmap(30, 30, dc);
//wxMemoryDC temp_dc;
//temp_dc.SelectObject(emptyBitmap);
//temp_dc.SetFont(fsmall);
//temp_dc.GetTextExtent("H", &width, &height);
dc.SetFont(fsmall);
}
}
} // level
} // fontchanger
}
}
@ -967,7 +1003,7 @@ void wxTopActivity::paintSelRange(wxDC& dc, int width_sample) {
wxPoint p1(cx - dx1, m_area.y + 1);
wxPoint p2(cx - dx1, m_area.y + m_area.height);
{
wxDCPenChanger npen(dc, wxPen(*wxBLACK, 2, wxPENSTYLE_SOLID));
wxDCPenChanger npen(dc, wxPen(ws->GetColorGui(Color_GUI::CURSOR_LINE), 2, wxPENSTYLE_SOLID));
dc.DrawLine(p1, p2);
}
}
@ -980,7 +1016,7 @@ void wxTopActivity::paintSelRange(wxDC& dc, int width_sample) {
wxPoint p1(cx - dx2, m_area.y + 1);
wxPoint p2(cx - dx2, m_area.y + m_area.height);
{
wxDCPenChanger npen(dc, wxPen(*wxBLACK, 2, wxPENSTYLE_SOLID));
wxDCPenChanger npen(dc, wxPen(ws->GetColorGui(Color_GUI::CURSOR_LINE), 2, wxPENSTYLE_SOLID));
dc.DrawLine(p1, p2);
}
}
@ -1008,6 +1044,7 @@ void wxTopActivity::paintSelRange(wxDC& dc, int width_sample) {
dc.SetPen(*wxBLACK);
dc.DrawRectangle(r);
dc.DrawText(labeltext, p);
dc.SetPen(ws->GetColorGui(Color_GUI::CURSOR_LINE));
dc.DrawLine(p1, p2);
}
}
@ -1022,10 +1059,10 @@ void wxTopActivity::paintSelRange(wxDC& dc, int width_sample) {
wxSize szf = dc.GetTextExtent(labelLeft);
wxPoint p1(cx - dx1, m_area.y + 25);
wxPoint p2(cx - dx2, m_area.y + 25);
dc.SetBrush(*wxBLACK);
dc.SetPen(*wxBLACK);
dc.SetBrush(wxBrush(ws->GetColorGui(Color_GUI::CURSOR_LINE)));
dc.SetPen(wxPen(ws->GetColorGui(Color_GUI::CURSOR_LINE)));
{
wxDCPenChanger npen(dc, wxPen(*wxBLACK, 2, wxPENSTYLE_SOLID));
wxDCPenChanger npen(dc, wxPen(ws->GetColorGui(Color_GUI::CURSOR_LINE), 2, wxPENSTYLE_SOLID));
dc.DrawLine(p1, p2);
}
@ -1054,25 +1091,42 @@ void wxTopActivity::paintSelRange(wxDC& dc, int width_sample) {
wxString l3text = ElapsedTimeToStr(ll.GetValue());
wxSize sz3 = dc.GetTextExtent(l3text);
wxRect r2(tx2.x - 1, tx2.y, sz.x + 2, sz.y);
int maxx = 0;
int maxx = 0; bool isup = true;
if (szf.x < (p2.x - p1.x)) {
dc.DrawRectangle(r);
dc.DrawText(labelLeft, tx1);
// | labelLeft
dc.DrawRectangle(r); // inner
dc.DrawText(labelLeft, r.x+1,r.y);
maxx = r.width;
}
else {
// labelLeft |
r.x = tx1.x - 1 - r.width;
dc.DrawRectangle(r);
dc.DrawText(labelLeft, r.x + 1,r.y);
}
if (sz.x + maxx < (p2.x - p1.x) && fix_pos_R.IsValid()) {
// labelRight |
dc.DrawRectangle(r2);
dc.DrawText(labeltext, tx2);
dc.DrawText(labeltext, r2.x+1,r2.y);
maxx += r2.width;
}
if (sz3.x + maxx < (p2.x - p1.x)) {
else {
// | labelRight
r2.x = cx - dx2 + 2;
dc.DrawRectangle(r2);
dc.DrawText(labeltext, r2.x + 1,r2.y);
}
if (sz3.x + maxx < (p2.x - p1.x) && false) { // up
wxRect r3(r.x + r.width + (p2.x - p1.x - maxx) / 2 - sz3.x / 2, r.y, sz3.x + 2, sz3.y);
dc.DrawRectangle(r3);
dc.DrawText(l3text, r3.x + 1, r3.y);
maxx += r3.width;
}
else if (sz3.x < (p2.x - p1.x) ) { // down
wxRect r3(tx1.x - 1 + (p2.x - p1.x ) / 2 - sz3.x / 2, points[0].y + 5, sz3.x + 2, sz3.y);
dc.DrawRectangle(r3);
dc.DrawText(l3text, r3.x + 1, r3.y);
}
}
if (m_click == 2 && !fix_pos_L.IsValid()) {
@ -1540,7 +1594,7 @@ void wxCustomButton::render(wxDC& dc)
if (pressedDown)
dc.SetBrush(*wxRED_BRUSH);
else
dc.SetBrush(*wxGREY_BRUSH);
dc.SetBrush(ws->GetColorGui(Color_GUI::BG));
wxRect r = dc.GetWindow()->GetClientRect();
wxSize sz = r.GetSize();
//dc.DrawRectangle(0, 0, r.width, r.height);

View file

@ -313,7 +313,8 @@ public:
// wxPopupTransientWindow virtual methods are all overridden to log them
private:
wxScrolledWindow* m_panel;
//wxScrolledWindow* m_panel;
wxPanel* m_panel;
wxTopActivity* top;
topDataViewCtrl* dvc;
wxObjectDataPtr<MyIndexListModel> m_index_list_model;
@ -376,13 +377,13 @@ class wxTopActivity : public wxControl
int m_agg_int = 5000;
int m_count_wait;
int m_inter[9] = {
5000 ,
10000 ,
5000 ,// 5 sek
10000 ,//10 sek
30000 ,//30 s
60000 ,//1 min
5 * 60000 ,//5 min
10 * 60000,//10 min
15 * 60000,//10 min
15 * 60000,//15 min
30 * 60000,//30 min
60 * 60000 //60 min
};
@ -433,6 +434,7 @@ public:
//SetMinSize(wxSize(300,200));
top = topactive;
w = NULL;
m_win_s = NULL;
w = top->getViewRange(agg, right_g);
Bind(wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, [&](wxDataViewEvent& event) {
int col = event.GetColumn();
@ -474,6 +476,82 @@ public:
if (!ispidfirst) ispidfirst = col->GetTitle() == "QID" && event.GetColumn() == 1;
CalcRowsDataView(true, ispidfirst);
Refresh();
if (m_win_s != NULL) m_win_s->Refresh();
});
Bind(wxEVT_CHAR, [&](wxKeyEvent& event) {
bool fnd = false;
wxChar charcode = event.GetUnicodeKey();
int l = m_find.length();
if (event.GetKeyCode() == WXK_ESCAPE) {
//GetParent()->Close(true);
m_find = "";
if (m_win_s != NULL) {
m_win_s->Destroy();
m_win_s = NULL;
}
} else
if (event.GetKeyCode() == WXK_F3) {
//GetParent()->Close(true);
fnd = true;
} else
if (event.GetKeyCode() == WXK_BACK) {
if (l > 0) m_find.RemoveLast();
//m_win_s->SetValue(m_find);
fnd = true;
} else
if (wxIsprint(charcode))
{
//txt->EmulateKeyPress(event);
m_find += charcode;
fnd = true;
}
//else
// event.Skip();
if (fnd && m_find.length() > 0) {
if (m_win_s == NULL) {
wxWindow* t = this->GenericGetHeader();
wxRect r;
r.width=GetColumn(0)->GetWidth();
r.height = t->GetSize().GetHeight();
m_win_s = new wxTextCtrl(t->GetParent(), wxID_ANY, "",
r.GetPosition(),
r.GetSize(),
wxTE_PROCESS_ENTER
| wxTE_READONLY
);
m_win_s->SetInsertionPointEnd();
}
if (m_win_s != NULL) {
m_win_s->SetValue(m_find); m_win_s->Refresh();
}
MyIndexListModel* m = static_cast<MyIndexListModel*>(GetModel());
wxDataViewItem item(GetCurrentItem());
long row = (long)item.GetID();
if (!(row < m->GetCount())) row = 0;
while (row != -1 && row < m->GetCount()) {
key3 k = m->GetRowValue(row);
wxString v=wxString::Format("%d,%llx",k.pid,k.qid);
// m->GetValueByRow(v, row, 0);
bool isfind = v.Contains(m_find);
if (isfind) {
wxDataViewItem it = GetItemByRow(row);
SetCurrentItem(it);
EnsureVisible(it);
return;
}
row++;
}
return;
}
// end function
event.Skip();
});
GetMainWindow()->Bind(wxEVT_MOTION, [&](wxMouseEvent& event) {
if (event.Dragging())
@ -575,6 +653,8 @@ private:
int agg, right_g, left_g;
bool ignoreBG = false;
bool ispidfirst = true;
wxString m_find;
wxTextCtrl *m_win_s;
wxTopActivity* top;
WaitSample* w;
};

View file

@ -186,6 +186,7 @@ public:
frmStatus(frmMain *form, const wxString &_title, pgConn *conn);
~frmStatus();
void Go();
bool getTextSqlbyQid(long long qid);
private:
wxAuiManager manager;
@ -209,7 +210,7 @@ private:
long backend_pid;
int wait_event_type_col;
bool isrecovery,track_commit_timestamp, is_read_log;
bool wait_sample, wait_enable, wait_save;
bool wait_sample, wait_enable, wait_save,std,pro;
bool frm_exit = false; // need close form
bool logisread = false; // need close form
WaitSample WS;
@ -351,7 +352,6 @@ private:
void addLogFile(wxDateTime *dt, bool skipFirst);
void addLogFile(const wxString &filename, const wxDateTime timestamp, long len, long &read, bool skipFirst);
void addLogLine(const wxString &str, bool formatted = true, bool csv_log_format = false);
void checkConnection();
DECLARE_EVENT_TABLE()

View file

@ -1,6 +1,10 @@
#pragma once
#ifndef __WAITSAMPLE_H
#define __WAITSAMPLE_H
#include <map>
//#include <frm/frmStatus.h>
class frmStatus;
struct Sample
{
int btime;
@ -56,11 +60,18 @@ struct key3p {
};
typedef std::vector<int> vec_int;
enum class Color_GUI{
BG,
CURSOR_LINE,
GRID_LINE,
LABEL
};
class WaitSample
{
private:
int periodms = 10;
int history_size;
frmStatus *m_frmStatus;
wxJSONValue opt;
std::map<int, int> pids;
std::map<int, int> chkpids;
@ -85,12 +96,14 @@ private:
long long basetime = 0;
int timebegiserios = 0, timeendserios = 0;
int start_index_serios;
std::vector<wxColour> color_gui;
/// <summary>
/// Получение номера группы по имени группы.
/// </summary>
/// <param name="wclass"></param>
/// <returns></returns>
int wait_class(wxString wclass);
wxString m_file_cache_sql;
public:
void SaveFileSamples();
void LoadFileSamples();
@ -171,17 +184,19 @@ public:
/// <returns></returns>
int getPositionByTime(int time);
inline int getPeriod() { return periodms; }
void SetConfig(long periodmills, long history_size) {
void SetConfig(long periodmills, long history_size,frmStatus *parent) {
periodms = periodmills;
this->history_size = history_size;
m_frmStatus = parent;
};
void Init();
WaitSample() {
//c2.FromString("#3644ff");
Init();
m_frmStatus = NULL;
};
void BeginSeriosSample(long long timeserios) {
void BeginSeriosSample(long long timeserios) {
chkpids.clear();
if (basetime == 0) basetime = timeserios;
timebegiserios = timeendserios;
@ -191,5 +206,8 @@ public:
}
void EndSeriosSample();
void AddSample(int pid, bool isXidTransation, wxString& active, const wxString& sample);
wxColour & GetColorGui(Color_GUI gui_index) { return color_gui[(int)gui_index]; }
bool RemoveFiles();
};
#endif

View file

@ -6,35 +6,37 @@
void WaitSample::Init() {
wxString clr = "h1 { \
region: \"IO:DataFileRead\", #3644ff;\n\
region: \"IO:DataFileWrite\", #790808;\n\
region: \"IO:DataFileRead\", #2132bd;\n\
region: \"IO:DataFileWrite\", #2132bd;\n\
region: \"IO:BufFileRead\", #16658d;\n\
region: \"IO:BufFileWrite\", #d30a0a;\n\
region: \"IO:BufFileWrite\", #16658d;\n\
region: \"IO:DataFileExtend\", #9720ba;\n\
region: \"IO:DataFilePrefetch\", #c03ae8;\n\
region: \"IO:DataFileFlush\", #b609ea;\n\
region: \"IO:DataFileSync\", #b609ea;\n\
region: \"IO:DataFilePrefetch\", #2132bd;\n\
region: \"IO:DataFileFlush\", #2132bd;\n\
region: \"IO:DataFileSync\", #2132bd;\n\
region: \"IO:ReplicationSlotSync\", #b609ea;\n\
region: \"IO:WALSync\", #ff6a00;\n\
region: \"IO:WALWrite\", #ff6a00;\n\
region: \"IO:WALInitWrite\", #ff6a00;\n\
region: \"IO:WALRead\", #ba550e;\n\
region: \"IO:WALRead\", #ff6a00;\n\
region: \"IO\", #2132bd;\n\
region: \"IPC\", #908b3b;\n\
region: \"Lock\", #ff0000;\n\
region: \"Client\", #0b6222;\n\
region: \"BufferPin\", #a4a3a0;\n\
region: \"Client:ClientWrite\", #76bb88;\n\
region: \"IPC:ArchiveCommand\", #fff200;\n\
region: \"IPC:ArchiveCommand\", #908b3b;\n\
region: \"IPC:MessageQueueReceive\", #aaae4f;\n\
region: \"IPC:MessageQueueSend\", #aaae4f;\n\
region: \"LWLock\", #87f566;\n\
region: \"LWLock:WALWrite\", #3bf61e;\n\
region: \"LWLock:WALInsert\", #3bf61e;\n\
region: \"LWLock:Autovacuum\", #20bb08;\n\
region: \"LWLock:BufferContent\", #98db19;\n\
region: \"LWLock:WALWrite\", #87f566;\n\
region: \"LWLock:WALInsert\", #87f566;\n\
region: \"LWLock:Autovacuum\", #87f566;\n\
region: \"LWLock:BufferContent\", #87f566;\n\
region: \"CPU\", #FFFA8A;\n\
region: \"Timeout\", #6ce4c6;\n\
region: \"Timeout:VacuumDelay\", #20bb08;\n\
region: \"Timeout:VacuumDelay\", #6ce4c6;\n\
region: \"Timeout:PgSleep\", #6ce4c6;\n\
}";
wxStringTokenizer tk(clr, "\n", wxTOKEN_DEFAULT);
wxString cc;
@ -48,18 +50,37 @@ region: \"Timeout:VacuumDelay\", #20bb08;\n\
wxString w = l.AfterFirst('"').BeforeFirst('"');
if (w.IsEmpty()) continue;
wxString c = l.AfterFirst('#').BeforeFirst(';');
unsigned long tmp;
unsigned long tmp=0;
wxSscanf(c, "%lx", &tmp);
tmp = (tmp >> 16) & 0xFF | (tmp & 0x00FF00) | (tmp & 0xFF) << 16;
wait_idx.emplace(w, tmp);
wxJSONValue e(wxJSONType::wxJSONTYPE_OBJECT);
wxColour cc3("#"+c);
e["enable"] = true;
wxColour cc3;
cc3.Set(tmp);
bool en = true;
if (w == "Timeout:PgSleep" ||
w == "Timeout:VacuumDelay" ||
w == "IPC:ArchiveCommand" ||
w == "Timeout:PgSleep")
en = false; // disable for example
e["enable"] = en;
e["color"] = "#" + c;
e["name"] = w;
events.Append(e);
}
wxJSONValue def(wxJSONType::wxJSONTYPE_OBJECT);
def["events"] = events;
wxString cstr;
cstr = "#808080";
wxJSONValue c1=wxString(cstr); //BG
wxJSONValue c2 = wxString("#000000"); //CURSOR_LINE
cstr = "#c0c0c0";
wxJSONValue c3 = wxString(cstr); //GRID_LINE
wxJSONValue c4 = wxString("#000000"); //LABEL
def["bg"] = c1;
def["cursorline"] = c2;
def["gridline"] = c3;
def["label"] = c4;
//def["autoloadcache_sql"] = true;
group.push_back("BufferPin");
group.push_back("Client");
@ -69,6 +90,7 @@ region: \"Timeout:VacuumDelay\", #20bb08;\n\
group.push_back("Activity");
group.push_back("LWLock");
group.push_back("Timeout");
group.push_back("CPU");
settings->ReloadJsonFileIfNeed();
settings->ReadJsonObect("WaitEvents", opt, def);
// settings->WriteJsonFile();
@ -81,6 +103,7 @@ region: \"Timeout:VacuumDelay\", #20bb08;\n\
wxString c= e["color"].AsString();
unsigned long tmp;
wxSscanf(c, "#%lx", &tmp);
tmp = (tmp >> 16) & 0xFF | (tmp & 0x00FF00) | (tmp & 0xFF) << 16;
wxColour cc(tmp);
if (!cc.IsOk()) cc = *wxBLACK;
//wxSscanf(c, "%lx", &tmp);
@ -90,7 +113,22 @@ region: \"Timeout:VacuumDelay\", #20bb08;\n\
}
}
else opt = def;
// color gui
wxColour cc1(opt["bg"].AsString());
if (cc1.IsOk()) color_gui.push_back(wxColour(cc1)); else
color_gui.push_back(wxColour(def["bg"].AsString()));
cc1.Set(opt["cursorline"].AsString());
if (cc1.IsOk()) color_gui.push_back(wxColour(cc1)); else
color_gui.push_back(wxColour(def["cursor_line"].AsString()));
cc1.Set(opt["gridline"].AsString());
if (cc1.IsOk()) color_gui.push_back(wxColour(cc1)); else
color_gui.push_back(wxColour(def["gridline"].AsString()));
cc1.Set(opt["label"].AsString());
if (cc1.IsOk()) color_gui.push_back(wxColour(cc1)); else
color_gui.push_back(wxColour(def["label"].AsString()));
wxString tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxFileName::GetPathSeparator() + "postgresql" + wxFileName::GetPathSeparator() + "cache_sql.txt";
m_file_cache_sql = tempDir;
wxTextFile file(tempDir);
if (file.Exists()) file.Open();
if (file.IsOpened())
@ -439,6 +477,13 @@ wxString WaitSample::GetQueryByQid(long long qid) {
wxString sql = qid_sql[qid];
return sql;
}
else {
// try get text sql
if (m_frmStatus && m_frmStatus->getTextSqlbyQid(qid)) {
wxString sql = qid_sql[qid];
return sql;
};
}
return wxEmptyString;
}
@ -593,7 +638,8 @@ void WaitSample::SaveFileSamples() {
file.Write(strnl);
file.Close();
}
tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxFileName::GetPathSeparator() + "postgresql" + wxFileName::GetPathSeparator() + "cache_sql.txt";
tempDir = m_file_cache_sql;
wxUtfFile file1(tempDir, wxFile::write, wxFONTENCODING_UTF8);
if (file1.IsOpened())
{
@ -608,7 +654,14 @@ void WaitSample::SaveFileSamples() {
file1.Close();
}
}
bool WaitSample::RemoveFiles() {
bool rez = false;
if (wxFileExists(m_file_cache_sql)) {
wxRemoveFile(m_file_cache_sql);
rez = true;
}
return rez;
}
void WaitSample::AddSample(int pid, bool isXidTransation, wxString& btype, const wxString& sample) {
//PidWait pw(pid, basetime);;
// ïîèñê