Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 693|回复: 0

异常处理带来的副作用

[复制链接]

该用户从未签到

发表于 2011-9-13 21:36:08 | 显示全部楼层 |阅读模式
这问题, 仅仅是特定业务场景下的。 希望别纠缠。
今天看到, 某个string转integer的代码性能非常有问题。 这个代码被极大数量的使用。 代码如下:
[pre]    public Object convert(Object source) {        if (source == null) {            return new Integer(0);        }        String strValue = (String) source;        try {            return new Integer(strValue);        } catch (Exception e) {            try {                return new Integer(strValue.trim());            } catch (Exception ex) {                return new Integer(0);            }        }    }[/pre]刚看上去, 我觉得比较正常, 因为我知道业务数据99%的情况下, 不会有非法的情况。 我测试下1000W次转换的性能:
conv.convert("1234")    550ms
conv.convert(" 1234 ")  26846ms
conv.convert(" ")  51013ms
居然相差了快50
倍的性能。 这个代码仔细看了下, 如果source=" "; source=" 1234 "
这样的情况下, 性能变的特别恶劣, 特别是"", " "
的情况下, 几乎是100
倍的性能差异。 这让我意识到, java形成异常的过程是非常消耗cpu/mem
的。 我改写了这个代码,做了一下几点改进:
1. "", " " 处理过程中不再产生异常。
2. 测试了下String.trim()性能, 可以直接使用。
3. 居然 new Integer(String s)比 Integer.valueOf(String s) 性能高一点点
[pre]    static Integer ZERO_INTEGER = Integer.valueOf(0);    public Object convert(Object source) {        String strValue = (String) source;        if (strValue == null) {            return ZERO_INTEGER;        }        strValue = strValue.trim();        if (strValue.length() == 0) {            return ZERO_INTEGER;        }        Integer ret = null;        try {            ret = new Integer(strValue);        } catch (NumberFormatException e) {            ret = ZERO_INTEGER;        }        return ret;    }[/pre]我测试下了1000W次性能:
conv.convert("1234")    660ms
conv.convert(" 1234 ")  860 ms
conv.convert(" ")  260ms
虽然, 我们调整了代码, 但是, 正常情况代码的性能是下降了。 这是没有任何办法了。 当然, 为了避免正常情况下trim()的操作可以加上,这要根据生产具体情况了:
[pre]  if (strValue.charAt(0) == ' ' || strValue.charAt(strValue.length() - 1) == ' '){            strValue = strValue.trim();  }[/pre]事情应该到此了, 但是,我还是很怀疑, 这个变化怎么能在生产环境中, 产生如此大的影响,以现在CPU这点性能变化,应该不至于非常致命。应该不同的栈深度的, 造成了更大的性能障碍。我测试了下:
[pre]public Object convert2(Object source) {        if (source == null) {            return new Integer(0);        }        String strValue = (String) source;        try {            return new Integer(strValue);        } catch (Exception e) {            try {                return new Integer(strValue.trim());            } catch (Exception ex) {                return new Integer(0);            }        }    }//使用递归构造栈深度public void rescue(String source, int depth) {                if (depth > 0) {            rescue(source, --depth);        } else {            convert2(source);        }    }[/pre]100万次测试的结果如下:
conv.rescue(" 1234", 0)   2779ms
conv.rescue(" 1234", 1)   3001ms
conv.rescue(" 1234", 5)   3258ms
conv.rescue(" 1234", 10) 3751ms
conv.rescue(" 1234", 50); 7611ms
很明显栈的程度,对于异常的构造, 还是需要不少时间的。
现在我们可以获得几个结论:
1. 在一个框架级应用上, 尽量检查数据后, 再进行类型转换, 尽量避免使用"无谓"的异常, 否则,在高度覆盖的代码上, 可能造成严重的性能问题。特别使用特定的异常进行条件跳转。
2. 尽量少在系统底层抛出异常。 否则在异常栈的构造随着深度, 消耗的时间增加。
这个问题,造成生产系统速度下降了100%+。 别怀疑, 这是非常特殊的应用。 大量的解析xml数据, 然后形成JavaBean对象。 大约有60%的类型是string=>integer转化。 另外声讨下xml, 下一节, 我们会讲述一个恐怖的xml性能故障点, 大部分解析器都存在的问题。
PS: 我刚想了下, 好像我这么测试栈深度是不对的。 会不会是这个条件引起的。 谁有办法测试?
[pre] if (depth > 0) {            rescue(source, --depth);        }[/pre]
[/td][/tr][/table]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-5-7 07:53 , Processed in 0.389948 second(s), 34 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表