今天在工作上遇到這麼個需求:需要獲取物件上所有屬性的值,但並事先並不知道物件的型別。 我的第一反應就是使用反射,但是這個操作會進行多次,大量的反射肯定會有效能影響。雖然對我這個專案無關緊要,但我還是選擇了另外一種解決方案:構建表示式樹,再生成委託,然後將委託快取在字典裡。**如下:
首先構建表示式樹(類似這種形式:'(a) => a.xx'),並生成委託:
private static funcbuilddynamicgetpropertyvaluedelegate(propertyinfo property)接著,當需要獲取屬性的值時,先在字典裡檢視是否有已經生成好的委託,有的話取出委託執行獲取屬性值。沒有則構建表示式樹生成委託,並放入字典中:
private static dictionarydelegatecache = new dictionary();就這麼簡單,完成之後,我想測試一下表示式樹版本和反射版本的效能差距如何,於是我又簡單實現反射版本作為測試對比:public static object getpropertyvalueuseexpression(tobject obj, propertyinfo property)
var getvaluedelegate = builddynamicgetpropertyvaluedelegate(property);
delegatecache[property] = getvaluedelegate;
return getvaluedelegate(obj);
}
public static object getpropertyvalueusereflection(tobject obj, propertyinfo propertyinfo)接下來是兩者的測試**:
class car在我的預想之中是這樣的:表示式樹版本在呼叫次數很少的情況下會慢於反射版本,隨著次數增多,表示式樹版本的優勢會越來越明顯。public string model
public int capacity
}.....
int repeattimes = 10000;
propertyinfo property = typeof(car).getproperty("make");
car car = new car();
stopwatch stopwatch = stopwatch.startnew();
for (int i = 0; i < repeattimes; i++)
stopwatch.stop();
console.writeline("repeated , cache in dictionary expression used time: ms", repeattimes, stopwatch.elapsedticks);
stopwatch.reset();
stopwatch.start();
for (int i = 0; i < repeattimes; i++)
stopwatch.stop();
console.writeline("repeated , reflection used time: ms", repeattimes, stopwatch.elapsedticks);
測試結果:
在呼叫次數為十萬、百萬、千萬次的情況下,表示式書版本的優勢隨著次數而提高。
ps:之前在**中犯了一些錯誤導致表示式樹版本的效率比反射還低,還把原因歸結於dictionary的效率,確實不該。但是為何這些小錯誤會導致如此的差距我還沒弄明白,搞明白之後再寫一篇部落格吧。
更新:
經過echofool、zhaxg兩位園友的提示,其實訪問屬性的委託可以不用放在字典裡,而是通過多接收乙個引數再根據switch case來獲取相應的屬性值,**如下:
public class propertydynamicgetter這個版本不使用字典,從而去除了從字典取物件的影響。它實現上先是取出物件所有的屬性,然後在構建表示式樹時根據屬性名使用switch。}public object execute(t obj, string propertyname)
private funcbuilddynamicgetdelegate(propertyinfo properties)
//set null when default
var defaultbodyexpression = expression.assign(variableexpression, expression.constant(null));
var switchexpression = expression.switch(nameparamexpression, defaultbodyexpression, switchcases.toarray());
var blockexpression = expression.block(typeof(object), new , switchexpression);
var lambdaexpression = expression.lambda>(blockexpression, objparamexpression, nameparamexpression);
return lambdaexpression.compile();}}
測試結果:
可以看到,在千萬次的情況下(十萬,百萬也是如此),這個版本效率比表示式樹快取在字典裡的效率還要高一些。
使用表示式樹和反射來訪問物件屬性的效能比較
今天在工作上遇到這麼個需求 需要獲取物件上所有屬性的值,但並事先並不知道物件的型別。我的第一反應就是使用反射,但是這個操作會進行多次,大量的反射肯定會有效能影響。雖然對我這個專案無關緊要,但我還是選擇了另外一種解決方案 構建表示式樹,再生成委託,然後將委託快取在字典裡。如下 首先構建表示式樹 類似這...
使用C 和Thrift來訪問Hbase例項
今天試著用c 和thrift來訪問hbase,主要參考了上的這篇文章。查了thrift,hbase的資料,結合的這篇文章,終於搞好了。期間經歷了不少彎路,下面我盡量詳細的記錄下來,免得大家走彎路。hbase 0.94.1 vs2012 netframework 4.0 一定要注意各產品的版本號,不同...
正規表示式和反射
1 什麼是正規表示式?就是對你想要操作的字串指定操作格式。2 為什麼要用它?簡化對字串的操作。3 如何用它?實際上就是對字串函式裡面傳指定規則的正規表示式。匹配 利用matches 正規表示式 切割 split 正規表示式 替代 replaceall 正規表示式 獲取 1,獲取pattern類例項 ...