XML 反序列化嵌入式资源会减慢 Xamarin Forms 中的应用程序启动速度
XML deserializing for embedded resources slow down app startup in Xamarin Forms
我正在使用 Xamarin Forms 为 Android 和 iOS 设备开发移动应用程序。有两个 XML 文件(每个大约 12MB)包含两种语言之间的翻译。目前,这些文件是共享项目中的嵌入式资源,并被反序列化以便在应用程序内部使用。我做了一个(单例)资源管理器来搜索这些文件中的翻译。管理器总是在启动时 运行 一个初始化方法来反序列化 XML 文件并防止在每次应该搜索单词时加载 XML 文件。这会增加启动时间; iOS 在 iPhone 8 上需要 7 秒,在三星 galaxy S8 上 Android 需要 17 秒。
我的问题:
- 将这些文件用作共享项目中的嵌入资源是否正确?如果不是,最小化启动的最佳做法是什么?
- 读取和反序列化 XML 文件是使用这些文件的最佳方式吗?
请注意,我已经搜索过但没有从经验的角度得出任何结论。任何建议(特别是一些例子)表示赞赏。
更新:
这是 XMl 文件中的示例。但请记住,原始 XML 文件中有超过 50000 个 <word>
标签。
<?xml version="1.0" encoding="utf-8"?>
<MyDictionary>
<word class="nn" comment="även samklang av andra sinnesintryck; allmänt &quot;överensstämmelse&quot;" lang="sv" value="harmoni">
<translation comment="also used of harmony of other sensory impressions; generally, &quot;agreement&quot;" value="harmony" />
<phonetic soundFile="harmoni.swf" value="harmonI:" />
<paradigm>
<inflection value="harmonien" />
<inflection value="harmonier" />
</paradigm>
<synonym level="4.4" value="balans" />
<synonym level="3.2" value="endräkt" />
<synonym level="3.8" value="samklang" />
<synonym level="3.3" value="samspel" />
<synonym level="3.4" value="sämja" />
<synonym level="3.0" value="välbefinnande" />
<see type="saldo" value="harmoni||harmoni..1||harmoni..nn.1" />
<example value="leva i harmoni med naturen">
<translation value="be at one with Nature" />
</example>
<derivation inflection="harmoniskt" value="harmonisk">
<translation value="harmonious; harmonic" />
</derivation>
<definition value="samklang av toner">
<translation value="the simultaneous combination of musical tones" />
</definition>
</word>
</MyDictionary>
为了反序列化,首先使用 Paste Special(将 XML 粘贴为 类) Visual Studio 中的函数。然后使用以下方法执行反序列化。
private MyDictionary Load(string fileName)
{
try
{
var ass = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
var resourceName = $"LexinApp.XmlResources.{fileName}";
using (Stream stream = ass.GetManifestResourceStream(resourceName))
{
using (StreamReader reader = new StreamReader(stream))
{
var serializer = new XmlSerializer(typeof(MyDictionary));
return serializer.Deserialize(reader) as MyDictionary;
}
}
}
catch (Exception) { }
return null;
}
之后一个词被
搜索
var a = MyDictionary.word.Where(x => x.value == searchKey.ToLower()).ToList();
我最好的猜测是 xml 序列化程序不是同类中最快的,尤其是因为您的词 class 具有一定程度的复杂性。
正如我在评论中所建议的那样,放弃 xml 序列化程序可能会获得相当大的性能提升,编写一个基于 XmlReader 的自定义 xml 解析器并通过它推送数据。
将 xml 的序列化与应用程序的启动时间分离的另一个(或其他)想法是在异步后台任务中加载 xml,这样您的主 UI 就赢了不必等待它,因为你有两个文件,你也可以尝试使用并行线程加载它们(使用 System.Collections.Concurrent):
string[] xmlFileNames = new string[] { "filenameA.xml", "filenameB.xml" };
Parallel.ForEach(xmlFileNames, xmlFile =>
{
Load(xmlFile);
});
我正在使用 Xamarin Forms 为 Android 和 iOS 设备开发移动应用程序。有两个 XML 文件(每个大约 12MB)包含两种语言之间的翻译。目前,这些文件是共享项目中的嵌入式资源,并被反序列化以便在应用程序内部使用。我做了一个(单例)资源管理器来搜索这些文件中的翻译。管理器总是在启动时 运行 一个初始化方法来反序列化 XML 文件并防止在每次应该搜索单词时加载 XML 文件。这会增加启动时间; iOS 在 iPhone 8 上需要 7 秒,在三星 galaxy S8 上 Android 需要 17 秒。
我的问题:
- 将这些文件用作共享项目中的嵌入资源是否正确?如果不是,最小化启动的最佳做法是什么?
- 读取和反序列化 XML 文件是使用这些文件的最佳方式吗?
请注意,我已经搜索过但没有从经验的角度得出任何结论。任何建议(特别是一些例子)表示赞赏。
更新:
这是 XMl 文件中的示例。但请记住,原始 XML 文件中有超过 50000 个 <word>
标签。
<?xml version="1.0" encoding="utf-8"?>
<MyDictionary>
<word class="nn" comment="även samklang av andra sinnesintryck; allmänt &quot;överensstämmelse&quot;" lang="sv" value="harmoni">
<translation comment="also used of harmony of other sensory impressions; generally, &quot;agreement&quot;" value="harmony" />
<phonetic soundFile="harmoni.swf" value="harmonI:" />
<paradigm>
<inflection value="harmonien" />
<inflection value="harmonier" />
</paradigm>
<synonym level="4.4" value="balans" />
<synonym level="3.2" value="endräkt" />
<synonym level="3.8" value="samklang" />
<synonym level="3.3" value="samspel" />
<synonym level="3.4" value="sämja" />
<synonym level="3.0" value="välbefinnande" />
<see type="saldo" value="harmoni||harmoni..1||harmoni..nn.1" />
<example value="leva i harmoni med naturen">
<translation value="be at one with Nature" />
</example>
<derivation inflection="harmoniskt" value="harmonisk">
<translation value="harmonious; harmonic" />
</derivation>
<definition value="samklang av toner">
<translation value="the simultaneous combination of musical tones" />
</definition>
</word>
</MyDictionary>
为了反序列化,首先使用 Paste Special(将 XML 粘贴为 类) Visual Studio 中的函数。然后使用以下方法执行反序列化。
private MyDictionary Load(string fileName)
{
try
{
var ass = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
var resourceName = $"LexinApp.XmlResources.{fileName}";
using (Stream stream = ass.GetManifestResourceStream(resourceName))
{
using (StreamReader reader = new StreamReader(stream))
{
var serializer = new XmlSerializer(typeof(MyDictionary));
return serializer.Deserialize(reader) as MyDictionary;
}
}
}
catch (Exception) { }
return null;
}
之后一个词被
搜索var a = MyDictionary.word.Where(x => x.value == searchKey.ToLower()).ToList();
我最好的猜测是 xml 序列化程序不是同类中最快的,尤其是因为您的词 class 具有一定程度的复杂性。
正如我在评论中所建议的那样,放弃 xml 序列化程序可能会获得相当大的性能提升,编写一个基于 XmlReader 的自定义 xml 解析器并通过它推送数据。
将 xml 的序列化与应用程序的启动时间分离的另一个(或其他)想法是在异步后台任务中加载 xml,这样您的主 UI 就赢了不必等待它,因为你有两个文件,你也可以尝试使用并行线程加载它们(使用 System.Collections.Concurrent):
string[] xmlFileNames = new string[] { "filenameA.xml", "filenameB.xml" };
Parallel.ForEach(xmlFileNames, xmlFile =>
{
Load(xmlFile);
});