![](/img/trans.png)
[英]Do large namespaces affect performance / are many small namespaces more efficient than large namespaces in C#?
[英]Performance Problems - Large DLLs and Large Namespaces
這是我在這里問到的LINQ to DB2問題的下一步。
在zb_z的回答之后,我對DB_Linq的代碼進行了一些討論 ,並設法添加了有效的DB2支持。 (它現在還處於起步階段,尚未准備好回饋到項目中。)概念驗證工作得很好,實際上非常令人興奮。 但是,我一路上遇到了另一次打嗝。
事實證明,我們的DB2數據庫很大 。 8,306桌大。 因此,生成的代碼竟然超過了520萬行代碼。 在一個文件中。 毋庸置疑,Visual Studio並沒有太在意它:)
所以我進一步修改了生成器,將每個表類都吐出到自己的文件中。 這給我留下了8,307個文件(數據上下文和每個表一個,它們使用表屬性擴展數據上下文)。 Visual Studio仍然不喜歡它,這是可以理解的,因此我將代碼生成和編譯包裝在一個腳本中,然后運行它來輸出一個DLL供我的項目使用。
一個36 MB的DLL。
現在,在性能上進行一些搜索使我得到了這個問題 (它本身就引用了這個 問題 ),我已經按照答案和鏈接看了他們在說什么。 因此,這讓我想知道它是否可能在同一名稱空間中存在超過8,000個類,這是明顯的性能問題的罪魁禍首。
我的性能測試是編寫一個初始化數據上下文的小控制台應用程序,使用LINQ獲取數據,打印行數,使用經典ADO獲取數據,並打印出另一行計數。 每個聲明都包含一個時間戳。 添加更多查詢以進行測試等始終會產生相同的性能。 LINQ代碼需要幾秒鍾才能運行,而ADO會在眨眼間填充數據集。
所以我想這最終會成為一個有點開放(並且啰嗦,抱歉)的問題。 有沒有人對加快績效有任何想法? 我可以應用哪些簡單的調整或設計考慮因素?
編輯
有幾點需要注意:
var foo = from t in bank1.TMX9800F where t.T9ADDEP > 0 select t.T9ADDEP
上的var foo = from t in bank1.TMX9800F where t.T9ADDEP > 0 select t.T9ADDEP
的行長度為var foo = from t in bank1.TMX9800F where t.T9ADDEP > 0 select t.T9ADDEP
,當我在調試器中展開屬性以枚舉結果時(或讓它轉到下一行,它執行.Count())然后該部分根本沒有時間。 編輯
我無法發布整個生成的DLL,但這里是測試應用程序的代碼:
static void Main(string[] args)
{
Console.WriteLine(string.Format("{0}: Process Started", DateTime.Now.ToLongTimeString()));
// Initialize your data contexts
var bank1 = new BNKPRD01(new iDB2Connection(ConfigurationManager.ConnectionStrings["DB2"].ConnectionString));
var bank6 = new BNKPRD06(new iDB2Connection(ConfigurationManager.ConnectionStrings["DB2"].ConnectionString));
Console.WriteLine(string.Format("{0}: Data contexts initialized", DateTime.Now.ToLongTimeString()));
var foo = from t in bank1.TMX9800F where t.T9ADDEP > 0 select t; // <- runs slow
Console.WriteLine(string.Format("{0}: {1} records found in BNKPRD01 test table", DateTime.Now.ToLongTimeString(), foo.Count().ToString()));
var baz = from t in bank6.TMX9800F where t.T9ADDEP > 0 select t; // <- runs slow
Console.WriteLine(string.Format("{0}: {1} records found in BNKPRD06 test table", DateTime.Now.ToLongTimeString(), baz.Count().ToString()));
var ds = new DataSet();
using (var conn = new iDB2Connection(ConfigurationManager.ConnectionStrings["DB2"].ConnectionString))
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM BNKPRD01.TMX9800F WHERE T9ADDEP > 0";
new IBM.Data.DB2.iSeries.iDB2DataAdapter(cmd).Fill(ds);
}
}
Console.WriteLine(string.Format("{0}: {1} records found in BNKPRD01 test table", DateTime.Now.ToLongTimeString(), ds.Tables[0].Rows.Count.ToString()));
ds = new DataSet();
using (var conn = new iDB2Connection(ConfigurationManager.ConnectionStrings["DB2"].ConnectionString))
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM BNKPRD06.TMX9800F WHERE T9ADDEP > 0";
new IBM.Data.DB2.iSeries.iDB2DataAdapter(cmd).Fill(ds);
}
}
Console.WriteLine(string.Format("{0}: {1} records found in BNKPRD06 test table", DateTime.Now.ToLongTimeString(), ds.Tables[0].Rows.Count.ToString()));
Console.WriteLine("Press return to exit.");
Console.ReadLine();
}
也許我錯過了一些明顯的東西,或者有一些關於LINQ的東西我沒有理解?
編輯
在下面與Jon和Brian討論后,我進一步研究了在創建LINQ查詢時調用的DB_Linq代碼,並且遇到了很長的步驟:
public override IEnumerable<MetaTable> GetTables()
{
const BindingFlags scope = BindingFlags.GetField |
BindingFlags.GetProperty | BindingFlags.Static |
BindingFlags.Instance | BindingFlags.NonPublic |
BindingFlags.Public;
var seen = new HashSet<Type>();
foreach (var info in _ContextType.GetMembers(scope))
{
// Only look for Fields & Properties.
if (info.MemberType != MemberTypes.Field && info.MemberType != MemberTypes.Property)
continue;
Type memberType = info.GetMemberType();
if (memberType == null || !memberType.IsGenericType ||
memberType.GetGenericTypeDefinition() != typeof(Table<>))
continue;
var tableType = memberType.GetGenericArguments()[0];
if (tableType.IsGenericParameter)
continue;
if (seen.Contains(tableType))
continue;
seen.Add(tableType);
MetaTable metaTable;
if (_Tables.TryGetValue(tableType, out metaTable))
yield return metaTable;
else
yield return AddTableType(tableType);
}
}
該循環迭代16,718次。
發布控制台應用程序真的會有所幫助。
在命名空間和程序集中有很多類會減慢編譯速度,每種類型的每個方法都會有一次性的JITting命中...但我不希望它會減慢LINQ查詢的速度。
您應該檢查從LINQ查詢實際生成的SQL。 我希望問題出在那里。
我剛剛在命名空間中創建了一個帶有10.000個類的小型測試項目,雖然在加載/ jitting組件時有明顯的開銷,但我不會說它特別慢。 因此,可能不是類本身的數量,這是你所看到的糟糕表現的原因。
我是喬恩在這里,它會對您的測試應用程序的更多信息有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.