[C#] 使用 Fasterflect 進行快速反射

2012-11-07

 

之前一篇文章 [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 來試試看..



 



2012-09-04_230344


我們來透過 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 裡面是否有某屬性中有某關鍵字 測試結果時間差異是因為我電腦用的不同 所以數據跟上篇文章不同…


當麻許的超技八 2014 | Donma Hsu Design.