JobHarvest——利用springAOP进行运行性能测评(更新中)
来源:互联网 发布:sql中minus 编辑:程序博客网 时间:2024/06/07 05:10
本文首先设计了一个简单的测时工具类进行函数耗时计算,然后利用spring AOP测试函数性能,最后分析了系统的耗时函数。
测试准备
测时方法1-工具类-代码入侵:
写了一个简单测试函数耗时的工具类(以后用spring aop代替)
public class ProfileUtils { private static Map<String, Long> tempTime = new HashMap<>(); private static Map<String, Long> avgTime = new TreeMap<>(); public static void start(String tag) { tempTime.put(tag, System.nanoTime()); } public static void end(String tag) { Long preTime = tempTime.get(tag); Long avgpre = avgTime.get(tag); if (preTime == null) return; long cuTime = System.nanoTime() - preTime; if (avgpre != null && avgpre != 0) { avgpre = (avgpre + cuTime) / 2; } else { avgpre = cuTime; } avgTime.put(tag, avgpre); } public static void print() { Set<String> keys = avgTime.keySet(); for (String key : keys) { Long rs = avgTime.get(key); System.out.println(key + "-avg: " + rs / 1000000 + "ms"); } }}
缺点:使用比较麻烦,需要注意前后名称对应,且需要显示入侵代码。
解决方案:SpringAOP
性能评测方法2:spring AOP
spring文件配置中加入一行(基于注解的aop配置)如下:
<aop:aspectj-autoproxy/>配置aspect类与切入点:
/** * Created by caiqingliang on 2016/8/7. * 切面,计算函数耗时,按函数总耗时排序输出(总耗时、平均单次耗时、调用次数) */@Component @Aspect public class TimeAdvice { private Map<String, MyProfile> map = new ConcurrentHashMap<>(); @Around("execution(* com.leocai.bbscraw.crawlers.MyCrawler.nextPage(..))" + "||execution(* com.leocai.bbscraw.crawlers.MyCrawler.getCuCaoTarget(..))" + "||execution(* com.leocai.bbscraw.crawlers.MyCrawler.getInfoDTO(..))" + "||execution(* com.leocai.bbscraw.services.*.*(..))" // + "||execution(* com.leocai.bbscraw.*.*(..))" // + "||execution(* com.leocai.bbscraw.mappers.*.*(..))" + "") public Object logTime(ProceedingJoinPoint pointcut) throws Throwable { long pre = System.nanoTime(); Object rs = pointcut.proceed();//此处注意要返回 String sig = pointcut.getSignature().getName(); long time = (System.nanoTime() - pre) / 1000000; MyProfile profile = map.get(sig); if (profile == null) { profile = new MyProfile(); map.put(sig, profile); } profile.incr(); profile.addTime(time); return rs; } /** * 输出的数据结构,包含总耗时、平均单次耗时、调用次数 * 大小根据总耗时比较 */ public static class MyProfile implements Comparable { List<Long> times = new ArrayList<>(); { times = Collections.synchronizedList(times); } AtomicLong count = new AtomicLong(0); public void incr() { count.incrementAndGet(); } public void addTime(long time) { times.add(time); } public long getAvg() { long avg = 0; int count = 0; for (long t : times) { avg += t; count++; } avg /= count; return avg; } public long getTotalCost() { return getAvg() * count.get(); } @Override public String toString() { return "total-cost " + getTotalCost() + "ms\tavg-cost " + getAvg() + " ms\tcalled " + count + " times"; } @Override public int compareTo(Object o) { return (int) (((MyProfile) o).getTotalCost() - getTotalCost()); } } @PreDestroy public void print() { map = MapUtil.sortByValue(map); Set<String> keys = map.keySet(); for (String key : keys) { System.out.println(key+"\t"+map.get(key)); } }}优点很明显:只需要在注解中包含需要代理的函数即可
输出:
continueCrawtotal-cost 7117msavg-cost 7117 mscalled 1 timesgetInfoDTOtotal-cost 742msavg-cost 53 mscalled 14 timesnextPagetotal-cost 609msavg-cost 203 mscalled 3 timesproduceJobInfototal-cost 378msavg-cost 27 mscalled 14 timesgetCuCaoTargettotal-cost 126msavg-cost 42 mscalled 3 timesgetLatestDateBySourcetotal-cost 11msavg-cost 11 mscalled 1 times
性能分析:
现在对CrawlerWriter重要部分函数进行性能分析:
- crawSince:单个爬虫爬取总时间
- crawOnePage-avg:单个爬虫在爬取一页上的平均耗时(不包括获取网址)
- nextPage-avg:获取下一页的耗时
单线程执行:
NJUCSCrawler.crawSince-avg: 12310msNJUCSCrawler.crawOnePage-avg: 579msNJUCSCrawler.nextPage-avg: 221ms NJUCrawler.crawSince-avg: 14272msNJUCrawler.crawOnePage-avg: 1000msNJUCrawler.nextPage-avg: 180ms NOWCODERCrawler.crawSince-avg: 33186msNOWCODERCrawler.crawOnePage-avg: 2003msNOWCODERCrawler.nextPage-avg: 584ms NYUCrawler.crawSince-avg: 27739msNYUCrawler.crawOnePage-avg: 1131msNYUCrawler.nextPage-avg: 871ms SJUCrawler.crawSince-avg: 17627msSJUCrawler.crawOnePage-avg: 1146msSJUCrawler.nextPage-avg: 172ms continueCraw-avg: 105215msinit-avg: 49ms
五个线程执行:
NJUCSCrawler.crawSince-avg: 16404msNJUCSCrawler.crawOnePage-avg: 906msNJUCSCrawler.nextPage-avg: 193ms NJUCrawler.crawSince-avg: 26351msNJUCrawler.crawOnePage-avg: 1221msNJUCrawler.nextPage-avg: 272ms NOWCODERCrawler.crawSince-avg: 55302msNOWCODERCrawler.crawOnePage-avg: 2125msNOWCODERCrawler.nextPage-avg: 614ms NYUCrawler.crawSince-avg: 43536msNYUCrawler.crawOnePage-avg: 1328msNYUCrawler.nextPage-avg: 980ms SJUCrawler.crawSince-avg: 33862msSJUCrawler.crawOnePage-avg: 1168msSJUCrawler.nextPage-avg: 214ms continueCraw-avg: 55321msinit-avg: 4ms
问题分析:
- 可以看到单线程执行仅仅比5个线程执行多耗时1倍,问题可能在webdriver需要同步,cpu核心不够,mysql冲突等。
- 五个线程并发执行,最终耗时约等于最耗时间的一个爬虫,从时间分析中看出,爬取牛客网的耗时最高,这可以理解,牛客网一页信息量较大
- 爬取一页的耗时比较大,是下一页的1.5倍-5倍不等。
- 所以爬取一页需要优化,问题可能在写mysql,也可能在查找dom
- 优化重点在爬取单页的内容上
分析crawlerReader的性能
不用缓存的CrawlerReader性能
getFromCache-avg: 0msgetJobInfos-avg: 98msgetJobInfosMysql-avg: 98msinit-avg: 3ms
使用缓存的CrawlerReader性能
getFromCache-avg: 109msgetJobInfos-avg: 124msgetJobInfosMysql-avg: 14msinit-avg: 4ms
分析:
- 使用缓存效果不明显,甚至更差,
- 可能缓存使用不当,或是数据量太少
- mysql有查询缓存
1 0
- JobHarvest——利用springAOP进行运行性能测评(更新中)
- JobHarvest——校招并发爬虫系统(更新中)
- JobHarvest——虚拟机性能监控实例
- 利用POI对EXCEL进行更新操作方法(性能大于WritableWorkbook)
- Unity手游性能测评报告——MOBA篇
- Unity手游性能测评报告——MOBA篇
- DataSnap——利用TParams进行多表事务更新
- AOP——SpringAOP(最重要)
- 利用Python进行性能测试(上)
- 利用python进行性能测试(下)
- 《Android应用性能优化》2——内存、CPU、性能测评
- SpringAop进行日志管理。
- 利用yum进行系统更新
- AnyviewC编程作业系统——支持程序可视化运行、调试和测评
- android 性能测评感悟
- OWI监控和收集方法——利用PL/SQL过程进行性能数据采样(2)
- 利用pylot进行性能测试
- Android开发——利用Systrace工具优化Android App的运行性能
- C++ 字符串长度的不同求取方式及差异
- 偷懒的桐桐(递归)
- 通过File类在计算机上创建制定的文件
- Spark初识
- hdu 5631 Rikka with Graph(无向图的割边)
- JobHarvest——利用springAOP进行运行性能测评(更新中)
- hdu 5748 Bellovin (最长递增子序列 二分查找)
- Oozie 大致概览
- module compiled against API version 9 but this version of numpy is 7的解决方法
- tjut 2824
- POJ 1861最小瓶颈树wa
- mybatis下使用log4j打印sql语句和执行结果
- MPTCP 源码分析(七) 拥塞控制
- BNU Training 2016.07.25 总结