Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

High CPU usage with 1.0.781-prerelease #878

Closed
AbeniMatteo opened this issue Jan 30, 2021 · 15 comments
Closed

High CPU usage with 1.0.781-prerelease #878

AbeniMatteo opened this issue Jan 30, 2021 · 15 comments
Labels
bug Something isn't working tracked We are tracking this work internally.

Comments

@AbeniMatteo
Copy link

AbeniMatteo commented Jan 30, 2021

Description
High CPU usage while doing nothing. This problem is only present from 1.0.781-prerelease.
1.0.721-prerelease and 1.0.705.50 are ok.

Version
SDK: 1.0.781-prerelease
Runtime: 89.0.774.8 (Official build) dev (64-bit)
Framework: .NET 5.0.102 + WPF
OS: Win10 10.0.19042 Build 19042

Repro Steps
Run the following code:

Program.cs

namespace Repro
{
    using System;
    using System.Windows;
    using Microsoft.Web.WebView2.Wpf;

    static class Program
    {
        [STAThread]
        static void Main()
        {
            // Init Application.Current
            new Application();
            var w = new Window();
            w.Content = new WebView2();
            w.ShowDialog();
        }
    }
}

Repro.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Web.WebView2" Version="1.0.781-prerelease" />
  </ItemGroup>
</Project>

AB#31577027

@albahari
Copy link

albahari commented Feb 1, 2021

I've reproduced this problem with both the WPF and WinForms controls.

It's caused by a continuous stream of WM_PAINT messages being generated, keeping the UI thread close to 100% busy. This also saturates the message loop and sometimes prevents other controls from receiving a WM_PAINT. You can verify this as follows:

public class WebView2Ex : WebView2
{
    protected override IntPtr WndProc (IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        Debug.WriteLine (msg);
        return base.WndProc (hwnd, msg, wParam, lParam, ref handled);
    }
}

This needs to be fixed ASAP, because the control is close to unusable right now.

@tildebox
Copy link

tildebox commented Feb 2, 2021

~15% CPU usage. I had to downgrade to 1.0.705.50.

@champnic
Copy link
Member

champnic commented Feb 2, 2021

Thanks for finding this - I've filed a bug on our backlog and we're taking a look right away.

@champnic champnic added the tracked We are tracking this work internally. label Feb 2, 2021
@johna-ms
Copy link
Contributor

johna-ms commented Feb 3, 2021

Hello all! We are working on getting another release turned around as soon as possible with the fix for this. In the mean time, you can try this workaround:

  • Extend the WebView control with your own control
  • Override the WndProc method
  • Check for the WM_PAINT window message (0x000F), call BeginPaint, EndPaint, and return IntPtr.Zero
    • Begin/EndPaint are Win32 APIs and you'll need to DllImport them. Here's the code we used:
    •  `[StructLayout(LayoutKind.Sequential)]
          public struct Rect
          {
              public int left;
              public int top;
              public int right;
              public int bottom;
          }
      
          [StructLayout(LayoutKind.Sequential)]
          public struct PaintStruct
          {
              public IntPtr hdc;
              public bool fErase;
              public Rect rcPaint;
              public bool fRestore;
              public bool fIncUpdate;
              [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] public byte[] rgbReserved;
          }
      
          [DllImport("user32.dll", SetLastError = true)]
          public static extern IntPtr BeginPaint(IntPtr hwnd, out PaintStruct lpPaint);
      
          [DllImport("user32.dll", SetLastError = true)]
          public static extern bool EndPaint(IntPtr hwnd, ref PaintStruct lpPaint);`
      

@ukandrewc
Copy link

This sort of works, but still got the issues with z-order. Any WebView2 that paints, comes to the front.

@johna-ms
Copy link
Contributor

johna-ms commented Feb 4, 2021

@ukandrewc does your code in WndProc look like this?

    `protected override void WndProc(ref Message m)
    {
        switch (unchecked((NativeMethods.WM)m.Msg))
        {
            case NativeMethods.WM.PAINT:
            {
                NativeMethods.PaintStruct lpPaint;
                NativeMethods.BeginPaint(m.HWnd, out lpPaint);
                NativeMethods.EndPaint(m.HWnd, ref lpPaint);
                m.Result = IntPtr.Zero;
                return;
            }
        }
        base.WndProc(ref m);
    }`

Re: your last message, you don't need to fill out PaintStruct at all

@ukandrewc
Copy link

ukandrewc commented Feb 4, 2021

@johna-ms Yes, it does (I work in VB, but it's the same)

I've attached a screen-capture (had to zip as GitHub not accepting wmv)

There are two WebView2s controlled by z-order (Web1, Web2)

When the 2nd tab is clicked it calls web2.BringToFront(), but when eBay (Web1) refreshes, it becomes visible again. Not sure if it's transparency or Z order.

Video_2021-02-04_130715.zip

For anyone else in VB:

Imports System.Runtime.InteropServices
Public Class WVBrowser : Inherits WebView2

	<StructLayout(LayoutKind.Sequential)>
	Private Structure Rect
		Public left As Integer
		Public top As Integer
		Public right As Integer
		Public bottom As Integer
	End Structure

	<StructLayout(LayoutKind.Sequential)>
	Private Structure PaintStruct
		Public hdc As IntPtr
		Public fErase As Boolean
		Public rcPaint As Rect
		Public fRestore As Boolean
		Public fIncUpdate As Boolean
		<MarshalAs(UnmanagedType.ByValArray, SizeConst:=32)>
		Public rgbReserved As Byte()
	End Structure

	<DllImport("user32.dll", SetLastError:=True)>
	Private Shared Function BeginPaint(ByVal hwnd As IntPtr, <Out> ByRef lpPaint As PaintStruct) As IntPtr
	End Function

	<DllImport("user32.dll", SetLastError:=True)>
	Private Shared Function EndPaint(ByVal hwnd As IntPtr, ByRef lpPaint As PaintStruct) As Boolean
	End Function

	Protected Overrides Sub WndProc(ByRef m As Message)
		If m.Msg = &HF Then
			Dim PS As New PaintStruct
			BeginPaint(m.HWnd, PS)
			EndPaint(m.HWnd, PS)
			m.Result = IntPtr.Zero
		Else
			MyBase.WndProc(m)
		End If
	End Sub

End Class

Thanks, I deleted the question once I'd read your code properly (been a while since I've done any winapi) ;-)

@johna-ms
Copy link
Contributor

johna-ms commented Feb 4, 2021

So this fixes the CPU issue for you but not the related issue about items refreshing on the form?

Seems like you're finding a different issue? So this doesn't repro on the older prerelease package? I'm going to work on a repro for this to investigate.

@ukandrewc
Copy link

ukandrewc commented Feb 4, 2021

Yes, sorry, just realised this issue is only for High CPU usage, not #875.

It does allow other controls on the form to refresh normally, but I'm still still seeing transparency issues with Z order (Shown in the video above)

I also had to add Web2.Refresh() after Web2.BringToFront()

@ukandrewc
Copy link

ukandrewc commented Feb 4, 2021

It seems that whichever WebView2 paints last, gets to be visible, but this doesn't affect main scrollbars.

When Web2 is at the front of Z order, and Web1 is refreshed, it becomes visible. Scrolling Web2, shows it's content again (until Web1 content changes).

@johna-ms
Copy link
Contributor

johna-ms commented Feb 4, 2021

Ok that's definitely weird. We're tracking it on our end as a separate issue. Thanks!

@ukandrewc
Copy link

In the video Web2 is at the front (HTML Table)
When Web1 banner (eBay) refreshes, it is visible.
Scrolling Web2 (scrollbar is Web2's) shows it again (until eBay content changes)

Video_2021-02-04_194717.mp4

@johna-ms
Copy link
Contributor

johna-ms commented Feb 4, 2021

Tracking this on github here

#897

@ukandrewc
Copy link

Thanks

@champnic
Copy link
Member

The high CPU usage should now be fixed in 1.0.790-prerelease SDK package. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working tracked We are tracking this work internally.
Projects
None yet
Development

No branches or pull requests

6 participants