В моем приложении Blazor у меня есть компонент с таким методом. (Я заменил вызов GetFromJsonAsync кодом изнутри, чтобы сузить медленную часть.)
private async Task GetData()
{
IsLoading = true;
string url = $".../api/v1/Foo"; // will return a 1.5 MB JSON array
var client = clientFactory.CreateClient("MyNamedClient");
Console.WriteLine($"starting");
List<Foo> results;
Task<HttpResponseMessage> taskResponse = client.GetAsync(url, HttpCompletionOption.ResponseContentRead, default);
var sw = Stopwatch.StartNew();
using (HttpResponseMessage response = await taskResponse)
{
response.EnsureSuccessStatusCode();
var content = response.Content!;
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
string contentString = await content.ReadAsStringAsync();
sw.Stop();
Console.WriteLine($"Read string: {sw.Elapsed}");
sw.Restart();
results = System.Text.Json.JsonSerializer.Deserialize<List<Foo>>(contentString);
}
sw.Stop();
Console.WriteLine($"Deserialize: {sw.Elapsed}");
StateHasChanged();
IsLoading = false;
Моя загрузка 1,5 МБ занимает 1-6 секунд, но остальная часть операции (во время которой пользовательский интерфейс заблокирован) занимает 10-30 секунд. Это просто медленная десериализация в ReadFromJsonAsync
(которая вызывает System.Text.Json.JsonSerializer.Deserialize
внутренне), или здесь что-то еще происходит? Как повысить эффективность получения такого большого набора данных (хотя, я думаю, он не такой уж и большой!)
Я закомментировал все, что связано с Results
, чтобы упростить, и вместо этого у меня просто есть индикатор, привязанный к IsLoading
. Это говорит мне, что нет проблем с обновлением DOM или рендерингом.
Когда я пробую тот же набор кода в автоматическом интеграционном тесте, это занимает всего 3 секунды или около того. Действительно ли WebAssembly так медленно выполняет десериализацию? Если да, то является ли единственное решение извлекать очень маленькие наборы данных повсюду на моем сайте? Мне это не кажется правильным.
Вот итоговый журнал консоли браузера при выполнении вышеуказанного кода:
VM1131:1 Fetch finished loading: GET "https://localhost:5001/api/v1/Foo".
read string 00:00:05.5464300
Deserialize: 00:00:15.4109950
L: GC_MAJOR_SWEEP: major size: 3232K in use: 28547K
L: GC_MAJOR: (LOS overflow) time 18.49ms, stw 18.50ms los size: 2048K in use: 187K
L: GC_MINOR: (LOS overflow) time 0.33ms, stw 0.37ms promoted 0K major size: 3232K in use: 2014K los size: 2048K in use: 187K
Вот график производительности Chrome. Зеленый цвет - загрузка, а оранжевый - выполнение микрозадач, что, как я полагаю, означает работу WebAssembly.
Newtonsoft.Json.JsonConvert.DeserializeObject
вместоSystem.Text.Json.JsonSerializer.Deserialize
дает очень похожие результаты. - person Patrick Szalapski   schedule 05.08.2020