性能调优(一) 缓存方法返回值

对于多次调用且耗时比较长的方法,在第一次调用时,把“返回值”保存起来,在以后再次调用时,直接返回“返回值”。

 

案例:在客户代码中,多次调用方法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 });
}
}

 

 

辅助类:

 

代码
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
{
}

 

 

此性能调优方法有不妥之处,敬请指正。如果你有其他优化方案,能不能分享一下,^_^ 谢了先。

posted on 2010-10-21 16:47  三十没立  阅读(459)  评论(0编辑  收藏  举报

导航