GDI render Windows 7 vs Windows 10

New desktop computer (LCD 4K, AMD 5900X - 12 cores, 24 threads, SSD NVMe, 32GB RAM, GTX 1070 8GB / Memory Bandwidth 256 GB/s) and what? The charts lags and they are about two times slower (Windows 10) than in old computer with Windows 7 ( Intel Core i5 2500K - 4 cores, 4 thread, the same graphics cart).

Simply 6 panes in one chart:
Windows 7 GDI render: 220 ms
Windows 10 GDI render: 400 ms
On much more software bloat charts I permanently see "Warning 901. Chart incomplete. Rendering timeout reached (1046ms). Rendered 7 plots"!.

Is there some magical solution for that?

Here you go

Check again. It should run fine now.


Are there any 3rd party plugins involved or AB plugins that do not come with default setup?

AB setups are exactly the same ones (same AB version and bitness, same DB and data source, same AFL and layouts, ...)?

What is Antivirus on W10?
Have you excluded AB folders from AV scanning?

1 Like

There is also similar problem with Metatrader 4, but Metatrader 5 works very well.

Do you connect AB and MT4 via DDE?

No. I tested on local data.

https://social.technet.microsoft.com/Forums/...

It would be much easier to help you, if you share your code, so we could compare the timings. At least the simplified version of it...

200 or 400 ms for GDI render is definitely way too much. It seems that your code is very ineffective and uses all bars. Is it necessary? In most cases not. If the chart is forced to use all bars instead of the visible ones, the timings might skyrocket. Check the code for SetBarsRequired() line.

You wrote that you have same DB, but I still think that the discrepancies in GDI render timings between an old and a new setup might come from the fact that you have more bars in your newer database (i.e. 1M instead of 500K).

Also you might see if you have below options checked:

Render

There is simple charts with "Price all in one" and "Volume at price multi". About 6000 bars. No realtime data.

Look at this (!):

1/4 of screen (Multi-threaded enabled):
1-4 enabled

1/4 of screen (Multi-threaded disabled!):
1-4 disabled

Full screen (Multi-threaded enabled):
Chart timing: about 900 ms

Full screen (Multi-threaded disabled!):
Chart timing: about 450 ms

????

This is interesting: www

I see you use an NVIDIA GTX 1070.

Try downloading and installing a fresh set of GPU graphics drivers:
https://www.nvidia.com/Download/index.aspx?lang=en-us

If Windows has not be activated you should do that too.

Also make sure you have all Windows Updates installed. Don't believe Windows when it says "up to date" especially on a new install. Click the Check for Updates button. After an update/reboot do this again - you might need to do several rounds of this to actually bring your system up-to-date.

Post from 2016.
Can a fast GPU speed up drawing complex charts?

Answer from Tomasz Janeczko:
"Hello,

That depends on many factors, including operating system you are using and graphic card drivers.
AmiBroker currently uses GDI which is pretty fast because it is simple.

Depending on OS and graphic card that you use GDI may or may not be hardware accelerated.
To surprise of many people Windows XP and earlier had hardware accelerated GDI but
Vista does not, Win 7 and higher only in small portion (BitBlt and AlphaBlend).
In the old days, all graphic card drivers have hardware accelerated 2D primitives.

Microsoft expects people to use new APIs every now and then but new APIs have many compatibility
problems (not working on Terminal server for example) and are not necessarily faster.
For example GDIPlus is 10 times slower.

Direct2D that is newest API from MS for 2D rendering requires modern graphic card
and most recent OS (Windows 7 or higher) and does not work in some scenarios.

It produces nicely anti-aliased output BUT... there is no 2D hardware on the graphic card.
So it does that using 3D hardware and
this makes it not as fast as you would expect,
because to actually draw a single line it sends two 3D triangles to graphic card 3D rendering engine.
Single pixel is also rendered as two 3D triangles (because all hardware 3D rendering on graphic cards is based on triangles).

So, you won't gain much speed with newest Direct2D and even most modern graphic card .
Actual measured difference is just 1.5....2x.
Bigger difference can only be seen if rendering on very high resolutions (4K and higher).

The gains are small because most of the time is not spent on rendering but on CPU => GPU communication.
"

Hello, we have 2021. Bigger screens, faster CPU, GPU, SSD....

First and foremost: you did not provide necessary information to give you an anwer, namely THE FORMULA that you are using ( Please follow this advice: How to ask a good question )

Given the same formula, the difference in rendering time are most likely due to different resolution and/or bit depth. GDI in both Windows 7 and Windows 10 are software only (the only hardware accelerated stuff is AlphaBlend and BitBlit, color fills. Line drawing is NOT hardware accelerated in Window 7 and higher see this), so speed is merely limited by the number of RAM data writes that CPU can make). GDI was hardware accelerated in Windows XP and earlier but Microsoft decided to drop hardware acceleration in GDI: Did you know: All GDI apps render slower under Win7? - Windows - Neowin

Judging from your screenshots you are drawing lots of vertical lines (again no formula, just guessing). To improve performance remove them. Again SEND THE FORMULA if you want help.

The difference between time in multithreading and single threading GDI is caused by the fact that GDI has internal synchronization (inside Windows) locks that prevents fully parallel execution) and also about the fact that multiple threads compete against RAM bandwidth. So these timings are really comparing apples to oranges because in single-threading mode these chart panes run ONE after another (SEQUENTIALLY ONE at a time). While in multi-threading mode they ALL RENDER IN PARALLEL. So total time to render ALL PANES in multithreading case is just 372ms (max value from all panes). While in single threading case it is 208+201+198+199 = 806ms.
So multithreading is 2.2x faster, not slower as you might think.

The time reported in "chart timing" figure in multi-threading case is sum of times from MULTIPLE threads. If say 8 threads execute for 1 second it would say 8 seconds, even if it took 1 second of PHYSICAL time.

And what I wrote about GDIPlus and Direct2D is still 100% correct. 2021 and SSD does not change things. And Direct2D is SLOWER than GDI for simple geometry like lines and pixels (that make almost 100% of charts)

5 Likes
_SECTION_BEGIN("Price");
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) Vol " +WriteVal( V, 1.0 ) +" {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 )) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 
_SECTION_END();

_SECTION_BEGIN("MA");
P = ParamField("Price field",-1);
Periods = Param("Periods", 15, 2, 200, 1 );
Plot( MA( P, Periods ), _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle("Style", styleLine | styleNoLabel ) | styleNoRescale ); 
_SECTION_END();

_SECTION_BEGIN("Mid MA");
P = ParamField("Price field",-1);
Periods = Param("Periods", 45, 2, 300, 1 );
Plot( MA( P, Periods ), _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle("Style", styleLine | styleNoLabel ) | styleNoRescale ); 
_SECTION_END();

_SECTION_BEGIN("Long MA");
P = ParamField("Price field",-1);
Periods = Param("Periods", 100, 2, 400, 1 );
Plot( MA( P, Periods ), _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle("Style", styleLine | styleNoLabel ) | styleNoRescale ); 
_SECTION_END();

_SECTION_BEGIN("BBands");
P = ParamField("Price field",-1);
Periods = Param("Periods", 15, 2, 100, 1 );
Width = Param("Width", 2, 0, 10, 0.05 );
Color = ParamColor("Color", colorLightGrey );
Color = ColorBlend( Color,  GetChartBkColor(), 0.5 );
Style = ParamStyle("Style", styleLine | styleNoLabel ) | styleNoRescale;;
Plot( bbt = BBandTop( P, Periods, Width ), "BBTop" + _PARAM_VALUES(), Color, Style ); 
Plot( bbb = BBandBot( P, Periods, Width ), "BBBot" + _PARAM_VALUES(), Color, Style ); 
PlotOHLC( bbt, bbt, bbb, bbb, "", ColorBlend( Color, GetChartBkColor(), 0.7 ), styleNoLabel | styleCloud | styleNoRescale, Null, Null, Null, -1 );
_SECTION_END();

_SECTION_BEGIN("Volume");
Color = ParamColor("Color", ColorRGB( 128, 128, 192 ) );
Plot( Volume, _DEFAULT_NAME(), ColorBlend( Color, GetChartBkColor(), 0.5  ), styleNoTitle | ParamStyle( "Style", styleHistogram | styleOwnScale | styleThick | styleNoLabel, maskHistogram  ), 2 );
_SECTION_END();

_SECTION_BEGIN("Price Interpretation");
movshort = ParamField("Short Time MA", 8 );
movmed = ParamField("Mid Time MA", 9 );
movlong = ParamField("Long Time MA", 10 );
btop = ParamField("BBTop", 11 );
bbot = ParamField("BBBottom", 12 );
if( Status("action") == actionCommentary )
{
width = btop - bbot;
lslop = LinRegSlope( C, 30 ) + 100;
lslo = LLV( lslop, 90 );
lshi = HHV( lslop, 90 );
lswidth = lshi - lslo;
trend = 100*( lslop - lslo )/lswidth;

mawidth = MA( width, 100 );
relwidth = 100*(width - mawidth)/mawidth;

_N( tname = Name()+"("+FullName()+")" );

printf("Price and moving averages:\n");
printf( "%s", tname + " has closed " + WriteIf( C > movshort, "above" , "below" ) + " its Short time moving average. ");

printf( "%s", "\nShort time moving average is currently " + WriteIf( movshort > movmed, "above", "below") + " mid-time, AND " + WriteIf( movshort > movlong, "above", "below" ) + " long time moving averages.");

printf( "%s", "\nThe relationship between price and moving averages is: "+
WriteIf( C > movshort AND movshort > movmed, "bullish",
WriteIf( C < movshort AND movshort < movmed, "bearish", "neutral" ) ) + " in short-term, and "+
WriteIf( movshort > movmed AND movmed > movlong , "bullish",
WriteIf( movshort < movmed AND movmed < movlong, "bearish", "neutral" ) ) + " in mid-long term. ");

printf("\n\nBollinger Bands:\n");
printf("%s", tname+ " has closed " + 
WriteIf( C < bbot, "below the lower band by " +
WriteVal( 100 *( bbot-C )/ width, 1.1 ) + "%. " +
WriteIf( trend < 30, " This combined with the steep downtrend can suggest that the downward trend in prices has a good chance of continuing.  However, a short-term pull-back inside the bands is likely.",
WriteIf( trend > 30 AND trend < 70, "Although prices have broken the lower band and a downside breakout is possible, the most likely scenario for "+tname+" is to continue within current trading range.", "" ) ), "" ) +

WriteIf( C > btop, "above the upper band by " +
WriteVal( 100 *( C- btop )/ width, 1.1 ) + "%. " +
WriteIf( trend > 70, " This combined with the steep uptrend suggests that the upward trend in prices has a good chance of continuing.  However, a short-term pull-back inside the bands is likely.",
WriteIf( trend > 30 AND trend < 70, "Although prices have broken the upper band and a upside breakout is possible, the most likely scenario for "+tname+" is to continue within current trading range.", "" ) ), "" ) +

WriteIf( C < btop AND ( ( btop - C ) / width ) < 0.5, 
"below upper band by " +
WriteVal( 100 *( btop - C )/ width, 1.1 ) + "%. ", 
WriteIf( C < btop AND C > bbot , "above bottom band by " +
WriteVal( 100 *( C - bbot )/ width, 1.1 ) + "%. ", "" ) ));

printf("%s", "\n"+
WriteIf( ( trend > 30 AND trend < 70 AND ( C > btop OR C < bbot ) ) AND abs(relwidth) > 40,
		 "This picture becomes somewhat unclear due to the fact that Bollinger Bands are  currently",
		 "Bollinger Bands are " )+	  
WriteVal( abs( relwidth ), 1.1 ) + "% " +
WriteIf( relwidth > 0, "wider" , "narrower" ) +
" than normal.");

printf("\n");

printf("%s",
WriteIf( abs( relwidth ) < 40, "The current width of the bands (alone) does not suggest anything conclusive about the future volatility or movement of prices.","")+
WriteIf( relwidth < -40, "The narrow width of the bands suggests low volatility as compared to " + tname + "'s normal range.  Therefore, the probability of volatility increasing with a sharp price move has increased for the near-term. "+
"The bands have been in this narrow range for " + WriteVal(BarsSince(Cross(-40,relwidth)),1.0) + " bars. The probability of a significant price move increases the longer the bands remain in this narrow range." ,"")+
WriteIf( relwidth > 40, "The large width of the bands suggest high volatility as compared to " + tname + "'s normal range.  Therefore, the probability of volatility decreasing and prices entering (or remaining in) a trading range has increased for the near-term. "+
"The bands have been in this wide range for  " + WriteVal(BarsSince(Cross(relwidth,40)),1.0) + " bars.The probability of prices consolidating into a less volatile trading range increases the longer the bands remain in this wide range." ,""));

printf("\n\nThis commentary is not a recommendation to buy or sell. Use at your own risk.");
}
_SECTION_END();

_SECTION_BEGIN("Price");
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 
_SECTION_END();

_SECTION_BEGIN("VAP");
segments = IIf( Interval() < inDaily, Day(), Month() );
segments = segments != Ref( segments , -1 );

PlotVAPOverlayA( segments , Param("Lines", 300, 100, 1000, 1 ), Param("Width", 80, 1, 100, 1 ), ParamColor("Color", colorGold ), ParamToggle("Side", "Left|Right" ) | 2 * ParamToggle("Style", "Fill|Lines", 0) | 4*ParamToggle("Z-order", "On top|Behind", 1 ) );
Plot(segments, "", colorLightGrey, styleHistogram | styleOwnScale );
_SECTION_END();

So it is bad that I disable Multi-threaded chart+GDI?

You are using PlotVapOverlayA EVERY day/month. This is a killer if you want to display 22 years of data because it is may need to render millions of lines (that you barely see at this zoom level yet they need to be drawn).
Try removing PlotVapOverlayA in this zoom level and retry.

I tried your formula with pretty much same data set (FW20 from 2000), 5400 daily bars and my timings (zoom out max) and 4 panes without PlotVapOverlay are merely 32ms per pane

image

With PlotVapOverlayA it goes up to 139-144 ms per pane. This is Windows 10 WITHOUT dedicated graphic card (just very low-end integrated Intel HD620 graphics)

image

This means that ALL panes are redrawn in 144 ms of physical time. (that is max timing from all threads).

So your timings look too high.

As to this question:

It is bad if you want fast refreshes. Multithreading charts draw faster and refresh much more often. As I explained, even though you see 900ms of time it is SUM from multiple threads. Physical time however is approx 900ms/number of threads.

I know, but I used it intentionally for testing differences between W7, W10, W11 (results coming soon).

As I wrote: without dedicated graphic card I am getting 140ms total rendering time with PlotVapOverlayA for all 4 panes and multi-threading enabled on Windows 10.

But I use 4K LCD without "Override high DPI scaling behavior". For full screen of AmiBroker this timing is about 900 ms (for 25% size of AmiBroker 372 ms). When I use override high DPI "System (Enhanced)" for AmiBroker, timing is much more acceptable.

OK, now when you provided missing pieces of information (formula and the information about 4K screen), it makes much more sense. On 4K screens there are 8.5 million pixels to pump (34MB framebuffer). That is quite a lot of RAM access

GDI render test for 4K LCD results:
GDI render for 4K LCD
Conslusion: Windows 10 and Windows 11 are SUCKS!