[英]MetadataType buddy class for EF generated POCO - attributes are ignored by XmlSerializer
[英]Performance optimizing use of generated XmlSerializer class
我們的應用程序正在讀取一些XML文件。 XML格式是固定的,因此我們可以使用XmlSerializer輕松讀取它們。
我使用以下代碼讀取XML文件並將其轉換為類:
public static T FromXml<T>(this string xml) where T : class
{
if (string.IsNullOrEmpty(xml))
{
return default(T);
}
XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
XmlTextReader textReader = new XmlTextReader(new StringReader(xml));
textReader.Normalization = false;
XmlReaderSettings settings = new XmlReaderSettings();
T value;
using (XmlReader reader = XmlReader.Create(textReader, settings))
{
value = (T)xmlserializer.Deserialize(reader);
}
return value;
}
但是,存在一些性能問題。 第一次使用此代碼的特定類型的T
, XmlSerializer
生成一個Project.XmlSerializer.dll
文件。
很好,但是要花費一些寶貴的毫秒(在我的情況下約為900毫秒)。 可以通過使用XML Serializer Generator(sgen)預先生成該程序集來避免這種情況。 這將時間減少到大約一半。 主要是由於組件的讀取和反射。
我想通過將XmlSerializer
類引入實際類所在的程序集中來進一步優化此方法 ,但是我找不到讓XmlSerializer
知道不讀取外部程序集,而是使用當前程序集中的序列化器的方法。
有什么想法如何做到這一點或另一種方式使這項工作嗎? (我無法預加載它們,因為大多數序列化的類在啟動時使用)
使用ANTS Profiler進行的分析(來自其他計算機的指標,但模式相同):
平原。 在生成和加載XmlSerializer程序集的大部分時間(300ms + 400ms = 700ms)中丟失了。
用sgen生成的程序集。 大部分時間(336ms)浪費在加載XmlSerializer程序集上。
當將程序集的實際源包含在項目中並直接調用序列化程序時,操作將降至456ms(第一時間為1s,第二時間為556ms)。
注意:OP發布了一個示例配置: http : //pastebin.com/d67nch3R
根據樣本配置和您遇到的問題的類型,有兩種蠻力方法,幾乎可以保證達到目的,兩種方法最終都完全放棄了XML序列化器。
1號路線
放棄XML序列化,並使用XDocument從XML中獲取數據。
2號線
使用json和Newtonsoft Json來存儲和加載配置。 它的性能應該比XML Serializer好很多
樣本json對應內容如下所示:
{
"Connections": {
"-default": "Local\\SqlServer",
"-forcedefault": "false",
"group": {
"-name": "Local",
"connection": {
"-name": "SqlServer",
"database": {
"-provider": "SqlServer",
"-connectionString": "blah"
}
}
}
},
"LastLanguage": "en",
"UserName": "un",
"SavePassword": "true",
"AutoConnect": "false",
"Password": "someObfuscatedHashedPassword==",
"ConnectionName": "Somewhere\\Database",
"LastAvailableBandwidth": "0",
"LastAvailableLatency": "0",
"DateLastConnectionSuccesful": "2014-08-13T15:21:35.9663654+02:00"
}
並加載它:
UserSettings settings = JsonConvert.DeserializeObject<UserSettings>(File.ReadAllText("settings.json"))
除非您在應用程序啟動時就進行序列化,否則一種方法將是強制CLR提前加載甚至編譯您正在使用的任何類,可能會在啟動后立即在后台運行的線程中您的應用。
例如:
foreach (Assembly a in assembliesThatShouldBeCompileed)
foreach (Type type in a.GetTypes())
if (!type.IsAbstract && type.IsClass)
{
foreach (MethodInfo method in type.GetMethods(
BindingFlags.DeclaredOnly |
BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.Static))
{
if (method.ContainsGenericParameters ||
method.IsGenericMethod ||
method.IsGenericMethodDefinition)
continue;
if ((method.Attributes & MethodAttributes.PinvokeImpl) > 0)
continue;
System.Runtime.CompilerServices
.RuntimeHelpers.PrepareMethod(method.MethodHandle);
}
}
然而,很奇怪的是,您的性能分析似乎表明,如果SGEN的代碼在單獨的程序集中,則沒有太大的區別,而加載似乎是瓶頸。 我想知道圖表在同一裝配中的情況如何?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.