mirror of https://github.com/buggins/dlangide.git
DMD profiling on windows workaround
This commit is contained in:
parent
f36056d37e
commit
b412b9a037
|
@ -38,13 +38,13 @@ void sortFunctionNodes(FunctionNode[] nodes, TraceSortOrder sortOrder) {
|
|||
import std.algorithm.sorting : sort;
|
||||
final switch(sortOrder) {
|
||||
case TraceSortOrder.BY_FUNCTION_TIME:
|
||||
sort!((a,b) => a.function_time < b.function_time)(nodes);
|
||||
sort!((a,b) => a.function_time > b.function_time)(nodes);
|
||||
break;
|
||||
case TraceSortOrder.BY_TOTAL_TIME:
|
||||
sort!((a,b) => a.function_and_descendant_time < b.function_and_descendant_time)(nodes);
|
||||
sort!((a,b) => a.function_and_descendant_time > b.function_and_descendant_time)(nodes);
|
||||
break;
|
||||
case TraceSortOrder.BY_CALL_COUNT:
|
||||
sort!((a,b) => a.number_of_calls < b.number_of_calls)(nodes);
|
||||
sort!((a,b) => a.number_of_calls > b.number_of_calls)(nodes);
|
||||
break;
|
||||
case TraceSortOrder.BY_NAME:
|
||||
sort!((a,b) => a.name < b.name)(nodes);
|
||||
|
@ -65,7 +65,7 @@ class DMDTraceLogParser {
|
|||
FunctionNode[] nodesByName;
|
||||
//FunctionEdge[string] caller_graph;
|
||||
//FunctionEdge[string] called_graph;
|
||||
private ulong ticks_per_second;
|
||||
ulong ticks_per_second;
|
||||
|
||||
this(string fname) {
|
||||
filename = fname;
|
||||
|
@ -187,6 +187,11 @@ class DMDTraceLogParser {
|
|||
caller = false;
|
||||
}
|
||||
}
|
||||
if (function_name.length != 0)
|
||||
{
|
||||
nodes[text(function_name)] = new FunctionNode(function_name,
|
||||
function_times, function_and_descendant, function_only, caller_graph, called_graph);
|
||||
}
|
||||
makeSorted();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ module dlangide.ui.dmdprofilerview;
|
|||
|
||||
import dlangui.widgets.layouts;
|
||||
import dlangui.widgets.widget;
|
||||
import dlangui.widgets.grid;
|
||||
import dlangui.widgets.scroll;
|
||||
import dlangui.widgets.controls;
|
||||
import dlangide.ui.frame;
|
||||
|
@ -9,13 +10,291 @@ import dlangide.ui.commands;
|
|||
import dlangui.core.i18n;
|
||||
import dlangide.tools.d.dmdtrace;
|
||||
|
||||
class DMDProfilerView : ScrollWidget {
|
||||
class DMDProfilerView : WidgetGroupDefaultDrawing {
|
||||
protected IDEFrame _frame;
|
||||
protected DMDTraceLogParser _data;
|
||||
protected TraceFunctionList _fullFunctionList;
|
||||
this(string ID, IDEFrame frame, DMDTraceLogParser data) {
|
||||
super(ID);
|
||||
_frame = frame;
|
||||
_data = data;
|
||||
contentWidget = new TextWidget(null, "DMD profiler view"d);
|
||||
layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
|
||||
_fullFunctionList = new TraceFunctionList("FULL_FUNCTION_LIST", "All functions"d, _data.nodesByTotalTime, _data.ticks_per_second); // new TextWidget(null, "DMD profiler view"d);
|
||||
addChild(_fullFunctionList);
|
||||
}
|
||||
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
|
||||
override void layout(Rect rc) {
|
||||
super.layout(rc);
|
||||
applyMargins(rc);
|
||||
applyPadding(rc);
|
||||
Rect rc1 = rc;
|
||||
rc1.right = rc1.left + rc.width / 2;
|
||||
_fullFunctionList.layout(rc1);
|
||||
}
|
||||
/**
|
||||
Measure widget according to desired width and height constraints. (Step 1 of two phase layout).
|
||||
|
||||
*/
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
_fullFunctionList.measure(parentWidth, parentHeight);
|
||||
measuredContent(parentWidth, parentHeight, _fullFunctionList.measuredWidth, _fullFunctionList.measuredHeight);
|
||||
}
|
||||
}
|
||||
|
||||
class TraceFuncionGrid : StringGridWidgetBase {
|
||||
protected FunctionNode[] _list;
|
||||
protected dstring[] _colTitles;
|
||||
protected ulong _ticksPerSecond;
|
||||
this(string ID, FunctionNode[] list, ulong ticks_per_second) {
|
||||
super(ID);
|
||||
_ticksPerSecond = ticks_per_second;
|
||||
_list = list;
|
||||
layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
|
||||
fullColumnOnLeft(false);
|
||||
fullRowOnTop(false);
|
||||
resize(4, cast(int)list.length);
|
||||
setColTitle(0, "Function name"d);
|
||||
setColTitle(1, "Called"d);
|
||||
setColTitle(2, "F us"d);
|
||||
setColTitle(3, "F+D us"d);
|
||||
showRowHeaders = false;
|
||||
rowSelect = true;
|
||||
minVisibleRows = 10;
|
||||
minVisibleCols = 4;
|
||||
}
|
||||
|
||||
private dchar[128] _numberFormatBuf;
|
||||
dstring formatNumber(ulong v, dchar[] buffer) {
|
||||
dchar[64] buf;
|
||||
int k = 0;
|
||||
if (!v) {
|
||||
buf[k++] = '0';
|
||||
} else {
|
||||
while (v) {
|
||||
buf[k++] = '0' + (cast(int)(v % 10));
|
||||
v /= 10;
|
||||
}
|
||||
}
|
||||
// reverse order
|
||||
for (int i = 0; i < k; i++)
|
||||
buffer[i] = buf[k - i - 1];
|
||||
return cast(dstring)buffer[0..k];
|
||||
}
|
||||
dstring formatDurationTicks(ulong n) {
|
||||
ulong v = n * 1000000 / _ticksPerSecond;
|
||||
return formatNumber(v, _numberFormatBuf[]);
|
||||
}
|
||||
|
||||
/// get cell text
|
||||
override dstring cellText(int col, int row) {
|
||||
if (row < 0 || row >= _list.length)
|
||||
return ""d;
|
||||
FunctionNode entry = _list[row];
|
||||
switch (col) {
|
||||
case 0:
|
||||
string fn = entry.name;
|
||||
if (fn.length > 256)
|
||||
fn = fn[0..256] ~ "...";
|
||||
return fn.to!dstring;
|
||||
case 1:
|
||||
return formatNumber(entry.number_of_calls, _numberFormatBuf);
|
||||
case 2:
|
||||
return formatDurationTicks(entry.function_time);
|
||||
case 3:
|
||||
return formatDurationTicks(entry.function_and_descendant_time);
|
||||
default:
|
||||
return ""d;
|
||||
}
|
||||
}
|
||||
/// set cell text
|
||||
override StringGridWidgetBase setCellText(int col, int row, dstring text) {
|
||||
// do nothing
|
||||
return this;
|
||||
}
|
||||
/// returns row header title
|
||||
override dstring rowTitle(int row) {
|
||||
return ""d;
|
||||
}
|
||||
/// set row header title
|
||||
override StringGridWidgetBase setRowTitle(int row, dstring title) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/// returns row header title
|
||||
override dstring colTitle(int col) {
|
||||
return _colTitles[col];
|
||||
}
|
||||
|
||||
/// set col header title
|
||||
override StringGridWidgetBase setColTitle(int col, dstring title) {
|
||||
_colTitles[col] = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
void autofit() {
|
||||
autoFitColumnWidths();
|
||||
fillColumnWidth(0);
|
||||
}
|
||||
|
||||
/// set new size
|
||||
override void resize(int c, int r) {
|
||||
if (c == cols && r == rows)
|
||||
return;
|
||||
int oldcols = cols;
|
||||
int oldrows = rows;
|
||||
super.resize(c, r);
|
||||
_colTitles.length = c;
|
||||
}
|
||||
|
||||
protected override Point measureCell(int x, int y) {
|
||||
if (_customCellAdapter && _customCellAdapter.isCustomCell(x, y)) {
|
||||
return _customCellAdapter.measureCell(x, y);
|
||||
}
|
||||
//Log.d("measureCell ", x, ", ", y);
|
||||
FontRef fnt = font;
|
||||
dstring txt;
|
||||
if (x >= 0 && y >= 0)
|
||||
txt = cellText(x, y);
|
||||
else if (y < 0 && x >= 0)
|
||||
txt = colTitle(x);
|
||||
else if (y >= 0 && x < 0)
|
||||
txt = rowTitle(y);
|
||||
Point sz = fnt.textSize(txt);
|
||||
if (sz.y < fnt.height)
|
||||
sz.y = fnt.height;
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
/// draw cell content
|
||||
protected override void drawCell(DrawBuf buf, Rect rc, int col, int row) {
|
||||
if (_customCellAdapter && _customCellAdapter.isCustomCell(col, row)) {
|
||||
return _customCellAdapter.drawCell(buf, rc, col, row);
|
||||
}
|
||||
if (BACKEND_GUI)
|
||||
rc.shrink(2, 1);
|
||||
else
|
||||
rc.right--;
|
||||
FontRef fnt = font;
|
||||
dstring txt = cellText(col, row);
|
||||
Point sz = fnt.textSize(txt);
|
||||
Align ha = Align.Right;
|
||||
//if (sz.y < rc.height)
|
||||
applyAlign(rc, sz, ha, Align.VCenter);
|
||||
int offset = BACKEND_CONSOLE ? 0 : 1;
|
||||
fnt.drawText(buf, rc.left + offset, rc.top + offset, txt, textColor);
|
||||
}
|
||||
|
||||
/// draw cell content
|
||||
protected override void drawHeaderCell(DrawBuf buf, Rect rc, int col, int row) {
|
||||
if (BACKEND_GUI)
|
||||
rc.shrink(2, 1);
|
||||
else
|
||||
rc.right--;
|
||||
FontRef fnt = font;
|
||||
dstring txt;
|
||||
if (row < 0 && col >= 0)
|
||||
txt = colTitle(col);
|
||||
else if (row >= 0 && col < 0)
|
||||
txt = rowTitle(row);
|
||||
if (!txt.length)
|
||||
return;
|
||||
Point sz = fnt.textSize(txt);
|
||||
Align ha = Align.Left;
|
||||
if (col < 0)
|
||||
ha = Align.Right;
|
||||
//if (row < 0)
|
||||
// ha = Align.HCenter;
|
||||
applyAlign(rc, sz, ha, Align.VCenter);
|
||||
int offset = BACKEND_CONSOLE ? 0 : 1;
|
||||
uint cl = textColor;
|
||||
cl = style.customColor("grid_cell_text_color_header", cl);
|
||||
fnt.drawText(buf, rc.left + offset, rc.top + offset, txt, cl);
|
||||
}
|
||||
|
||||
/// draw cell background
|
||||
protected override void drawHeaderCellBackground(DrawBuf buf, Rect rc, int c, int r) {
|
||||
bool selectedCol = (c == col) && !_rowSelect;
|
||||
bool selectedRow = r == row;
|
||||
bool selectedCell = selectedCol && selectedRow;
|
||||
if (_rowSelect && selectedRow)
|
||||
selectedCell = true;
|
||||
if (!selectedCell && _multiSelect) {
|
||||
selectedCell = Point(c, r) in _selection || (_rowSelect && Point(0, r) in _selection);
|
||||
}
|
||||
// draw header cell background
|
||||
DrawableRef dw = c < 0 ? _cellRowHeaderBackgroundDrawable : _cellHeaderBackgroundDrawable;
|
||||
uint cl = _cellHeaderBackgroundColor;
|
||||
if (c >= 0 || r >= 0) {
|
||||
if (c < 0 && selectedRow) {
|
||||
cl = _cellHeaderSelectedBackgroundColor;
|
||||
dw = _cellRowHeaderSelectedBackgroundDrawable;
|
||||
} else if (r < 0 && selectedCol) {
|
||||
cl = _cellHeaderSelectedBackgroundColor;
|
||||
dw = _cellHeaderSelectedBackgroundDrawable;
|
||||
}
|
||||
}
|
||||
if (!dw.isNull)
|
||||
dw.drawTo(buf, rc);
|
||||
else
|
||||
buf.fillRect(rc, cl);
|
||||
static if (BACKEND_GUI) {
|
||||
uint borderColor = _cellHeaderBorderColor;
|
||||
buf.drawLine(Point(rc.right - 1, rc.bottom), Point(rc.right - 1, rc.top), _cellHeaderBorderColor); // vertical
|
||||
buf.drawLine(Point(rc.left, rc.bottom - 1), Point(rc.right - 1, rc.bottom - 1), _cellHeaderBorderColor); // horizontal
|
||||
}
|
||||
}
|
||||
|
||||
/// draw cell background
|
||||
protected override void drawCellBackground(DrawBuf buf, Rect rc, int c, int r) {
|
||||
bool selectedCol = c == col;
|
||||
bool selectedRow = r == row;
|
||||
bool selectedCell = selectedCol && selectedRow;
|
||||
if (_rowSelect && selectedRow)
|
||||
selectedCell = true;
|
||||
if (!selectedCell && _multiSelect) {
|
||||
selectedCell = Point(c, r) in _selection || (_rowSelect && Point(0, r) in _selection);
|
||||
}
|
||||
uint borderColor = _cellBorderColor;
|
||||
if (c < fixedCols || r < fixedRows) {
|
||||
// fixed cell background
|
||||
buf.fillRect(rc, _fixedCellBackgroundColor);
|
||||
borderColor = _fixedCellBorderColor;
|
||||
}
|
||||
static if (BACKEND_GUI) {
|
||||
buf.drawLine(Point(rc.left, rc.bottom + 1), Point(rc.left, rc.top), borderColor); // vertical
|
||||
buf.drawLine(Point(rc.left, rc.bottom - 1), Point(rc.right - 1, rc.bottom - 1), borderColor); // horizontal
|
||||
}
|
||||
if (selectedCell) {
|
||||
static if (BACKEND_GUI) {
|
||||
if (_rowSelect)
|
||||
buf.drawFrame(rc, _selectionColorRowSelect, Rect(0,1,0,1), _cellBorderColor);
|
||||
else
|
||||
buf.drawFrame(rc, _selectionColor, Rect(1,1,1,1), _cellBorderColor);
|
||||
} else {
|
||||
if (_rowSelect)
|
||||
buf.fillRect(rc, _selectionColorRowSelect);
|
||||
else
|
||||
buf.fillRect(rc, _selectionColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
|
||||
override void layout(Rect rc) {
|
||||
super.layout(rc);
|
||||
autofit();
|
||||
}
|
||||
}
|
||||
|
||||
class TraceFunctionList : VerticalLayout {
|
||||
TraceFuncionGrid _grid;
|
||||
|
||||
this(string ID, dstring title, FunctionNode[] list, ulong ticks_per_second) {
|
||||
super(ID);
|
||||
addChild(new TextWidget("gridTitle", title).layoutWidth(FILL_PARENT));
|
||||
_grid = new TraceFuncionGrid("FUNCTION_LIST", list, ticks_per_second);
|
||||
addChild(_grid);
|
||||
layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue