[C#] 使用 Fasterflect 進行快速反射
之前一篇文章 [C#] 搜尋 T 裡面是否有某屬性中有某關鍵字
提到有關於 反射找出T 是否某一Property 帶有某值..
套一句 運轉手之戀這部電影說過的話..那時候我一值在想,如果再快一點會怎麼樣?!
之前的案例..
/// <summary>
/// 搜尋是否物件某屬性中是否帶有某關鍵字
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="lists"></param>
/// <param name="propertyName">屬性名</param>
/// <param name="propertyValue">是否包含某關鍵字</param>
/// <returns></returns>
public T[] SearchListPropertyValue<T>(List<T> lists, string propertyName, string propertyValue)
{
List<T> re = new List<T>();
return
lists.Where(
x => x.GetType().GetProperty(propertyName).GetValue(x, null).ToString().IndexOf(propertyValue, StringComparison.OrdinalIgnoreCase) >= 0).
ToArray();
}
這時候我們呼叫 一個 擁有一百萬個物件的List
public class User
{
public string Id { get; set; }
public string Name { get; set; }
public string Memo { get; set; }
public int Age { get; set; }
}
public partial class Test1 : System.Web.UI.Page
{
static List<User> sampleUsers = new List<User>();
protected void Page_Load(object sender, EventArgs e)
{
if (sampleUsers.Count == 0)
{
for (int i = 1; i <= 1000000; i++)
{
sampleUsers.Add(new User { Name = "User" + i, Memo = "Memo" + i, Age = i });
}
}
}
}
放入一百萬個 User 物件 ..這時候我使用一般反射去呼叫..結果..
for (int i = 0; i < 9; i++)
{
var search = new Search<User>();
Stopwatch sw = new Stopwatch();
sw.Start();
//搜尋Name 此屬性是否帶有ER5 這字詞
var res = search.SearchListPropertyValue(sampleUsers, "Name", "ER5");
sw.Stop();
Response.Write("搜尋到筆數為 " + res.Count() + ",耗時:" + sw.Elapsed + "<br />");
}
搜尋到筆數為 111111,耗時:00:00:00.8778668
搜尋到筆數為 111111,耗時:00:00:00.8438448
搜尋到筆數為 111111,耗時:00:00:00.7305316
搜尋到筆數為 111111,耗時:00:00:00.7095184
搜尋到筆數為 111111,耗時:00:00:00.8092698
搜尋到筆數為 111111,耗時:00:00:00.7838926
搜尋到筆數為 111111,耗時:00:00:00.7944344
搜尋到筆數為 111111,耗時:00:00:00.7090353
搜尋到筆數為 111111,耗時:00:00:00.7535085
這時候我們改由 Fasterflect 來試試看..
我們來透過 Fasterflect 來做做看
public T[] FastSearchListPropertyValue<T>(List<T> lists, string propertyName, string propertyValue)
{
return
lists.Where(
x => x.GetType().GetProperty(propertyName).FastGetValue(x).ToString().IndexOf(propertyValue, StringComparison.OrdinalIgnoreCase) >= 0).
ToArray();
}
使用程式:
for (int i = 0; i < 9; i++)
{
var search = new Search<User>();
Stopwatch sw = new Stopwatch();
sw.Start();
//搜尋Name 此屬性是否帶有ER5 這字詞
var res = search.FastSearchListPropertyValue(sampleUsers, "Name", "ER5");
sw.Stop();
Response.Write("搜尋到筆數為 " + res.Count() + ",耗時:" + sw.Elapsed + "<br />");
}
看看結果:
搜尋到筆數為 111111,耗時:00:00:00.6758539
搜尋到筆數為 111111,耗時:00:00:00.5838941
搜尋到筆數為 111111,耗時:00:00:00.5873150
搜尋到筆數為 111111,耗時:00:00:00.6452037
搜尋到筆數為 111111,耗時:00:00:00.6575470
搜尋到筆數為 111111,耗時:00:00:00.6282716
搜尋到筆數為 111111,耗時:00:00:00.5720522
搜尋到筆數為 111111,耗時:00:00:00.5156619
搜尋到筆數為 111111,耗時:00:00:00.5496252
真的變快了…
不過當然透過不用反射的速度是最快的..
for (int i = 0; i < 9; i++)
{
Stopwatch sw = new Stopwatch();
var count = 0;
sw.Start();
foreach (var user in sampleUsers)
{
if (user.Name.IndexOf("ER5", StringComparison.OrdinalIgnoreCase) >= 0)
count++;
}
sw.Stop();
Response.Write("搜尋到筆數為 " + count + ",耗時:" + sw.Elapsed + "<br />");
}
這邊我也提供數據..
搜尋到筆數為 111111,耗時:00:00:00.3095256
搜尋到筆數為 111111,耗時:00:00:00.2814147
搜尋到筆數為 111111,耗時:00:00:00.2711218
搜尋到筆數為 111111,耗時:00:00:00.2436696
搜尋到筆數為 111111,耗時:00:00:00.2532605
搜尋到筆數為 111111,耗時:00:00:00.2503655
搜尋到筆數為 111111,耗時:00:00:00.2443736
搜尋到筆數為 111111,耗時:00:00:00.2417092
搜尋到筆數為 111111,耗時:00:00:00.2358284
跟之前那篇文章 [C#] 搜尋 T 裡面是否有某屬性中有某關鍵字 測試結果時間差異是因為我電腦用的不同 所以數據跟上篇文章不同…