原文:http://www.cnblogs.com/RicCC/archive/2010/03/15/castle-dynamic-proxy.html

在Nuget引用 Castle.DynamicProxy 和 Newtonsoft.Json 这个

操作日志的作用:

    可用来分析方法的执行效率

    分析方法执行效率慢的原因

    根据传入的参数测试,找到运行瓶颈问题

拦截器:

    /// <summary>
/// 拦截器
/// </summary>
public class CallingLogInterceptor : IInterceptor
{
private DateTime dt { get; set; }
private TimeSpan ts { get; set; } /// <summary>
/// 方法执行前
/// </summary>
/// <param name="invocation"></param>
private void PreProceed(IInvocation invocation)
{
dt = DateTime.Now;
} /// <summary>
/// 方法执行后
/// </summary>
/// <param name="invocation"></param>
private void PostProceed(IInvocation invocation)
{
ts = DateTime.Now - dt;
MethodOperationInfo.Add(invocation, ts.TotalMilliseconds);
} /// <summary>
/// 拦截
/// </summary>
/// <param name="invocation"></param>
public void Intercept(IInvocation invocation)
{
this.PreProceed(invocation);
invocation.Proceed();//调用
this.PostProceed(invocation);
}
}

操作日志:

    /// <summary>
/// 操作日志
/// </summary>
public class MethodOperationInfo
{
public string NameSpaceName { get; set; }
public string ClassName { get; set; }
public string MethodName { get; set; }
public string Parameters { get; set; }
public string ParameterTypes { get; set; }
public double TotalMilliseconds { get; set; }
public int ExecuteNumber { get; set; } public static List<MethodOperationInfo> list = new List<MethodOperationInfo>();//存放 详细信息
public static Dictionary<string, MethodOperationInfo> dic = new Dictionary<string, MethodOperationInfo>();//存放 统计信息 /// <summary>
/// 保证数据长度相同
/// </summary>
/// <param name="obj"></param>
/// <param name="len"></param>
/// <param name="afterFill">后填充/前填充</param>
/// <returns></returns>
public static string GetSameLenString(object obj, int len, bool afterFill = true)
{
string name = obj.ToString();
int count = len - name.Length; if (afterFill)
{
for (int i = ; i < count; i++)
{
name += " ";
}
return name; }
else
{
string value = "";
for (int i = ; i < count; i++)
{
value += " ";
}
value += name;
return value;
}
} /// <summary>
/// 获取方法的参数类型
/// 如:(System.String, System.Object, System.Int32)
/// </summary>
/// <param name="invocation"></param>
/// <returns></returns>
public static string GetParameterTypes(IInvocation invocation)
{
MethodInfo mInfo = invocation.Method;
ParameterInfo[] pInfos = mInfo.GetParameters(); string str = "";
str += "(";
for (int j = ; j < pInfos.Length; j++)
{
var p = pInfos[j];
string pTypeName = $"{p.ParameterType.ToString()}, ";
if (p.ParameterType.IsGenericType && (p.ParameterType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
pTypeName = $"{Nullable.GetUnderlyingType(p.ParameterType).Name}?, ";
}
str += pTypeName;
}
str = str.TrimEnd(' ').TrimEnd(',');
str += ")"; return str;
} /// <summary>
/// 获取方法的参数
/// </summary>
/// <param name="invocation"></param>
/// <returns></returns>
public static string GetParameter(IInvocation invocation)
{
string Parameters = "";//参数
if ((invocation.Arguments != null) && (invocation.Arguments.Length > ))
{
Parameters = JsonConvert.SerializeObject(invocation.Arguments);
}
return Parameters;
} /// <summary>
/// 添加信息
/// </summary>
/// <param name="invocation"></param>
/// <param name="TotalMilliseconds"></param>
public static void Add(IInvocation invocation, double TotalMilliseconds)
{
string NameSpaceName = invocation.TargetType.Namespace;
string ClassName = invocation.TargetType.Name;
string MethodName = invocation.Method.Name;//方法名
string ParameterTypes = GetParameterTypes(invocation);
string Parameters = GetParameter(invocation);//参数 //添加到 list
var model = new MethodOperationInfo
{
NameSpaceName = NameSpaceName,
ClassName = ClassName,
MethodName = MethodName,
ParameterTypes = ParameterTypes,
Parameters = Parameters,
TotalMilliseconds = TotalMilliseconds,
ExecuteNumber =
};
list.Add(model); //添加到 dictionary
string key = MethodName + ParameterTypes;
if (dic.ContainsKey(key))
{
dic[key].TotalMilliseconds += TotalMilliseconds;
dic[key].ExecuteNumber += ;
}
else
{
dic.Add(key, model.MemberwiseClone() as MethodOperationInfo);
}
} /// <summary>
/// 显示日志
/// </summary>
/// <param name="ShowDetailRecord">是否显示详情记录-比较占用时间</param>
/// <param name="IsFilter">是否开启过滤</param>
public static void Show(bool ShowDetailRecord = true, bool IsFilter = false)
{
StringBuilder sb = new StringBuilder();
DateTime beforDT = DateTime.Now;
List<string> list_Show_Method = new List<string>() { "GetSingle_Value1" };//可改为配置参数 //每个方法-耗时
string str = "";
double TotalMilliseconds = ;
foreach (var item in dic)
{
TotalMilliseconds += item.Value.TotalMilliseconds; str += $"命名空间:{GetSameLenString(item.Value.NameSpaceName, 40)} ";
str += $"类名:{GetSameLenString(item.Value.ClassName, 30)} ";
str += $"方法:{GetSameLenString(item.Key, 80)} ";
str += $"次数:{GetSameLenString(item.Value.ExecuteNumber, 10)} ";
str += $"耗时:{GetSameLenString(item.Value.TotalMilliseconds, 10, false) }毫秒 ";
str += $"\r\n";
}
sb.Append(str + "\r\n\r\n"); //方法-总耗时
str = "";
str += $"所有方法-耗时:{TotalMilliseconds}毫秒 ";
str += $"{TotalMilliseconds / 1000}秒 ";
str += $"{(TotalMilliseconds / 1000 / 60).ToString("f2")}分钟 ";
str += $"当前时间:{DateTime.Now} ";
sb.Insert(, str + "\r\n\r\n"); //方法每次-耗时
if (ShowDetailRecord)
{
for (int i = ; i < list.Count; i++)
{
Console.WriteLine($"处理数据-当前行:{list.Count - i}");
var item = list[i]; //数据过滤
if (IsFilter && !list_Show_Method.Contains(item.MethodName))
{
continue;
} sb.Append($"命名空间:{GetSameLenString(item.NameSpaceName, 40)} ");
sb.Append($"类名:{GetSameLenString(item.ClassName, 30)} ");
sb.Append($"方法:{GetSameLenString(item.MethodName + item.ParameterTypes, 80)} ");
sb.Append($"次数:{GetSameLenString(item.ExecuteNumber, 10)} ");
sb.Append($"耗时:{GetSameLenString(item.TotalMilliseconds, 10, false) }毫秒 ");
sb.Append($"参数:{GetSameLenString(item.Parameters, 50)} ");
sb.Append($"\r\n");
}
} //计算日志-耗时
sb.Insert(, $"计算日志-耗时:{DateTime.Now.Subtract(beforDT).TotalSeconds.ToString("#0.00000")}秒 \r\n\r\n"); System.IO.File.WriteAllText($"LOG_{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.txt", sb.ToString());
Console.WriteLine("完成!");
} }

测试类:

    /// <summary>
/// 测试类1
/// </summary>
public class Class5_test1
{
public virtual void test1()
{
System.Threading.Thread.Sleep( * );
int num = ;
for (int i = ; i < ; i++)
{
num += ;
}
test1();
test1(, );
test1(, "");
}
public virtual void test1(int i) { }
public virtual void test1(int i, int j) { }
public virtual void test1(int i, string j) { }
}

入口:

    class Class5
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();//代理
CallingLogInterceptor interceptor = new CallingLogInterceptor();//定义 拦截器
Class5_test1 entity = generator.CreateClassProxy<Class5_test1>(interceptor);
//SensorRecordService entity = generator.CreateClassProxy<SensorRecordService>(interceptor); DateTime beforDT1 = DateTime.Now;//开始时间
try
{
entity.test1();
//entity.DealWithSensorRecord(74619, 174619);
//int start = Convert.ToInt32(GetAppSetting("start_Id"));
//int end = Convert.ToInt32(GetAppSetting("end_Id"));
//for (int i = start; i < end;)
//{
// int start_Id = i;
// i = i + 10000;
// int end_Id = i > end ? end : i;
// Console.WriteLine($"开始计算:start_Id:{start_Id} end_Id:{end_Id}");
// entity.DealWithSensorRecord(start_Id, end_Id);
//} }
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
MethodOperationInfo.Show(); TimeSpan ts = DateTime.Now.Subtract(beforDT1);
string str = $"总共耗时:{ts.TotalSeconds.ToString()}秒 或 {ts.TotalMinutes.ToString("f3")}分";
System.IO.File.AppendAllText("1.txt", $"{str}\r\n\r\n"); Console.WriteLine(str);
Console.WriteLine("操作完成!");
Console.ReadLine();
} /// <summary>
/// 获取 配置文件信息
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetAppSetting(string key)
{
return ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings.Settings[key].Value;
}
}

会往Debug写入一个日志文件。

预览效果1:

预览效果2:

预览效果3:(删掉了命名空间和类名)

C# 监测每个方法的执行次数和占用时间(测试3)的更多相关文章

  1. C# 监测每个方法的执行次数和占用时间(测试4)

    今天也要做这个功能,就百度一下,结果搜索到了自己的文章.一开始还没注意,当看到里面的一个注释的方法时,一开始还以为自己复制错了代码,结果仔细一看网页的文章,我去,原来是自己写的,写的确实不咋地. 把自 ...

  2. C# 监测每个方法的执行次数和占用时间(测试2)

    在Nuget引用 Castle.DynamicProxy 和 Newtonsoft.Json 这个 原文:http://www.cnblogs.com/RicCC/archive/2010/03/15 ...

  3. C# 监测每个方法的执行次数和占用时间(测试1)

    在Nuget引用 Castle.DynamicProxy 和 Newtonsoft.Json 这个 原文:http://www.cnblogs.com/RicCC/archive/2010/03/15 ...

  4. C# 监测每个方法的执行次数和占用时间(测试5)

    又找到了一个bug 测试的类: public class Class11_1 { public virtual List<int> test2_1(List<tb_SensorRec ...

  5. 事件之onTouch方法的执行过程 及和 onClick执行发生冲突的解决办法

    转载:http://blog.csdn.net/jiangwei0910410003/article/details/17504315#quote 博主推荐: 风萧兮兮易水寒,“天真”一去兮不复还.如 ...

  6. Android中onTouch方法的执行过程以及和onClick执行发生冲突的解决办法

    $*********************************************************************************************$ 博主推荐 ...

  7. ORACLE查看SQL的执行次数/频率

    在ORACLE数据库应用调优中,一个SQL的执行次数/频率也是常常需要关注的,因为某个SQL执行太频繁,要么是由于应用设计有缺陷,需要在业务逻辑上做出优化处理,要么是业务特殊性所导致.如果执行频繁的S ...

  8. PLSQL_查询SQL的执行次数和频率(案例)

    2014-12-25 Created By BaoXinjian

  9. PLSQL_监控有些SQL的执行次数和频率

    原文:PLSQL_监控有些SQL的执行次数和频率 2014-12-25 Created By 鲍新建

随机推荐

  1. courator - maven

    ZK3.4.x: <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes --> <de ...

  2. 图像_pytesseract

    所需模块 ①安装PIL:pip install Pillow(之前的博客中有写过) ②安装pytesser3:pip install pytesser3 ③安装pytesseract:pip inst ...

  3. IOS 7层协议

    ios七层 (1)物理层——Physical 这是整个OSI参考模型的最低层,它的任务就是提供网络的物理连接.所以,物理层是建立在物理介质上(而不是逻辑上的协议和会话),它提供的是机械和电气接口.主要 ...

  4. KVM CPU线程等学习记录

    绝大多数操作系统调度单位是线程.线程是调度和分配的基本单位,进程是资源拥有的基本单位.linux下fork的叫进程pthread叫线程创建进程比线程性能要差好多5-100倍,因进程不同而异.进程之间共 ...

  5. mysql where in形式存储过程如何传递带有单引号的入参

    对于存储过程或者函数,我们通常都有这样的一个需求,传递一个参数,输出一个结果.如:我传递一个账号,返回这个账号所拥有的权限.但是如果这个需求改了,我要传递多个账号,获取这些账号权限,但是账号的个数不限 ...

  6. phpmyadmin无登录表单无法登陆

    发现我的博客的phpmyadmin登录过一次成功之后,后面在登录没有登录表单了,查了很多原因,下面的方法亲测可以解决 打开 phpMyAdmin\libraries\plugins\auth\Auth ...

  7. 性能测试day02_后端网络协议架构

    接着第一天的尾,继续来学习性能测试,上一次说到性能要大致经历哪些阶段,那么我们也来看下行业的做法: 行业有两种做法,一个是TPC,另一个是SPEC: TPC:指定业务类型,获得该指定业务的性能指标,也 ...

  8. gentoo kvm qemu virt-manager - Unable to complete install: error creating macvtap interface macvtap0@: Operation not supported'

    碰到这个一般是内核没有开启相应的 macvtap 选项,开启相应选项后,就不会报错了. Device Drivers ---> Network Device Support ---> &l ...

  9. <Linux> SSH配置之后 SHH slave1 测试 error:SSH: command not found

    首先要查看一下ssh命令存在何处 # which ssh /usr/bin/ssh 使用ssh的绝对路径 # /usr/bin/ssh slave1Welcome to Ubuntu 16.04 LT ...

  10. python [] 数组 list 交集 并集 差集

    >>> a = [1,2,3] >>> b = [2,4,5] >>> list(set(a).intersection(set(b))) [2] ...