performance fixes

This commit is contained in:
Vadim Lopatin 2014-04-02 13:27:00 +04:00
parent 970928d5f6
commit fbe9ef75fb
7 changed files with 62 additions and 26 deletions

View File

@ -8,12 +8,12 @@
<multiobj>0</multiobj> <multiobj>0</multiobj>
<singleFileCompilation>0</singleFileCompilation> <singleFileCompilation>0</singleFileCompilation>
<oneobj>0</oneobj> <oneobj>0</oneobj>
<trace>0</trace> <trace>1</trace>
<quiet>0</quiet> <quiet>0</quiet>
<verbose>0</verbose> <verbose>0</verbose>
<vtls>0</vtls> <vtls>0</vtls>
<symdebug>1</symdebug> <symdebug>1</symdebug>
<optimize>0</optimize> <optimize>1</optimize>
<cpu>0</cpu> <cpu>0</cpu>
<isX86_64>0</isX86_64> <isX86_64>0</isX86_64>
<isLinux>0</isLinux> <isLinux>0</isLinux>
@ -29,10 +29,10 @@
<useIn>0</useIn> <useIn>0</useIn>
<useOut>0</useOut> <useOut>0</useOut>
<useArrayBounds>0</useArrayBounds> <useArrayBounds>0</useArrayBounds>
<noboundscheck>0</noboundscheck> <noboundscheck>1</noboundscheck>
<useSwitchError>0</useSwitchError> <useSwitchError>0</useSwitchError>
<useUnitTests>0</useUnitTests> <useUnitTests>0</useUnitTests>
<useInline>0</useInline> <useInline>1</useInline>
<release>0</release> <release>0</release>
<preservePaths>0</preservePaths> <preservePaths>0</preservePaths>
<warnings>0</warnings> <warnings>0</warnings>

View File

@ -8,12 +8,12 @@
<multiobj>0</multiobj> <multiobj>0</multiobj>
<singleFileCompilation>0</singleFileCompilation> <singleFileCompilation>0</singleFileCompilation>
<oneobj>0</oneobj> <oneobj>0</oneobj>
<trace>0</trace> <trace>1</trace>
<quiet>0</quiet> <quiet>0</quiet>
<verbose>0</verbose> <verbose>0</verbose>
<vtls>0</vtls> <vtls>0</vtls>
<symdebug>1</symdebug> <symdebug>1</symdebug>
<optimize>0</optimize> <optimize>1</optimize>
<cpu>0</cpu> <cpu>0</cpu>
<isX86_64>0</isX86_64> <isX86_64>0</isX86_64>
<isLinux>0</isLinux> <isLinux>0</isLinux>
@ -29,10 +29,10 @@
<useIn>0</useIn> <useIn>0</useIn>
<useOut>0</useOut> <useOut>0</useOut>
<useArrayBounds>0</useArrayBounds> <useArrayBounds>0</useArrayBounds>
<noboundscheck>0</noboundscheck> <noboundscheck>1</noboundscheck>
<useSwitchError>0</useSwitchError> <useSwitchError>0</useSwitchError>
<useUnitTests>0</useUnitTests> <useUnitTests>0</useUnitTests>
<useInline>0</useInline> <useInline>1</useInline>
<release>0</release> <release>0</release>
<preservePaths>0</preservePaths> <preservePaths>0</preservePaths>
<warnings>0</warnings> <warnings>0</warnings>
@ -68,7 +68,7 @@
<versionlevel>0</versionlevel> <versionlevel>0</versionlevel>
<versionids>Unicode USE_OPENGL</versionids> <versionids>Unicode USE_OPENGL</versionids>
<dump_source>0</dump_source> <dump_source>0</dump_source>
<mapverbosity>0</mapverbosity> <mapverbosity>3</mapverbosity>
<createImplib>0</createImplib> <createImplib>0</createImplib>
<defaultlibname /> <defaultlibname />
<debuglibname /> <debuglibname />
@ -89,7 +89,7 @@
<resfile /> <resfile />
<exefile>$(OutDir)\$(ProjectName).exe</exefile> <exefile>$(OutDir)\$(ProjectName).exe</exefile>
<useStdLibPath>1</useStdLibPath> <useStdLibPath>1</useStdLibPath>
<additionalOptions /> <additionalOptions>-profile</additionalOptions>
<preBuildCommand /> <preBuildCommand />
<postBuildCommand /> <postBuildCommand />
<filesToClean>*.obj;*.cmd;*.build;*.json;*.dep</filesToClean> <filesToClean>*.obj;*.cmd;*.build;*.json;*.dep</filesToClean>

View File

@ -41,21 +41,29 @@ version (USE_OPENGL) {
struct GlyphCache struct GlyphCache
{ {
Glyph[ushort] _map; Glyph[ushort] _map;
Glyph[0x10000] _array;
// find glyph in cache // find glyph in cache
Glyph * find(ushort glyphIndex) { Glyph * find(ushort glyphIndex) {
Glyph * res = (glyphIndex in _map); if (_array[glyphIndex].glyphIndex)
if (res !is null) return &_array[glyphIndex];
res.lastUsage = 1; return null;
return res;
//Glyph * res = (glyphIndex in _map);
//if (res !is null)
// res.lastUsage = 1;
//return res;
} }
/// put glyph to cache /// put glyph to cache
Glyph * put(ushort glyphIndex, Glyph * glyph) { Glyph * put(ushort glyphIndex, Glyph * glyph) {
_map[glyphIndex] = *glyph; _array[glyphIndex] = *glyph;
Glyph * res = glyphIndex in _map; return &_array[glyphIndex];
res.lastUsage = 1;
return res; //_map[glyphIndex] = *glyph;
//Glyph * res = glyphIndex in _map;
//res.lastUsage = 1;
//return res;
} }
// clear usage flags for all entries // clear usage flags for all entries
@ -112,13 +120,16 @@ class Font : RefCountedObject {
abstract @property bool isNull(); abstract @property bool isNull();
// measure text string, return accumulated widths[] (distance to end of n-th character), returns number of measured chars. // measure text string, return accumulated widths[] (distance to end of n-th character), returns number of measured chars.
abstract int measureText(const dchar[] text, ref int[] widths, int maxWidth); abstract int measureText(const dchar[] text, ref int[] widths, int maxWidth);
private int[] _textSizeBuffer; // to avoid GC
// measure text string as single line, returns width and height // measure text string as single line, returns width and height
Point textSize(const dchar[] text, int maxWidth = 3000) { Point textSize(const dchar[] text, int maxWidth = 3000) {
int[] widths = new int[text.length + 1]; if (_textSizeBuffer.length < text.length + 1)
int charsMeasured = measureText(text, widths, maxWidth); _textSizeBuffer.length = text.length + 1;
//int[] widths = new int[text.length + 1];
int charsMeasured = measureText(text, _textSizeBuffer, maxWidth);
if (charsMeasured < 1) if (charsMeasured < 1)
return Point(0,0); return Point(0,0);
return Point(widths[charsMeasured - 1], height); return Point(_textSizeBuffer[charsMeasured - 1], height);
} }
/// draw text string to buffer /// draw text string to buffer
abstract void drawText(DrawBuf buf, int x, int y, const dchar[] text, uint color); abstract void drawText(DrawBuf buf, int x, int y, const dchar[] text, uint color);

View File

@ -343,9 +343,16 @@ class FreeTypeFont : Font {
override Glyph * getCharGlyph(dchar ch, bool withImage = true) { override Glyph * getCharGlyph(dchar ch, bool withImage = true) {
if (ch > 0xFFFF) // do not support unicode chars above 0xFFFF - due to cache limitations if (ch > 0xFFFF) // do not support unicode chars above 0xFFFF - due to cache limitations
return null; return null;
long measureStart = std.datetime.Clock.currStdTime;
Glyph * found = _glyphCache.find(cast(ushort)ch); Glyph * found = _glyphCache.find(cast(ushort)ch);
long measureEnd = std.datetime.Clock.currStdTime;
long duration = measureEnd - measureStart;
//if (duration > 10000)
if (duration > 10000)
Log.d("ft _glyphCache.find took ", duration / 10, " ns");
if (found !is null) if (found !is null)
return found; return found;
Log.v("Glyph ", ch, " is not found in cache, getting from font");
FT_UInt index; FT_UInt index;
FreeTypeFontFile file; FreeTypeFontFile file;
if (!findGlyph(ch, 0, index, file)) { if (!findGlyph(ch, 0, index, file)) {
@ -391,18 +398,24 @@ class FreeTypeFont : Font {
uint len = cast(uint)text.length; uint len = cast(uint)text.length;
int x = 0; int x = 0;
int charsMeasured = 0; int charsMeasured = 0;
int * pwidths = widths.ptr;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Glyph * glyph = getCharGlyph(text[i], true); // TODO: what is better //auto measureStart = std.datetime.Clock.currAppTick;
Glyph * glyph = getCharGlyph(pstr[i], true); // TODO: what is better
//auto measureEnd = std.datetime.Clock.currAppTick;
//auto duration = measureEnd - measureStart;
//if (duration.length > 10)
// Log.d("ft measureText took ", duration.length, " ticks");
if (glyph is null) { if (glyph is null) {
// if no glyph, use previous width - treat as zero width // if no glyph, use previous width - treat as zero width
widths[i] = i > 0 ? widths[i-1] : 0; pwidths[i] = i > 0 ? pwidths[i-1] : 0;
continue; continue;
} }
int w = x + glyph.width; // using advance int w = x + glyph.width; // using advance
int w2 = x + glyph.originX + glyph.blackBoxX; // using black box int w2 = x + glyph.originX + glyph.blackBoxX; // using black box
if (w < w2) // choose bigger value if (w < w2) // choose bigger value
w = w2; w = w2;
widths[i] = w; pwidths[i] = w;
x += glyph.width; x += glyph.width;
charsMeasured = i + 1; charsMeasured = i + 1;
if (x > maxWidth) if (x > maxWidth)

View File

@ -32,8 +32,14 @@ class Window {
_dx = width; _dx = width;
_dy = height; _dy = height;
if (_mainWidget !is null) { if (_mainWidget !is null) {
Log.d("onResize ", _dx, "x", _dy);
long measureStart = currentTimeMillis;
_mainWidget.measure(_dx, _dy); _mainWidget.measure(_dx, _dy);
long measureEnd = currentTimeMillis;
Log.d("measure took ", measureEnd - measureStart, " ms");
_mainWidget.layout(Rect(0, 0, _dx, _dy)); _mainWidget.layout(Rect(0, 0, _dx, _dy));
long layoutEnd = currentTimeMillis;
Log.d("layout took ", layoutEnd - measureEnd, " ms");
} }
} }
@ -80,7 +86,7 @@ class Window {
_mainWidget.layout(Rect(0, 0, _dx, _dy)); _mainWidget.layout(Rect(0, 0, _dx, _dy));
long layoutEnd = currentTimeMillis; long layoutEnd = currentTimeMillis;
Log.d("layout took ", layoutEnd - measureEnd, " ms"); Log.d("layout took ", layoutEnd - measureEnd, " ms");
checkUpdateNeeded(needDraw, needLayout, animationActive); //checkUpdateNeeded(needDraw, needLayout, animationActive);
} }
long drawStart = currentTimeMillis; long drawStart = currentTimeMillis;
_mainWidget.onDraw(buf); _mainWidget.onDraw(buf);

View File

@ -561,7 +561,7 @@ int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
Platform.setInstance(platform); Platform.setInstance(platform);
if (false) { if (true) {
/// testing freetype font manager /// testing freetype font manager
import dlangui.graphics.ftfonts; import dlangui.graphics.ftfonts;
import win32.shlobj; import win32.shlobj;

View File

@ -34,7 +34,13 @@ class TextWidget : Widget {
override void measure(int parentWidth, int parentHeight) { override void measure(int parentWidth, int parentHeight) {
FontRef font = font(); FontRef font = font();
auto measureStart = std.datetime.Clock.currAppTick;
Point sz = font.textSize(text); Point sz = font.textSize(text);
auto measureEnd = std.datetime.Clock.currAppTick;
auto duration = measureEnd - measureStart;
//if (duration > 10000)
if (duration.length > 10)
Log.d("TextWidget measureText took ", duration.length, " ticks");
measuredContent(parentWidth, parentHeight, sz.x, sz.y); measuredContent(parentWidth, parentHeight, sz.x, sz.y);
} }