【发布时间】: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