From 1ea2b200c0b38f9d9a058f5e4b6e27815a016860 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 12 Jan 2021 15:28:02 +0100 Subject: [PATCH] JsonSerializer deserialize from bytes where possible This is faster and uses way less memory ``` BenchmarkDotNet=v0.12.1, OS=fedora 32 Intel Core i7-6700HQ CPU 2.60GHz (Skylake), 1 CPU, 8 logical and 4 physical cores .NET Core SDK=5.0.100 [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT DefaultJob : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT | Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | |------- |---------:|--------:|--------:|--------:|------:|------:|----------:| | Bytes | 158.4 us | 2.56 us | 2.14 us | 16.8457 | - | - | 52.08 KB | | String | 172.8 us | 0.78 us | 0.70 us | 41.5039 | - | - | 127.82 KB | | Custom | 155.5 us | 2.95 us | 2.76 us | 10.0098 | - | - | 31.27 KB | ``` --- .../Channels/ChannelManager.cs | 10 +++++----- .../LiveTv/EmbyTV/ItemDataProvider.cs | 6 +++--- .../Plugins/PluginManager.cs | 6 ++---- .../ScheduledTasks/ScheduledTaskWorker.cs | 20 +++++++++---------- .../Routines/MigrateDisplayPreferencesDb.cs | 2 +- 5 files changed, 21 insertions(+), 23 deletions(-) diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 2d5b19fa69..8c5fa09f69 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -336,19 +336,19 @@ namespace Emby.Server.Implementations.Channels return GetChannel(GetInternalChannelId(channel.Name)) ?? GetChannel(channel, CancellationToken.None).Result; } - private List GetSavedMediaSources(BaseItem item) + private MediaSourceInfo[] GetSavedMediaSources(BaseItem item) { var path = Path.Combine(item.GetInternalMetadataPath(), "channelmediasourceinfos.json"); try { - var jsonString = File.ReadAllText(path, Encoding.UTF8); - return JsonSerializer.Deserialize>(jsonString, _jsonOptions) - ?? new List(); + var bytes = File.ReadAllBytes(path); + return JsonSerializer.Deserialize(bytes, _jsonOptions) + ?? Array.Empty(); } catch { - return new List(); + return Array.Empty(); } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index c80ecd6b3c..57424f0435 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -47,11 +47,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - var jsonString = File.ReadAllText(_dataPath, Encoding.UTF8); - _items = JsonSerializer.Deserialize(jsonString, _jsonOptions); + var bytes = File.ReadAllBytes(_dataPath); + _items = JsonSerializer.Deserialize(bytes, _jsonOptions); return; } - catch (Exception ex) + catch (JsonException ex) { Logger.LogError(ex, "Error deserializing {Path}", _dataPath); } diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 1ab01252d0..e7fcc1f585 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -514,12 +514,10 @@ namespace Emby.Server.Implementations.Plugins { try { - var data = File.ReadAllText(metafile, Encoding.UTF8); + var data = File.ReadAllBytes(metafile); manifest = JsonSerializer.Deserialize(data, _jsonOptions); } -#pragma warning disable CA1031 // Do not catch general exception types - catch (Exception ex) -#pragma warning restore CA1031 // Do not catch general exception types + catch (JsonException ex) { _logger.LogError(ex, "Error deserializing {Path}.", dir); } diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 29440b64a0..1d93b63a87 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -143,21 +143,21 @@ namespace Emby.Server.Implementations.ScheduledTasks { if (File.Exists(path)) { - try + var bytes = File.ReadAllBytes(path); + if (bytes.Length > 0) { - var jsonString = File.ReadAllText(path, Encoding.UTF8); - if (!string.IsNullOrWhiteSpace(jsonString)) + try { - _lastExecutionResult = JsonSerializer.Deserialize(jsonString, _jsonOptions); + _lastExecutionResult = JsonSerializer.Deserialize(bytes, _jsonOptions); } - else + catch (JsonException ex) { - _logger.LogDebug("Scheduled Task history file {Path} is empty. Skipping deserialization.", path); + _logger.LogError(ex, "Error deserializing {File}", path); } } - catch (Exception ex) + else { - _logger.LogError(ex, "Error deserializing {File}", path); + _logger.LogDebug("Scheduled Task history file {Path} is empty. Skipping deserialization.", path); } } @@ -541,8 +541,8 @@ namespace Emby.Server.Implementations.ScheduledTasks TaskTriggerInfo[] list = null; if (File.Exists(path)) { - var jsonString = File.ReadAllText(path, Encoding.UTF8); - list = JsonSerializer.Deserialize(jsonString, _jsonOptions); + var bytes = File.ReadAllBytes(path); + list = JsonSerializer.Deserialize(bytes, _jsonOptions); } // Return defaults if file doesn't exist. diff --git a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs index f4040748d7..07829c6969 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs @@ -90,7 +90,7 @@ namespace Jellyfin.Server.Migrations.Routines var results = connection.Query("SELECT * FROM userdisplaypreferences"); foreach (var result in results) { - var dto = JsonSerializer.Deserialize(result[3].ToString(), _jsonOptions); + var dto = JsonSerializer.Deserialize(result[3].ToBlob(), _jsonOptions); if (dto == null) { continue;