性能调优(一) 缓存方法返回值
对于多次调用且耗时比较长的方法,在第一次调用时,把“返回值”保存起来,在以后再次调用时,直接返回“返回值”。
案例:在客户代码中,多次调用方法ExecuteStoredProcedure,且传入的参数相同。
class Program
{
static void Main(string[] args)
{
int total = 0;
DBAccess db = new DBAccess();
for (int i = 0; i < 100; i++)
{
total += db.ExecuteStoredProcedure("sp1", new object[] { i });
total += db.ExecuteStoredProcedure("sp1", new object[] { i + 1 });
total += db.ExecuteStoredProcedure("sp1", new object[] { i + 2 });
}
Console.WriteLine(total);
}
}
class DBAccess
{
public int ExecuteStoredProcedure(string spName, object[] parameters)
{
//在此要访问数据库,运行时间较长
//...
System.Threading.Thread.Sleep(100);
return 2010;
}
}
此案例的性能调优方法:
class Program
{
static void Main(string[] args)
{
int total = 0;
DBAccess db = new DBAccessEx();
for (int i = 0; i < 100; i++)
{
total += db.ExecuteStoredProcedure("sp1", new object[] { i });
total += db.ExecuteStoredProcedure("sp1", new object[] { i + 1 });
total += db.ExecuteStoredProcedure("sp1", new object[] { i + 2 });
}
Console.WriteLine(total);
Console.Read();
}
}
class DBAccess
{
public virtual int ExecuteStoredProcedure(string spName, object[] parameters)
{
//在此要访问数据库,运行时间较长
//...
System.Threading.Thread.Sleep(100);
return 2010;
}
}
class DBAccessEx : DBAccess
{
MethodInvoker invoker = null;
DBAccess delegateObj = null;
public DBAccessEx()
{
delegateObj = new DBAccess();
invoker = new MethodInvoker(delegateObj);
}
public override int ExecuteStoredProcedure(string spName, object[] parameters)
{
return (int)this.invoker.Invoke(
"ExecuteStoredProcedure",
new object[] { spName, parameters });
}
}
辅助类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class MethodInvoker
{
private readonly Dictionary<Key, object> ResultDictionary = new Dictionary<Key, object>();
private object _instance;
private Type _type;
public MethodInvoker(object instance)
{
this._instance = instance;
this._type = this._instance.GetType();
}
public object Invoke(string methodName, object[] parameters, Type[] parameterTypes)
{
if (string.IsNullOrEmpty(methodName)) throw new ArgumentNullException("methodName");
if (parameters == null) throw new ArgumentNullException("parameters");
object result;
if (Find(methodName, parameters, out result))
return result;
MethodInfo methodInfo = _type.GetMethod(methodName, parameterTypes);
if (methodInfo == null) throw new MethodNotFundException();
result = methodInfo.Invoke(_instance, parameters);
Cache(methodName, parameters, result);
return result;
}
public object Invoke(string methodName, object[] parameters)
{
if (string.IsNullOrEmpty(methodName)) throw new ArgumentNullException("methodName");
if (parameters == null) throw new ArgumentNullException("parameters");
object result;
if (Find(methodName, parameters, out result))
return result;
MethodInfo methodInfo = _type.GetMethod(methodName);
if (methodInfo == null) throw new MethodNotFundException();
result = methodInfo.Invoke(_instance, parameters);
Cache(methodName, parameters, result);
return result;
}
public void RemoveCache()
{
ResultDictionary.Clear();
}
private bool Find(string methodName, object[] parameters, out object result)
{
var key = new Key(methodName, parameters);
if (ResultDictionary.ContainsKey(key))
{
result = ResultDictionary[key];
return true;
}
else
{
result = null;
return false;
}
}
private void Cache(string methodName, object[] parameters, object result)
{
var key = new Key(methodName, parameters);
ResultDictionary.Add(key, result);
}
[Serializable]
class Key
{
private string _methodName;
private object[] _parameters;
public Key(string methodName, object[] parameters)
{
this._methodName = methodName;
this._parameters = parameters;
}
public string MethodName
{
get { return _methodName; }
}
public override bool Equals(object obj)
{
if (obj is Key)
{
Key c = obj as Key;
if (!MethodName.Equals(c.MethodName))
return false;
if (!_parameters.Length.Equals(c._parameters.Length))
return false;
MemoryStream stream1 = GetMemoryStream(this._parameters);
MemoryStream stream2 = GetMemoryStream(c._parameters);
bool isMemoryEqual = MemoryStreamEquals(stream1, stream2);
stream1.Close();
stream2.Close();
if (!isMemoryEqual) return false;
return true;
}
else
{
return false;
}
}
public override int GetHashCode()
{
int hashCode = 0;
hashCode += this.MethodName.GetHashCode();
//hashCode += this.Instance.GetHashCode();
//hashCode += this._parameters.Length;
//foreach (var parameter in _parameters)
//{
// if (parameter != null)
// hashCode += parameter.GetHashCode();
//}
return hashCode;
}
private static MemoryStream GetMemoryStream(object p)
{
MemoryStream memStream = new MemoryStream();
BinaryFormatter binFormatter = new BinaryFormatter();
binFormatter.Serialize(memStream, p);
return memStream;
}
private static bool MemoryStreamEquals(MemoryStream stream1, MemoryStream stream2)
{
if (stream1.Length != stream2.Length)
return false;
for (int i = 0; i < stream1.Length; i++)
{
stream1.Seek(i, SeekOrigin.Begin);
stream2.Seek(i, SeekOrigin.Begin);
int x = stream1.ReadByte();
int y = stream2.ReadByte();
if (x != y) return false;
}
return true;
}
}
}
public class MethodNotFundException : Exception
{
}
此性能调优方法有不妥之处,敬请指正。如果你有其他优化方案,能不能分享一下,^_^ 谢了先。