【性能】甲 Spads 出品字符串高效提取数值方法 Shane 末日圣诞奉献 推荐
2012-12-26 04:55
851 查看
Spads 出品,作者 WangXP 与 Shane
目录
---------- ---------- ---------- ----------
1 【综述】 http://shanelooli.blog.51cto.com/5523233/1100063
2 【程序】 http://shanelooli.blog.51cto.com/5523233/1100074
3 【功能】 http://shanelooli.blog.51cto.com/5523233/1100356
4 【性能】 测试程序 http://shanelooli.blog.51cto.com/5523233/1100417
_ 测试分析 http://shanelooli.blog.51cto.com/5523233/1100418
5 【附录】
因为篇幅原因,51CTO 只允许单篇 80000 个字符,所以本文将拆分成几个部分发布。
其中 5【附录】是针对 1【综述】内容的,所以放在了一起。
4 【性能】
---------- ---------- ---------- ----------
根据功能测试,我们可以看到,各种简易方法都不能满足需要。接下来对几种能够满足需要的“完整”方法来进行性能测评对比。测试程序通过多线程,每个线程执行一种方案若干次,来直观地表现各种方法的快慢。这种测试被重复了七轮,基本消除了线程调度起伏带来的影响。每轮执行的时间都收录并累加,作为最终评判各方法性能的依据。线程控制使用了原子操作类。测试代码如下。
┌────────────┐
│ 以下是51CTO独家 │
└────────────┘
我们可以看到,在这个测试程序,我为每一种方案开启了一个线程。当这个线程完毕之后,就会报告这种方法的用时。基于这种设计,能够方便地让先执行完的线程将时间先输出出来。为了输出格式考虑,每一轮测试,每一种方案我都是用 System.out.print(String) 方法来进行输出的。那么就需要在最后一个线程执行结束之后输出一个回车符。我在主线程中采取了人工阻塞的方式,通过线程跳过和睡眠,让主线程等待所有测试线程执行完毕。
为了防止测试线程没有执行完毕主线程就输出回车符,我进行了一种控制,通过 final AtomicInteger runThreadNum 进行线程计数。使用 final 的变量,会尽可能地使用 CPU 二级缓存。然后因为线程在生成之前就进行了线程计数 +1 ,所以只可能发生线程没有成功启动于是计数没有回归的情况,不可能发生漏计数回车符提前输出的情况。AtomicInteger 提供了很多利用 CPU 指令单步操作的方法,可以避开多线程操作同一个数据有可能产生的并发问题。
本文还发表在我的其它技术日志
CSDN : http://blog.csdn.net/shanelooli/article/details/8432250
ITeye : http://surmounting.iteye.com/blog/1754323
中国开源社区: http://my.oschina.net/shane1984/blog/98088
目录
---------- ---------- ---------- ----------
1 【综述】 http://shanelooli.blog.51cto.com/5523233/1100063
2 【程序】 http://shanelooli.blog.51cto.com/5523233/1100074
3 【功能】 http://shanelooli.blog.51cto.com/5523233/1100356
4 【性能】 测试程序 http://shanelooli.blog.51cto.com/5523233/1100417
_ 测试分析 http://shanelooli.blog.51cto.com/5523233/1100418
5 【附录】
因为篇幅原因,51CTO 只允许单篇 80000 个字符,所以本文将拆分成几个部分发布。
其中 5【附录】是针对 1【综述】内容的,所以放在了一起。
4 【性能】
---------- ---------- ---------- ----------
根据功能测试,我们可以看到,各种简易方法都不能满足需要。接下来对几种能够满足需要的“完整”方法来进行性能测评对比。测试程序通过多线程,每个线程执行一种方案若干次,来直观地表现各种方法的快慢。这种测试被重复了七轮,基本消除了线程调度起伏带来的影响。每轮执行的时间都收录并累加,作为最终评判各方法性能的依据。线程控制使用了原子操作类。测试代码如下。
public void testFetchNumberPerformance() { Runnable r; List<SortedMap<Long, String>> timeUsed = new ArrayList<SortedMap<Long, String>>(this.numStrs.length); System.out.println("Loop times = " + this.loopNum); System.out.println("---------- ---------- ---------- ----------"); for (final String numStr: this.numStrs) { final Map<String, Long> timeUsedCount = Collections.synchronizedMap(new HashMap<String, Long>()); System.out.println("String: " + numStr); for (int loop = -1; ++loop != 7; ) { final AtomicInteger runThreadNum = new AtomicInteger(0); // StringTool r = new Runnable() { public void run() { boolean hasEx = false; if (timeUsedCount.get("StringTool") == null) timeUsedCount.put("StringTool", 0L); long start = System.currentTimeMillis(); for (int index = -1; ++index != FetchNumberTest.this.loopNum; ) { try { StringTool.parseNumber(numStr); } catch (Exception ex) { hasEx = true; } } long use = System.currentTimeMillis() - start; System.out.print("\ttool:" + use + "ms" + (hasEx ? "(EX)" : "") + '.'); use += timeUsedCount.get("StringTool"); timeUsedCount.put("StringTool", use); runThreadNum.addAndGet(-1); Thread.yield(); } }; runThreadNum.addAndGet(1); new Thread(r).start(); // JavaLib r = new Runnable() { public void run() { boolean hasEx = false; if (timeUsedCount.get("JavaLib") == null) timeUsedCount.put("JavaLib", 0L); long start = System.currentTimeMillis(); for (int index = -1; ++index != FetchNumberTest.this.loopNum; ) { try { FetchNumberTest.this.fetchNumberByJavaLib(numStr); } catch (Exception ex) { hasEx = true; } } long use = System.currentTimeMillis() - start; System.out.print("\tlib:" + use + "ms" + (hasEx ? "(EX)" : "") + '.'); use += timeUsedCount.get("JavaLib"); timeUsedCount.put("JavaLib", use); runThreadNum.addAndGet(-1); Thread.yield(); } }; runThreadNum.addAndGet(1); new Thread(r).start(); // WholeRegex r = new Runnable() { public void run() { boolean hasEx = false; if (timeUsedCount.get("WholeRegex") == null) timeUsedCount.put("WholeRegex", 0L); long start = System.currentTimeMillis(); for (int index = -1; ++index != FetchNumberTest.this.loopNum; ) { try { FetchNumberTest.this.fetchNumberByRegex(numStr, false); } catch (Exception ex) { hasEx = true; } } long use = System.currentTimeMillis() - start; System.out.print("\treg:" + use + "ms" + (hasEx ? "(EX)" : "") + '.'); use += timeUsedCount.get("WholeRegex"); timeUsedCount.put("WholeRegex", use); runThreadNum.addAndGet(-1); Thread.yield(); } }; runThreadNum.addAndGet(1); new Thread(r).start(); // Direct r = new Runnable() { public void run() { boolean hasEx = false; if (timeUsedCount.get("Direct") == null) timeUsedCount.put("Direct", 0L); long start = System.currentTimeMillis(); for (int index = -1; ++index != FetchNumberTest.this.loopNum; ) { try { FetchNumberTest.this.fetchNumberByDirect(numStr); } catch (Exception ex) { hasEx = true; } } long use = System.currentTimeMillis() - start; System.out.print("\t--:" + use + "ms" + (hasEx ? "(EX)" : "") + '.'); use += timeUsedCount.get("Direct"); timeUsedCount.put("Direct", use); runThreadNum.addAndGet(-1); Thread.yield(); } }; runThreadNum.addAndGet(1); new Thread(r).start(); // WholeApacheUtils r = new Runnable() { public void run() { boolean hasEx = false; if (timeUsedCount.get("WholeApacheUtils") == null) timeUsedCount.put("WholeApacheUtils", 0L); long start = System.currentTimeMillis(); for (int index = -1; ++index != FetchNumberTest.this.loopNum; ) { try { FetchNumberTest.this.fetchNumberByApacheUtils(numStr); } catch (Exception ex) { hasEx = true; } } long use = System.currentTimeMillis() - start; System.out.print("\tap:" + use + "ms" + (hasEx ? "(EX)" : "") + '.'); use += timeUsedCount.get("WholeApacheUtils"); timeUsedCount.put("WholeApacheUtils", use); runThreadNum.addAndGet(-1); Thread.yield(); } }; runThreadNum.addAndGet(1); new Thread(r).start(); while (runThreadNum.get() != 0) { try { Thread.sleep(10); } catch (Exception ex) { } Thread.yield(); } for (int index = -1; ++index != 3; ) { try { Thread.sleep(100); } catch (Exception ex) { } Thread.yield(); } System.out.println(); } SortedMap<Long, String> thisNumStrTimeUsed = Collections.synchronizedSortedMap(new TreeMap<Long, String>()); for (String name: timeUsedCount.keySet()) thisNumStrTimeUsed.put(timeUsedCount.get(name), name); timeUsed.add(thisNumStrTimeUsed); for (Long time: thisNumStrTimeUsed.keySet()) System.out.println(thisNumStrTimeUsed.get(time) + ": " + time + " ms."); System.out.println("---------- ---------- ---------- ----------"); } }
┌────────────┐
│ 以下是51CTO独家 │
└────────────┘
我们可以看到,在这个测试程序,我为每一种方案开启了一个线程。当这个线程完毕之后,就会报告这种方法的用时。基于这种设计,能够方便地让先执行完的线程将时间先输出出来。为了输出格式考虑,每一轮测试,每一种方案我都是用 System.out.print(String) 方法来进行输出的。那么就需要在最后一个线程执行结束之后输出一个回车符。我在主线程中采取了人工阻塞的方式,通过线程跳过和睡眠,让主线程等待所有测试线程执行完毕。
为了防止测试线程没有执行完毕主线程就输出回车符,我进行了一种控制,通过 final AtomicInteger runThreadNum 进行线程计数。使用 final 的变量,会尽可能地使用 CPU 二级缓存。然后因为线程在生成之前就进行了线程计数 +1 ,所以只可能发生线程没有成功启动于是计数没有回归的情况,不可能发生漏计数回车符提前输出的情况。AtomicInteger 提供了很多利用 CPU 指令单步操作的方法,可以避开多线程操作同一个数据有可能产生的并发问题。
本文还发表在我的其它技术日志
CSDN : http://blog.csdn.net/shanelooli/article/details/8432250
ITeye : http://surmounting.iteye.com/blog/1754323
中国开源社区: http://my.oschina.net/shane1984/blog/98088
相关文章推荐
- 【综述】Spads 出品字符串高效提取数值方法 Shane 末日圣诞奉献 推荐
- 【性能】乙 Spads 出品字符串高效提取数值方法 Shane 末日圣诞奉献
- Spads 出品字符串高效提取数值方法 Shane 末日圣诞奉献
- 【程序】Spads 出品字符串高效提取数值方法 Shane 末日圣诞奉献
- Spads 出品字符串高效提取数值方法 Shane 末日圣诞奉献
- 【功能】Spads 出品字符串高效提取数值方法 Shane 末日圣诞奉献
- 爪哇(Java)自定义的二个字符串高效处理方法,在静寂一个半月之后 推荐
- zz 高效的中文字符串截取函数,附带一个性能测试方法Benchmark_Iterate
- 判断一个字符串是否全是数字的多种方法及其性能比较(C#实现)
- OC中字符串的提取与替换-四种不同方法实现
- 判断一个字符串是否全是数字的多种方法及其性能比较(C#实现)--来源CSDN
- StringBuffer对象和传统的字符串连接方法性能测试比较
- Java 字符串拼接 五种方法的性能比较分析
- Java各种字符串连接方法性能比较
- JS中利用正则表达式提取一个字符串中的子字符串的方法
- OC中字符串和数值的方法与使用实例解析
- 从LiveJournal后台发展看大规模网站性能优化方法(推荐:有图示)
- Sql Server中三种字符串合并方法的性能比较
- 从字符串中查找字符出现次数的方法和性能对比
- 将16进制字符串转换为16进制数值的两种方法