From 82a1ba1d46650bf11164e26537ddfa64ae995c84 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 30 May 2022 17:42:27 +0900 Subject: [PATCH 1/2] Use pooled memory for memory copies performed by `ZipArchiveReader` --- osu.Game/IO/Archives/ZipArchiveReader.cs | 56 +++++++++++++++++++++--- osu.Game/osu.Game.csproj | 1 + 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/osu.Game/IO/Archives/ZipArchiveReader.cs b/osu.Game/IO/Archives/ZipArchiveReader.cs index 80dfa104f3..ae2b85da51 100644 --- a/osu.Game/IO/Archives/ZipArchiveReader.cs +++ b/osu.Game/IO/Archives/ZipArchiveReader.cs @@ -1,11 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Buffers; using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Toolkit.HighPerformance; +using osu.Framework.Extensions; using osu.Framework.IO.Stores; using SharpCompress.Archives.Zip; +using SixLabors.ImageSharp.Memory; namespace osu.Game.IO.Archives { @@ -27,15 +31,12 @@ namespace osu.Game.IO.Archives if (entry == null) throw new FileNotFoundException(); - // allow seeking - MemoryStream copy = new MemoryStream(); + var owner = MemoryAllocator.Default.Allocate((int)entry.Size); using (Stream s = entry.OpenEntryStream()) - s.CopyTo(copy); + s.ReadToFill(owner.Memory.Span); - copy.Position = 0; - - return copy; + return new MemoryOwnerMemoryStream(owner); } public override void Dispose() @@ -45,5 +46,48 @@ namespace osu.Game.IO.Archives } public override IEnumerable Filenames => archive.Entries.Select(e => e.Key).ExcludeSystemFileNames(); + + private class MemoryOwnerMemoryStream : Stream + { + private readonly IMemoryOwner owner; + private readonly Stream stream; + + public MemoryOwnerMemoryStream(IMemoryOwner owner) + { + this.owner = owner; + + stream = owner.Memory.AsStream(); + } + + protected override void Dispose(bool disposing) + { + owner?.Dispose(); + base.Dispose(disposing); + } + + public override void Flush() => stream.Flush(); + + public override int Read(byte[] buffer, int offset, int count) => stream.Read(buffer, offset, count); + + public override long Seek(long offset, SeekOrigin origin) => stream.Seek(offset, origin); + + public override void SetLength(long value) => stream.SetLength(value); + + public override void Write(byte[] buffer, int offset, int count) => stream.Write(buffer, offset, count); + + public override bool CanRead => stream.CanRead; + + public override bool CanSeek => stream.CanSeek; + + public override bool CanWrite => stream.CanWrite; + + public override long Length => stream.Length; + + public override long Position + { + get => stream.Position; + set => stream.Position = value; + } + } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 79cfd7c917..6ce21ccad6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -29,6 +29,7 @@ + all From d6b18d87b8f7c14bb078dca1863a4283ee16cb7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 30 May 2022 19:58:47 +0900 Subject: [PATCH 2/2] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index c28085557e..116c7dbfcd 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6ce21ccad6..eb47d0468f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index b1ba64beba..ccecad6f82 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -61,7 +61,7 @@ - + @@ -84,7 +84,7 @@ - +