7

Can someone explain me why TWebBrowser control is working so slow on all XE editions of Delphi including XE5 and possibly XE6? To test this you need to create a new Delphi project and put TWebBrowser control in it. On form show event, navigate to this website:

http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html

Please test this on Windows 7 or later. When navigation is complete, run setImmediate test and watch the results. It will take huge amount of time to complete the test. It will take about a minute to finish this.

When you open true Internet Explorer browser and do the same thing - test will be completed instantly (~200 miliseconds).

Some additional wierd informations:

When you recreate this procedure on old versions of Delphi (Delphi 7 to be precise) the web-control works as fast as it should be working and test is completed instantly. But the HTML5 speed test will still works slow (alternative test on this page).

Another weird thing is, the same slow behavior can be seen on C++ Builder but not in Visual Studio products. Is Microsoft deliberately slowing down the TWebBorwser in Embarcadero products?? I can't belive this.

I was trying to overcome this problem with diffrent methods such as:

  1. Trying different feature options in registry such as: FEATURE_GPU_RENDERING, FEATURE_BROWSER_EMULATION (11001), FEATURE_ALIGNED_TIMERS (undocumented option), FEATURE_ALLOW_HIGHFREQ_TIMER (undocumented option),

  2. Setting timerBeginPeriod(1) - no effect.

Please, if someone have any clue how to fix this issue - share this information with me.

UPDATE1 I made standalone test app if anyone cares. It can be downloaded here: http://mp.org.pl/download/ietest.zip It contains source and exe app with htm file. HTM file contains some js procedure that works 10 times faster in standalone IE than in TWebBrowser control. It uses setImmediate as a test (the same procedure used in test described above). But it can be easier for testing this way.

Oconnel
  • 71
  • 4
  • My guess is that IE when embedded in your app is using a compatibility-view implicitly. Check your registry configurations and learn how to make your own application have an explicit configuration for IShellDocView's compatibility-view settings. The compatibility view is probably causing an ancient slow JavaScript or HTML engine to be used, equivalent to IE 7 or IE 8, instead of modern IE. You are on the right track with the FEATURE_BROWSER_EMULATION item, but you did not specify what you tried exactly, what values, etc. – Warren P Jul 28 '14 at 16:51
  • 1
    Also does this behavior show up when you use TEmbeddedWB? cf: https://github.com/danielfrimerman/Delphi-EmbeddedWB-XE3 OR my version: https://bitbucket.org/wpostma/tembeddedwb – Warren P Jul 28 '14 at 16:54
  • Can you post an SSCCE? – whosrdaddy Jul 28 '14 at 17:00
  • I tested all compatibility modes, and you can check it for yourself too. I specify that I used 11001 setting (which is forced IE11). None of those settings gives any results - but they are in effect). I tested your component in a matter of fact with same poor results. What is very weird is that old compiled versions of apps written in Delphi (which none of them made any changes in registry) works just fine. The problem occurs only on XE versions of Delphi and later. The Delphi chromimum project delivers very nice performance but I can't use this in my project. I need TWebBrowser to do the job. – Oconnel Jul 28 '14 at 17:17
  • 2
    `SetImmediate` is a classic MS hack. No surprise it doesn't work as expected in this context. Try this --> Start the test, drag your form's window around, and watch the test suddenly race to complete. The performance seems tied to the busy-ness of the host application's message loop. This behaviour is the same for me in C#(VS2010) also -- `Windows.Forms.WebBrowser` control. Internet Explorer proper probably does something internally to lubricate the functionality of SetImmediate. As for why it seems to work in D7...who knows?? – J... Jul 28 '14 at 18:44
  • So it seems it has some connection to message loop indeed. But poor performance is a real deal. CSS animations which I use are much slower in TWebBrowser because of this too. So is there any way to force proper behavior? I have app app writen in Visual Studio and it works fine with the same ieframe.dll file. And thank you for your post - it is helpful. But we must investigate further. BTW - if I just press LMB on titlebar and I will hold it, a timer speeds up too. – Oconnel Jul 28 '14 at 19:03
  • @Oconnel - if your animations are relying on `SetImmediate` then the best solution is simply not to use it and to switch the implementation to something that is standard and supported on all browsers. Even the 15ms callbacks in HTML4 should be more that sufficient for a simple animation. Otherwise, `PostMessage`, etc... – J... Jul 29 '14 at 10:47
  • Well it's not good for me. I need and I want to use setImmediate, beside HTML5 test is much slower too. There has to be some way to fix this another way... – Oconnel Jul 29 '14 at 11:48

1 Answers1

1

I can also see the behavior described (in your original post and in the comments). I have a few thoughts, but not necessarily an answer.

One should expect some difference in performance between the WebBrowser control and IE, in part because your Delphi app will need to build in support for certain features/APIs that IE supports out of the box.

For example, the WebBrowser control fires notifications related to tabbed browsing (old, but relevant), but it does not intrinsically handle those notifications or update the UI. You have to respond to the notifications and draw the tabs yourself. By default, IE is hardware accelerated and uses certain Windows APIs that may not be directly supported by Delphi's VCL (for resource/performance) reasons. (Hardware acceleration could account for some of the performance differences you've noticed.)

(And, for the record, I don't believe a list of differences between IE and the WebBrowser control was ever documented. I certainly don't remember seeing one in the portfolio.)

Also, the default values for various feature controls vary between IE and applications hosting the WebBrowser control. Part of the reason for this stems from the idea that IE needs to highlight performance over compatibility whereas applications generally need to emphasize compatibility over performance. You may wish to review the feature control reference to see if there are other FCKs you need to enable for your app.

Second, your loops are very tight, perhaps too tight. You've got one request piling on earlier requests and you're not really leaving much room for processing, even with setImmediate. (IIRC, we're not really supposed to use anything smaller than 250ms for setInterval without risking performance hits from the sheer number of requests.) The remarks in the setImmdiate ref. page provide some guidance, as does this article on requestAnimationFrame.

One reason why dragging the window appears to improve performance may due to the priority of window drag repaint requests. They may be forcing your loops to hold long enough (or even break) to allow other events to process. Hard to say without with tracing the system with a debugger.

Have you ever had to add application.processMessages() to your Delphi apps in order to allow the system a chance to handle the work you've already assigned? A similar need may be coming into play given the nature of your test.

Performance testing and timing is a tricky thing. You need to make sure the test isn't imposing so much overhead that it interferes with the actual work you're trying to perform.

Finally, there were some questions about the document mode of the page as it's loaded into your project. When I first started messing around with your sample, I couldn't get project4 to load slowtest.html in anything other than IE5 quirks mode (notoriously slow). Here's what eventually started working for me:

<!DOCTYPE html>
<!-- saved from url=(0023)http://www.contoso.com/ --> 
<html>
<head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
  <script type="text/javascript">
  ...

(Note, I deleted your initial doctype declaration and rewrite it to resolve a syntax error that was being reported by the F12 tools debugger.)

A few style key points here:

  • I used a mark of the web to load the page in the Internet zone. I find this makes it easier to load the page in edge mode, as pages in the intranet zone are loaded in compatibility view by default (unless you map the zones differently).

  • The x-ua-compatible header needs to be one of the first in the head block. It can follow title, but not much else.

  • Stylistically, elements need to be specified in lower case these days. There's a possibility that not following the current conventions forces the parser to fall back to an earlier rendering that supports the conventions.

Once I was able to control the documentMode at runtime, I found results I expected: older document modes ran more slowly. I also found that using requestAnimationFrame instead of setImmediate led to even better performance, but also surfaced the timing issue almost immediately.

In the end, this may be a case where the test highlights a problem, but not necessarily one you're trying to solve. (Insert Inigo meme here.) I get that you're trying to resolve a bottleneck. Are you sure you've found the correct bottleneck?

You may not be able to replicate the same performance of the native browser, but perhaps you can refactor the code to perform adequately without the extra overhead? Is there anything that might be better handled with a worker or some other implementation technique?

Hope this helps...

Lance Leonard
  • 3,285
  • 3
  • 16
  • 15