From 1d031dcee0072ca4dcf16ffb471aea905b8ac516 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 19 Dec 2018 11:45:26 -0600 Subject: [PATCH] [Xamarin.Android.Build.Tasks] ResolveLibraryProjectImports temp files (#2540) When reviewing the `` task, I noticed a few things we could improve: 1. We are using `GetResourceData()` to get the entire contents of a file as a `byte[]` and then writing to disk. 2. We are writing temporary zip files to disk, reading them to extract, then deleting them. The first thing I did was take advantage of the `GetResourceStream()` method, so we could just do `stream.CopyTo(file)`. This prevents us from allocating big `byte[]` the size of each file. Next, I took advantage of `ZipArchive.Open(stream)` and `GetResourceStream()` to avoid the need for creating temporary zip files. We can unzip directly from the `Stream` in memory. ~~ Results ~~ When timing these changes, I used the Xamarin.Forms integration project in this repo: Before 1. 1793 ms ResolveLibraryProjectImports 1 calls 2. 1780 ms ResolveLibraryProjectImports 1 calls 3. 1770 ms ResolveLibraryProjectImports 1 calls After 1. 1750 ms ResolveLibraryProjectImports 1 calls 2. 1740 ms ResolveLibraryProjectImports 1 calls 3. 1702 ms ResolveLibraryProjectImports 1 calls I would say the improvements here are around 50ms. --- .../Tasks/ResolveLibraryProjectImports.cs | 33 +++++-------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs index 45252bd5c25..9f5cd4019bd 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs @@ -266,9 +266,9 @@ void Extract ( Directory.CreateDirectory (outDirForDll); var finfo = new FileInfo (Path.Combine (outDirForDll, envtxt.Name)); if (!finfo.Exists || finfo.LastWriteTimeUtc > assemblyLastWrite) { + using (var stream = envtxt.GetResourceStream ()) using (var fs = finfo.Create ()) { - var data = envtxt.GetResourceData (); - fs.Write (data, 0, data.Length); + stream.CopyTo (fs); } updated = true; } @@ -283,24 +283,18 @@ void Extract ( var outjarFile = Path.Combine (importsDir, resjar.Name); var fi = new FileInfo (outjarFile); if (!fi.Exists || fi.LastWriteTimeUtc > assemblyLastWrite) { - var data = resjar.GetResourceData (); + using (var stream = resjar.GetResourceStream ()) using (var outfs = File.Create (outjarFile)) - outfs.Write (data, 0, data.Length); + stream.CopyTo (outfs); updated = true; } } var libzip = mod.Resources.FirstOrDefault (r => r.Name == "__AndroidNativeLibraries__.zip") as EmbeddedResource; if (libzip != null) { - if (!Directory.Exists (outDirForDll)) - Directory.CreateDirectory (outDirForDll); - var finfo = new FileInfo (Path.Combine (outDirForDll, libzip.Name)); - using (var fs = finfo.Create ()) { - var data = libzip.GetResourceData (); - fs.Write (data, 0, data.Length); - } List files = new List (); - using (var zip = MonoAndroidHelper.ReadZipFile (finfo.FullName)) { + using (var stream = libzip.GetResourceStream ()) + using (var zip = Xamarin.Tools.Zip.ZipArchive.Open (stream)) { try { updated |= Files.ExtractAll (zip, nativeimportsDir, modifyCallback: (entryFullName) => { files.Add (Path.GetFullPath (Path.Combine (nativeimportsDir, entryFullName))); @@ -318,24 +312,15 @@ void Extract ( return; } } - - finfo.Delete (); } // embedded AndroidResourceLibrary archive var reszip = mod.Resources.FirstOrDefault (r => r.Name == "__AndroidLibraryProjects__.zip") as EmbeddedResource; if (reszip != null) { - if (!Directory.Exists (outDirForDll)) - Directory.CreateDirectory (outDirForDll); - var finfo = new FileInfo (Path.Combine (outDirForDll, reszip.Name)); - using (var fs = finfo.Create ()) { - var data = reszip.GetResourceData (); - fs.Write (data, 0, data.Length); - } - // temporarily extracted directory will look like: // __library_projects__/[dllname]/[library_project_imports | jlibs]/bin - using (var zip = MonoAndroidHelper.ReadZipFile (finfo.FullName)) { + using (var stream = reszip.GetResourceStream ()) + using (var zip = Xamarin.Tools.Zip.ZipArchive.Open (stream)) { try { updated |= Files.ExtractAll (zip, importsDir, modifyCallback: (entryFullName) => { return entryFullName @@ -374,8 +359,6 @@ void Extract ( } if (Directory.Exists (assemblyDir)) resolvedAssetDirectories.Add (assemblyDir); - - finfo.Delete (); } }