【问题标题】:Accessing Resources for the First Time in Xamarin.Android is Slow在 Xamarin.Android 中首次访问资源很慢
【发布时间】:2019-09-19 16:18:00
【问题描述】:

我正在创建一个应用程序,该应用程序将使用 Xamarin(当前为 Xamarin.Forms,但也可能是 Xamarin.Android)以 Android 操作系统为目标。此应用程序将通过 Web API 调用访问核心业务功能。

我注意到,每次我运行应用程序时,我第一次执行 API 调用时都会比进行后续调用时慢得多。对于我所针对的硬件,第一次调用通常需要大约 3000 毫秒,而随后的调用在 200 毫秒到 300 毫秒之间。每次我重新启动应用程序时,此行为都是一致的。

为了找出问题的根源,我使用 Fiddler 测试了 API 端点,响应时间总是非常快。我还创建了一个 UWP 项目,以查看它是否特定于 Android 或任何 Xamarin 目标。这个问题似乎是 Android 特有的。

当进行第一次 API 调用时,调试窗口中会生成类似于以下内容的输出:

07-28 00:03:50.354 D/Mono    (15670): DllImport searching in: '__Internal' ('(null)').
07-28 00:03:50.354 D/Mono    (15670): Searching for 'java_interop_jnienv_call_float_method_a'.
07-28 00:03:50.354 D/Mono    (15670): Probing 'java_interop_jnienv_call_float_method_a'.
07-28 00:03:50.354 D/Mono    (15670): Found as 'java_interop_jnienv_call_float_method_a'.
07-28 00:03:50.564 D/Mono    (15670): Loading reference 8 of netstandard.dll asmctx DEFAULT, looking for System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
07-28 00:03:50.564 D/Mono    (15670): Image addref System.Net.Http[0x65db9f70] (asmctx DEFAULT) -> System.Net.Http.dll[0x65dc4118]: 2
07-28 00:03:50.564 D/Mono    (15670): Prepared to set up assembly 'System.Net.Http' (System.Net.Http.dll)
07-28 00:03:50.564 D/Mono    (15670): Assembly System.Net.Http[0x65db9f70] added to domain RootDomain, ref_count=1
07-28 00:03:50.564 D/Mono    (15670): AOT: image 'System.Net.Http.dll.so' not found: (null)
07-28 00:03:50.574 D/Mono    (15670): AOT: image '/Users/builder/jenkins/workspace/archive-mono/2019-02/android/release/sdks/out/android-armeabi-v7a-release/lib/mono/aot-cache/arm/System.Net.Http.dll.so' not found: (null)
07-28 00:03:50.574 D/Mono    (15670): Config attempting to parse: 'System.Net.Http.dll.config'.
07-28 00:03:50.574 D/Mono    (15670): Config attempting to parse: '/Users/builder/jenkins/workspace/archive-mono/2019-02/android/release/sdks/out/android-armeabi-v7a-release/etc/mono/assemblies/System.Net.Http/System.Net.Http.config'.
07-28 00:03:50.574 D/Mono    (15670): Assembly Ref addref netstandard[0x64a97cd0] -> System.Net.Http[0x65db9f70]: 2
07-28 00:03:50.574 D/Mono    (15670): Loading reference 0 of System.Net.Http.dll asmctx DEFAULT, looking for mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
07-28 00:03:50.574 D/Mono    (15670): Assembly Ref addref System.Net.Http[0x65db9f70] -> mscorlib[0x62b37138]: 33
Loaded assembly: System.Net.Http.dll [External]
07-28 00:03:50.584 D/Mono    (15670): Loading reference 1 of System.Net.Http.dll asmctx DEFAULT, looking for System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
07-28 00:03:50.584 D/Mono    (15670): Assembly Ref addref System.Net.Http[0x65db9f70] -> System[0x645da088]: 6
Thread started:  #2
07-28 00:03:50.844 D/Mono    (15670): Loading reference 2 of System.Net.Http.dll asmctx DEFAULT, looking for System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
07-28 00:03:50.844 D/Mono    (15670): Assembly Ref addref System.Net.Http[0x65db9f70] -> System.Core[0x6488b0c0]: 6
Thread started: <Thread Pool> #3
Thread started: <Thread Pool> #4
Thread started: <Thread Pool> #5
Thread started: <Thread Pool> #6
Thread started: <Thread Pool> #7
Thread started: <Thread Pool> #8
07-28 00:03:51.265 D/Mono    (15670): DllImport attempting to load: 'libmono-native.so'.
07-28 00:03:51.275 D/Mono    (15670): DllImport loaded library './libmono-native.so'.
07-28 00:03:51.275 D/Mono    (15670): DllImport searching in: 'libmono-native.so' ('./libmono-native.so').
07-28 00:03:51.275 D/Mono    (15670): Searching for 'SystemNative_GetNonCryptographicallySecureRandomBytes'.
07-28 00:03:51.275 D/Mono    (15670): Probing 'SystemNative_GetNonCryptographicallySecureRandomBytes'.
07-28 00:03:51.275 D/Mono    (15670): Found as 'SystemNative_GetNonCryptographicallySecureRandomBytes'.
Thread started: <Thread Pool> #9

在随后的 API 调用中,调试窗口中不会生成任何内容(这或多或少解释了为什么响应时间更快)。

有人能解释一下这里发生了什么吗?有没有办法解决这个问题(例如,从应用程序启动时加载资源)?有没有更好的方法?

我认为调用 API 的代码不是问题(因为 UWP 版本没有表现出所描述的行为),但为了以防万一,我在下面包含了此代码。

    var uri = new Uri("...");

    try
    {
        var stopwatch = new Stopwatch();

        stopwatch.Start();

        using (var client = new HttpClient())
        {
            using (var response = await client.GetAsync(uri))
            {
            }
        }

        stopwatch.Stop();

        ResponseTimeLabel.Text = $"{stopwatch.ElapsedMilliseconds.ToString()}ms";
    }
    catch (Exception exception)
    {
        ResponseTimeLabel.Text = $"Exception: {exception.Message}";
    }

【问题讨论】:

    标签: xamarin xamarin.forms xamarin.android


    【解决方案1】:

    我搜索了一些信息,我想有很多原因。

    应用程序池正在预热,正在构建路由,DI 容器可能正在注册对象图,正在发生缓存,正在生成和缓存执行计划等等。

    还有其他问题,例如 JIT 开销和 DNS 查找。

    您应该始终假设应用程序需要预热时间。在首次运行时预热应用程序被认为是最佳实践,以确保您的应用程序的使用者能够快速响应。您无法避免这种预热成本,也不应该尝试这样做。相反,构建您的部署,以便您能够在用户点击应用程序之前预热应用程序,例如适当的负载平衡和服务器轮换。

    【讨论】:

    • 这不是 Web API 应用程序本身的问题,而是 Xamarin.Android 应用程序的问题。
    • @Jason,如果你认为是 Xamarin.android 的问题,我建议你可以在 github 上创建一个 issue 线程进行讨论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    相关资源
    最近更新 更多