From 600eaa2a9a47042e5eb55d1b141a91de2d16946c Mon Sep 17 00:00:00 2001 From: Ryan Lucia Date: Mon, 17 Aug 2020 18:53:53 -0400 Subject: [PATCH] [mono] Loader improvements: bundle optimization and logging (#40819) * Delay bundle loading until after checking the ALC cache This avoids having to create and destroy MonoImage objects over and over when looking for already-loaded assemblies, which should cut down on overall load time a bit. * Improve loader algorithm logging --- src/mono/mono/metadata/appdomain.c | 2 +- src/mono/mono/metadata/assembly.c | 88 ++++++++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/src/mono/mono/metadata/appdomain.c b/src/mono/mono/metadata/appdomain.c index 8282643..88686b6 100644 --- a/src/mono/mono/metadata/appdomain.c +++ b/src/mono/mono/metadata/appdomain.c @@ -2480,7 +2480,7 @@ mono_domain_assembly_preload (MonoAssemblyLoadContext *alc, char *base_dir = get_app_context_base_directory (error); search_path [0] = base_dir; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain %s (%p) ApplicationBase is %s", domain->friendly_name, domain, base_dir); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain (%p) ApplicationBase is %s", domain, base_dir); result = real_load (search_path, aname->culture, aname->name, &req); diff --git a/src/mono/mono/metadata/assembly.c b/src/mono/mono/metadata/assembly.c index 34cd398..1cf6d95 100644 --- a/src/mono/mono/metadata/assembly.c +++ b/src/mono/mono/metadata/assembly.c @@ -1642,6 +1642,27 @@ load_reference_by_aname_individual_asmctx (MonoAssemblyName *aname, MonoAssembly return reference; } #else +static MonoAssembly * +search_bundle_for_assembly (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname) +{ + if (bundles == NULL) + return NULL; + + MonoImageOpenStatus status; + MonoImage *image; + MonoAssemblyLoadRequest req; + image = mono_assembly_open_from_bundle (alc, aname->name, &status, FALSE); + if (!image) { + char *name = g_strdup_printf ("%s.dll", aname->name); + image = mono_assembly_open_from_bundle (alc, name, &status, FALSE); + } + if (image) { + mono_assembly_request_prepare_load (&req, MONO_ASMCTX_DEFAULT, alc); + return mono_assembly_request_load_from (image, aname->name, &req, &status); + } + return NULL; +} + static MonoAssembly* netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, MonoAssembly *requesting, gboolean postload) { @@ -1663,61 +1684,85 @@ netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, M * Try these until one of them succeeds (by returning a non-NULL reference): * 1. Check if it's already loaded by the ALC. * - * 2. If it's a non-default ALC, call the Load() method. + * 2. If we have a bundle registered, search the images for a matching name. * - * 3. If the ALC is not the default and this is not a satellite request, + * 3. If it's a non-default ALC, call the Load() method. + * + * 4. If the ALC is not the default and this is not a satellite request, * check if it's already loaded by the default ALC. * - * 4. If the ALC is the default or this is not a satellite request, + * 5. If the ALC is the default or this is not a satellite request, * check the TPA list, APP_PATHS, and ApplicationBase. * - * 5. If this is a satellite request, call the ALC ResolveSatelliteAssembly method. + * 6. If this is a satellite request, call the ALC ResolveSatelliteAssembly method. * - * 6. Call the ALC Resolving event. + * 7. Call the ALC Resolving event. * - * 7. Call the ALC AssemblyResolve event (except for corlib satellite assemblies). + * 8. Call the ALC AssemblyResolve event (except for corlib satellite assemblies). * - * 8. Return NULL. + * 9. Return NULL. */ reference = mono_assembly_loaded_internal (alc, aname, FALSE); - if (reference) + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly already loaded in the active ALC: '%s'.", aname->name); goto leave; + } + + if (bundles != NULL) { + reference = search_bundle_for_assembly (alc, aname); + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found in the bundle: '%s'.", aname->name); + goto leave; + } + } if (!is_default) { reference = mono_alc_invoke_resolve_using_load_nofail (alc, aname); - if (reference) + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found using Load method: '%s'.", aname->name); goto leave; + } } if (!is_default && !is_satellite) { reference = mono_assembly_loaded_internal (mono_domain_default_alc (mono_alc_domain (alc)), aname, FALSE); - if (reference) + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly already loaded in the default ALC: '%s'.", aname->name); goto leave; + } } if (is_default || !is_satellite) { reference = invoke_assembly_preload_hook (mono_domain_default_alc (mono_alc_domain (alc)), aname, assemblies_path); - if (reference) + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found with the filesystem probing logic: '%s'.", aname->name); goto leave; + } } if (is_satellite) { reference = mono_alc_invoke_resolve_using_resolve_satellite_nofail (alc, aname); - if (reference) + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found with ResolveSatelliteAssembly method: '%s'.", aname->name); goto leave; + } } reference = mono_alc_invoke_resolve_using_resolving_event_nofail (alc, aname); - if (reference) + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found with the Resolving event: '%s'.", aname->name); goto leave; + } // Looking up corlib resources here can cause an infinite loop // See: https://github.com/dotnet/coreclr/blob/0a762eb2f3a299489c459da1ddeb69e042008f07/src/vm/appdomain.cpp#L5178-L5239 if (!(strcmp (aname->name, MONO_ASSEMBLY_CORLIB_RESOURCE_NAME) == 0 && is_satellite) && postload) { reference = mono_assembly_invoke_search_hook_internal (alc, requesting, aname, FALSE, TRUE); - if (reference) + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found with AssemblyResolve event: '%s'.", aname->name); goto leave; + } } leave: @@ -4854,20 +4899,7 @@ mono_assembly_request_byname (MonoAssemblyName *aname, const MonoAssemblyByNameR result = prevent_reference_assembly_from_running (result, refonly); } #else - result = NULL; - if (bundles != NULL) { - MonoImageOpenStatus status; - MonoImage *image; - image = mono_assembly_open_from_bundle (req->request.alc, aname->name, &status, FALSE); - if (!image) { - char *name = g_strdup_printf ("%s.dll", aname->name); - image = mono_assembly_open_from_bundle (req->request.alc, name, &status, FALSE); - } - if (image) - result = mono_assembly_request_load_from (image, aname->name, &req->request, &status); - } - if (!result) - result = netcore_load_reference (aname, req->request.alc, req->requesting_assembly, !req->no_postload_search); + result = netcore_load_reference (aname, req->request.alc, req->requesting_assembly, !req->no_postload_search); #endif return result; } -- 2.7.4