-
Notifications
You must be signed in to change notification settings - Fork 10.2k
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
why it always call gc collection make web run slower. #23701
Comments
Garbage collection happens when lots of objects have been allocated and memory has to be cleared up. Collection is unlikely to be a problem in itself, however it might indicate that you do have a problem with your code allocating too many objects. If you're able to supply some minimal repro code showing what's giving you performance issues, we might be able to make suggestions about how to improve it. |
I will try to upload test case later, thank you. |
here are my app code: @page "/Console"
@using Hunter.App.Shared.Models
@using Hunter.App.Shared
@using Hunter.App.Client.Services
@using Microsoft.AspNetCore.SignalR.Client;
@using WebAssembly.Browser.DOM;
@inject NavigationManager NavigationManager
@inject ConsoleHubClient consoleHub
<div class="hunterContainer">
<div class="hunterDevList">
<p>请选择要跟踪的客户端</p>
<hr />
@foreach (var clientData in _clientDataList)
{
<div class="hunterDevice @((clientData == this._curClientData? " selected" : ""))" @onclick="@(e => ListenToDevice(clientData.uid))">
<p class="hunterDeviceName">@clientData.name</p>
<p class="hunterDeviceOs">@string.Format("{0}({1})", clientData.uid, clientData.os)</p>
</div>
@*<DeviceListItem clientData="clientData" bSelected="@(clientData == curClientData)" OnClick="OnItemClick" />*@
}
</div>
<div class="hunterContent">
<div class="hunterContentHeader">
@if (_curClientData != null)
{
<p class="hunterDeviceName moveUp">@_curClientData.name</p>
<p class="hunterDeviceOs moveUp">@string.Format("{0}({1})", _curClientData.uid, _curClientData.os)</p>
}
</div>
<div class="hunterContentData" id="scrollView">
@*// <ol>*@
@foreach (string message in this._messages)
{
<div>@message</div>
}
@*</ol>*@
</div>
</div>
</div>
@code {
private DeviceInfo _curClientData;
private List<string> _messages = new List<string>();
List<DeviceInfo> _clientDataList = new List<DeviceInfo>();
HTMLDivElement scrollView;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
consoleHub.Connection.On<string>(HubMethodName.OnPrintLog, OnPrintLog);
consoleHub.On<string[]>(HubMethodName.OnPrintLogs, OnPrintLogs);
consoleHub.On<List<DeviceInfo>>(HubMethodName.OnQueryDevices, OnSyncDevices);
consoleHub.On<string>(HubMethodName.OnDeviceDisconnected, OnDeviceDisconnected);
consoleHub.Connection.On<int, string>(HubMethodName.OnListenToDevice, this.OnListendDevice);
// 再请求下,服务器连接成功会主动推送,但是可能Console页面还没有初始化,没有注册回调接受数据
if (consoleHub.IsConnected)
await consoleHub.SendAsync(HubMethodName.QueryDevices);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (scrollView == null)
scrollView = Web.Document.GetElementById<HTMLDivElement>("scrollView");
if (scrollView != null) // && _needScroll && _allowScroll)
{
scrollView.ScrollTo(0, scrollView.ScrollHeight);
}
}
protected override void OnInitialized()
{
base.OnInitialized();
}
private async Task OnPrintLog(string message)
{
await Task.Run(() => this.PushMessage(message));
}
private void OnPrintLogs(string[] messages)
{
if (messages == null && messages.Length == 0)
return;
foreach (string message in messages)
{
this.PushMessage(message, false);
}
StateHasChanged();
}
private void PushMessage(string message, bool dirtyState = true)
{
// long startDate = System.DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
while (this._messages.Count >= 600)
{
this._messages.RemoveAt(0);
}
this._messages.Add(message);
if (dirtyState)
StateHasChanged();
// long endDate = System.DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
// System.Console.WriteLine("------------------->PushMessage: {0}, cost: {1}", message, (endDate - startDate)/1000f);
}
void ListenToDevice(string uid)
{
if (_curClientData == null || _curClientData.uid != uid)
{
// await _hubConnection.SendAsync("ListeneToClient", Convert.ToString(clientData.id));
consoleHub.ListenToDevice(uid);
// this.PushMessage(MessageData.CreateSystemMessageData(string.Format("Listene To Client clientData.id = {0}", clientData.id)));
}
}
private void OnDeviceDisconnected(string uid)
{
if (this._curClientData.uid == uid)
{
this._curClientData = null;
StateHasChanged();
}
}
private void OnListendDevice(int code, string deviceId)
{
if (code != 0)
return;
foreach (DeviceInfo deviceInfo in this._clientDataList)
{
if (deviceInfo.uid == deviceId)
this._curClientData = deviceInfo;
}
// _curClientData = clientData;
_messages.Clear();
StateHasChanged();
}
private void OnSyncDevices(List<DeviceInfo> clientDataList)
{
_clientDataList = clientDataList;
if (_curClientData != null)
{
foreach (var clientData in _clientDataList)
{
if (clientData.id == _curClientData.id)
{
_curClientData = clientData;
break;
}
}
}
StateHasChanged();
}
} our app is used to show log, with the OnPrintLog callback, push the log message to web view |
A few things immediately stand out:
|
thank you, @SteveSandersonMS I will try it right now. |
hi, @SteveSandersonMS here are the code with your advice, I remove unrelated code from it, this all the work code: @page "/Console"
@using Hunter.App.Shared.Models
@using Hunter.App.Shared
@using Hunter.App.Client.Services
@using Microsoft.AspNetCore.SignalR.Client;
@using WebAssembly.Browser.DOM;
@inject NavigationManager NavigationManager
@inject ConsoleHubClient consoleHub
<div class="hunterContainer">
<div class="hunterDevList">
<p>请选择要跟踪的客户端</p>
<hr />
@foreach (var clientData in _clientDataList)
{
<div class="hunterDevice @((clientData == this._curClientData? " selected" : ""))" @onclick="@(e => ListenToDevice(clientData.uid))" @key="clientData">
<p class="hunterDeviceName">@clientData.name</p>
<p class="hunterDeviceOs">@string.Format("{0}({1})", clientData.uid, clientData.os)</p>
</div>
}
</div>
<div class="hunterContent">
<div class="hunterContentHeader" @key="_curClientData">
@if (_curClientData != null)
{
<p class="hunterDeviceName moveUp">@_curClientData.name</p>
<p class="hunterDeviceOs moveUp">@string.Format("{0}({1})", _curClientData.uid, _curClientData.os)</p>
}
</div>
<div class="hunterContentData" id="scrollView" @key="_messages">
@foreach (MessageData message in this._messages)
{
<div @key="message">@message.content</div>
}
</div>
</div>
</div>
@code {
private DeviceInfo _curClientData;
private List<MessageData> _messages = new List<MessageData>();
private int _messageCount = 0;
List<DeviceInfo> _clientDataList = new List<DeviceInfo>();
HTMLDivElement scrollView;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
consoleHub.Connection.On<string>(HubMethodName.OnPrintLog, OnPrintLog);
consoleHub.On<string[]>(HubMethodName.OnPrintLogs, OnPrintLogs);
consoleHub.On<List<DeviceInfo>>(HubMethodName.OnQueryDevices, OnSyncDevices);
consoleHub.On<string>(HubMethodName.OnDeviceDisconnected, OnDeviceDisconnected);
consoleHub.Connection.On<int, string>(HubMethodName.OnListenToDevice, this.OnListendDevice);
// 再请求下,服务器连接成功会主动推送,但是可能Console页面还没有初始化,没有注册回调接受数据
if (consoleHub.IsConnected)
await consoleHub.SendAsync(HubMethodName.QueryDevices);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (scrollView == null)
scrollView = Web.Document.GetElementById<HTMLDivElement>("scrollView");
if (scrollView != null) // && _needScroll && _allowScroll)
{
scrollView.ScrollTo(0, scrollView.ScrollHeight);
}
}
private void OnPrintLog(string message)
{
this.PushMessage(message);
}
private void PushMessage(string message, bool dirtyState = true)
{
while (this._messages.Count >= Hunter.Shared.Config.LogMessageMaxCount)
{
this._messages.RemoveAt(0);
}
this._messages.Add(MessageData.Create(message));
if (dirtyState)
StateHasChanged();
}
} I create div element always with @key, so it make no differnece with make child component of log messages. but it also make ui freeze, as the performance of chrome DevTools it took a lot of time to execute script. |
@srxqds How fast do your log messages arrive? How many per second? Can you estimate the rate at which it becomes problematic? |
I dispatch the message on server side 30 times per second, and only with 1000 line total message. |
Re-rendering the whole log 30 times per second is going to put a lot of strain on the browser. It certainly can run that fast (on a reasonable laptop anyway) but I wouldn't do that for something that's meant to be left going in the background because it will still hurt the device's battery life. Two techniques you can try to do this with much less CPU load are:
|
Thank you @SteveSandersonMS, I use the timer up update view. |
Describe the bug
why always call gc collection?
To Reproduce
Exceptions (if any)
Further technical details
dotnet --info
: 3.1.4The text was updated successfully, but these errors were encountered: