
十四 对于boolean值 避免不必要的等式判断
将一个boolean值与一个true比较是一个恒等 *** 作(直接返回该boolean变量的值) 移走对于boolean的不必要 *** 作至少会带来 个好处
)代码执行的更快 (生成的字节码少了 个字节)
)代码也会更加干净
例子
public class UEQ
{
boolean method (String string) {
return string endsWith ( a ) == true; // Violation
}
}
更正
class UEQ_fixed
{
boolean method (String string) {
return string endsWith ( a );
}
}
十五 对于常量字符串 用 String 代替 StringBuffer
常量字符串并不需要动态改变长度
例子
public class USC {
String method () {
StringBuffer s = new StringBuffer ( Hello );
String t = s + World! ;
return t;
}
}
更正
把StringBuffer换成String 如果确定这个String不会再变的话 这将会减少运行开销提高性能
十六 用 StringTokenizer 代替 indexOf() 和 substring()
字符串的分析在很多应用中都是常见的 使用indexOf()和substring()来分析字符串容易导致StringIndexOutOfBoundsException 而使用StringTokenizer类来分析字符串则会容易一些 效率也会高一些
例子
public class UST {
void parseString(String string) {
int index = ;
while ((index = string indexOf( index)) != ) {
System out println (string substring(index string length()));
}
}
}
参考资料
Graig Larman Rhett Guthrie: Java Performance and Idiom Guide
Prentice Hall PTR ISBN: pp –
十七 使用条件 *** 作符替代 if (cond) return; else return; 结构
条件 *** 作符更加的简捷
例子
public class IF {
public int method(boolean isDone) {
if (isDone) {
return ;
} else {
return ;
}
}
}
更正
public class IF {
public int method(boolean isDone) {
return (isDone : );
}
}
十八 使用条件 *** 作符代替 if (cond) a = b; else a = c; 结构
例子
public class IFAS {
void method(boolean isTrue) {
if (isTrue) {
_value = ;
} else {
_value = ;
}
}
private int _value = ;
}
更正
public class IFAS {
void method(boolean isTrue) {
_value = (isTrue : ); // pact expression
}
private int _value = ;
}
十九 不要在循环体中实例化变量
在循环体中实例化临时变量将会增加内存消耗
例子
import java util Vector;
public class LOOP {
void method (Vector v) {
for (int i= ;i < v size();i++) {
Object o = new Object();
o = v elementAt(i);
}
}
}
更正
在循环体外定义变量 并反复使用
import java util Vector;
public class LOOP {
void method (Vector v) {
Object o;
for (int i= ;i<v size();i++) {
o = v elementAt(i);
}
}
}
二十 确定 StringBuffer的容量
StringBuffer的构造器会创建一个默认大小(通常是 )的字符数组 在使用中 如果超出这个大小 就会重新分配内存 创建一个更大的数组 并将原先的数组复制过来 再丢弃旧的数组 在大多数情况下 你可以在创建StringBuffer的时候指定大小 这样就避免了在容量不够的时候自动增长 以提高性能
例子
public class RSBC {
void method () {
StringBuffer buffer = new StringBuffer(); // violation
buffer append ( hello );
}
}
更正
为StringBuffer提供寝大小
public class RSBC {
void method () {
StringBuffer buffer = new StringBuffer(MAX);
buffer append ( hello );
}
private final int MAX = ;
}
参考资料
Dov Bulka Java Performance and Scalability Volume : Server Side Programming
Techniques Addison Wesley ISBN: p –
二十一 尽可能的使用栈变量
如果一个变量需要经常访问 那么你就需要考虑这个变量的作用域了 static local还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费 个时钟周期
例子
public class USV {
void getSum (int[] values) {
for (int i= ; i < value length; i++) {
_sum += value[i]; // violation
}
}
void getSum (int[] values) {
for (int i= ; i < value length; i++) {
_staticSum += value[i];
}
}
private int _sum;
private static int _staticSum;
}
更正
如果可能 请使用局部变量作为你经常访问的变量
你可以按下面的方法来修改getSum()方法
void getSum (int[] values) {
int sum = _sum; // temporary local variable
for (int i= ; i < value length; i++) {
sum += value[i];
}
_sum = sum;
}
程序的效率是每个程序员都应该重视的,无论您是采用哪一种语言进行开发 程序有时候越短,并不一定越快,有时候程序很多代码,但不一定会很慢 性能是一把双刃剑, 获得时间效率的同时, 牺牲的是空间的开销 这里提供一些建议以提高你的程序运行速度和减低系统荷载。
首先是尽量减少I/O *** 作,类似对硬盘的读写的I/O *** 作是最耗费时间的, 比如读写数据库。以下是减少I/O *** 作的例子:
1, 减少数据库DB的读写 *** 作, 当使用VIEW视图的时候, 当被视图join的table有数据更新 *** 作的时候, 同时系统也会更新到这个view里面, 使得它们之间的数据一样, 所以使用视图会对这些日常 *** 作带来效率问题 如果视图join的表多数是日常事物需要更新的事物数据表(如EKET), 就要避免使用视图
2, 避免使用SELECT , 尽量使用SELECT A B C INTO TABLE ITAB这样的语句。这个 *** 作会将所有符合条件的数据一次性地读进内表,这比在SELECT A B C INTO WA APPEND ENDSELECT的循环中添加数据到内表要快。不用频繁的读DB
3, 避免频繁使用SELECT SINGLE语句, 特别是在LOOP和SELECTENDSELECT里面用, 应该把要读取的数据用SELECT FOR ALL ENTRIES IN 一次全部取得, 然后用READ TABLE WITH KEY BINARY SEARCH
虽然说 *** 作内存比磁盘 *** 作要高效,但是如果对内存的使用不加以控制,可能有些时候不得不对硬盘的交换空间 *** 作, 这样就增加了对磁盘的I/O读写 *** 作正如下面所说:
4, 当你定义内表的时候可以也会出现这样的问题, 比如你定义一个内表使用的是OCCURS 100,而不是OCCURS 0, 会导致内表长度大于100的时候,就会占用系统页面缓存。
5, Field-groups对于多层次的排序和显示是非常有用的。它是将数据写入系统的页面文件,而不是内存(内表一般是使用内存的)。基于这个原因,field-groups比较适合于处理大量数据的列表(一般超过50000条记录)。如果涉及大量的数据处理,应该首先和系统管理员协商来决定这个程序最多能使用多少内存,以计算这个程序需要使用多少资源。然后你就可以决定是把数据写入内存还是交换空间。
6, 用SORT代替ORDER BY, ORDER BY从句是执行在数据库服务器上, 而SORT是ABAP语句执行在应用服务器上的 数据库服务器通常会形成性能瓶颈问题, 所以最好是吧数据导入内表做SORT
7, 避免使用SELECT DISTINCT语句, 因为当你用来判断唯一的字段为非索引字段时, 效率是十分的低, 所以请导入内表SORT后, 使用DELETE ADJACENT DUPLICATES 来去重复
其次就是要减轻CPU的负载, 可以通过优化程序来改善,比如在程序中语句和算法, 以下是减低CPU负载的优化例子:
1, 使用宏代替频繁函数调用 ABAP没有内联函数这个说法, 所以我们如果需要频繁调用函数时, 函数调用有栈内存创建和释放的开销 在ABAP中可以用宏代码提高执行效率,宏代码不是函数但使用起来像函数,编译器用复制宏代码的方式取代函数调用,省去了参数压栈、从而提高速度。注意使用宏有缺点:(1)容易出错, 宏不能pass-by-value按值传递,用于代替实现函数功能时要十分注意!(2)不可调试; (3)无法 *** 作类的私有数据成员
2, 避免使用过得的LOOP 和SELECT END SELECT 避免使用嵌套的LOOP 和SELECT END SELECT
3, 尽可能多地使用表的KEY FIELD作为Where分句的条件选项。比如SELECT FROM BSEG WHERE BUKRS = '1000' AND BELNR = '0100000007' AND GJAHR = '2006' AND BUZEI = '003' 这里的四个字段BUKRS,BELNR,GJAHR,BUZEI 都是BSEG表的KEY字段
4, 如果某些数据需要频繁的从不同表提取, 使用视图VIEW实现读取缓存可以提高效率 当视图连接的是读取次数较多, 但写入不频繁的表时(比如物料主数据表MARA), 可以使用视图, 这样比在程序里面简单用join要快,理论上join语句每次读取的速度都是一样的, 而视图是从读二次开始就快了,而且cache使得网络负载减低
5, 使用SQL语句里面的JOIN时候, 应该避免JOIN的表不要超过3个, 否则严重影响效率 如果真的要JOIN表3个以上的话, 正确的方法不是用视图VIEW, 而是使用SELECT INTO TABLE FOR ALL ENTRIES IN 以及 READ TABLE WITH KEY BINARY SEARCH例如我们要提高读取BSEG表的性能,首先我们会根据GJAHR主键从BKPF表取出部分数据到内表itab,然后使用FOR ALL ENTRIES IN itab WHERE BSEG~BELNR = itab~BELNR 这样的的方法取得符合itab里所有条件的BSEG数据注意使用FOR ALL ENTRIES要先CHECK作为条件的内表itab是否为空,还有作为WHERE的条件在这个内表里面是否会有空值存在,否则无效
6, 注意使用CORRESPONDING FIELDS OF 和 MOVE-CORRESPONDING 时候会进行字段比较, 带来CPU的开销大
7, 避免过得而频繁的数据类型转换,比如N转换为C,但是从N转换成STRING却是很快的,因为 *** 作STRING比CHAR类型少了比较长度的时间
8, 使用二级索引提高DDIC的读写效率, 可以根据你的需要在SE11里面创建INDEX, 并让你程序里的SQL查询语句里WHERE条件的顺序与你的索引顺序一致
9, 二分查找比线性查找要高效,READ TABLE的之前使用SORT TABLE BY XXX 某个表关键字段进行排序, 然后使用READ TABLE WITH KEY XXX = 'XXX' BINARY SEARCH 这个就是所谓的二分查找法的应用
10, 避免使用SQL语句动态查询条件,动态表名和动态字段名, 必要时候用宏或者子程序模块代替
11, 对于同一功能的函数和方法, 调用METHOD比调用FUNCTION要快
12, SORTED TABLE可以使用二分查找法取得节点, 其时间复杂度是O(log N),但是插入节点会慢,因为要移动很多节点 而HASHED TABLE则是基于哈希算法的,其高效主要体现在把数据的存储和查找时间大大降低,几乎可以看成是常数时间O(1),而代价是消耗比较多的内存,然而在硬件技术越来越发达的今天,用空间换时间的做法在某种意义上是值得的。但是使用哈希表必须注意键值的唯一性!如果键值会出现重复的话, 不能使用哈希表,只能用排序表和标准表。
13, 使用APPEND LINES(或者INSERT LINES) OF ITAB1 TO ITAB2 比 LOOP AT ITAB1 INTO WA APPEND(INSERT) WA TO ITAB2 ENDLOOP 要高效
14, 使用效率比较高的COLLECT, DELETE ADJACENT DUPLICATES FROM语句。
15, 使用高效的CONTEXT SQL语句如以下代码2比代码1要快10倍以上!
代码1:
SELECT FROM SBOOK INTO SBOOK_WA UP TO 10 ROWS
SELECT SINGLE AIRPFROM AIRPTO INTO (AP1, AP2)
FROM SPFLI
WHERE CARRID = SBOOK_WA-CARRID
AND CONNID = SBOOK_WA-CONNID
SELECT SINGLE NAME INTO NAME1 FROM SAIRPORT
WHERE ID = AP1
SELECT SINGLE NAME INTO NAME2 FROM SAIRPORT
WHERE ID = AP2
ENDSELECT
代码2:
SELECT FROM SBOOK INTO SBOOK_WA UP TO 10 ROWS
SUPPLY CARRID = SBOOK_WA-CARRID
CONNID = SBOOK_WA-CONNID
TO CONTEXT TRAV1
DEMAND AIRPFROM = AP1
AIRPTO = AP2
NAME_FROM = NAME1
NAME_TO = NAME2
FROM CONTEXT TRAV1
ENDSELECT
最后是注意内存的使用,以下是内存优化方面的例子:
1, 虽然ABAP拥有垃圾处理的机制, 但是这个是在程序运行完成后实现的 所以我们尽量把无用的变量,内表,对象都释放掉;
2, 尽量减少无用的静态定义的变量,内表和对象, 因为静态定义的对象会在编译开始就占有内存空间;
3, 尽量减少网络的传输负载, 比如在设计RFC远程调用传回的内表数据要尽量精简, 数据量越大,对CPU和内存需求越多;
4, 内存使用紧张的情况下, 使用FREE语句, 以及SQL语句的PACKAGE SIZE n 选项
SELECT vbeln erdat
FROM vbak
INTO TABLE li_vbak PACKAGE SIZE 50
1、使用where语句
不推荐
Select from zflight
Check : zflight-airln = ‘LF’ and zflight-fligh = ‘BW222’
Endselect
推荐
Select from zflight where airln = ‘LF’ and fligh = ‘222’
Endselect
2、使用聚合函数
不推荐
Maxnu = 0
Select from zflight where airln = ‘LF’ and cntry = ‘IN’
Check zflight-fligh >maxnu
Maxnu = zflight-fligh
Endselect
推荐
Select max( fligh ) from zflight intomaxnu where airln = ‘LF’ and cntry = ‘IN’
3、使用视图代替基本表查询
不推荐
Select from zcntry where cntry like ‘IN%’
Selectsingle from zflight where cntry = zcntry-cntry and airln = ‘LF’
Endselect
推荐
Select from zcnfl where cntry like ‘IN%’ and airln = ‘LF’
Endselect
4、使用INTO table 代替select endselect
不推荐
Refresh: int_fligh
Select from zflight into int_fligh
Append int_fligh Clear int_fligh
Endselect
推荐
Refresh: int_fligh
Select from zflight into table int_fligh
5、使用批量修改内表代替逐行修改
不推荐
Loop at int_fligh
If int_fligh-flag is initial
Int_fligh-flag = ‘X’
Endif
Modify int_fligh
Endloop
推荐
Int_fligh-flag = ‘X’
Modify int_fligh transporting flag where flag is initial
当使用不带表头的内表时,需要从工作区删除,例如
MODIFY IT_TEST1 FROM WA_TEST1 TRANSPORTING BOX WHERE BOX IS INITIAL
6、使用二分法查询,提高查询内表数据速度
不推荐
Read table int_fligh with key airln = ‘LF’
推荐
Read table int_fligh with key airln = ‘LF’ binary search
7、两个内表添加使用批量增加代替逐行
不推荐
Loop at int_fligh1
Append int_fligh1 to int_fligh2
Endloop
推荐
Append lines of int_fligh1 to int_fligh2
8、使用table buffering
Use of buffered tables is recommended to improve the performance considerably The buffer is bypassed while using the following statementsSelectdistinct
Select… for update
Order by, group by, having clause
Joins
Use the Bypass buffer addition to theselectclause in order to explicitly bypass the buffer whileselecting the data
9、 使用FOR ALL Entries
不推荐
Loop at int_cntrySelectsingle from zfligh into int_flighwhere cntry = int_cntry-cntryAppend int_flighEndloop
推荐
Select from zfligh appending table int_fligh
For all entries in int_cntry
Where cntry = int_cntry-cntry
10、正确地使用where语句,使查询能使用索引When a base table has multiple indices, the where clause should be in the order of the index, either a primary or a secondary index
To choose an index, the optimizer checks the field names specified in the where clause and then uses an index that has the same order of the fields One more tip is that if a table begins with MANDT, while an index does not, there is a high possibility that the optimizer might not use that index
11、正确地使用MOVE语句
Instead of using the move-corresponding clause it is advisable to use the move statement instead Attempt should be made to move entire internal table headers in a single shot, rather than moving the fields one by one
12、正确地使用inner joinLet us take an example of 2 tables, zairln and zflight The table zairln has the field airln, which is the airline code and the field lnnam, which is the name of the airline The table zflight has the field airln, the airline code and other fields which hold the details of the flights that an airline operates
Since these 2 tables a re logically joined by the airln field, it is advisable to use the inner join
Selecta~airln a~lnnam b~fligh b~cntry into table int_airdet
From zairln as a inner join zflight as b on a~airln = b~airln
In order to restrict the data as per theselection criteria, a where clause can be added to the above inner join
13、使用sort by 代替order by
14、避免使用SELECTDISTINCT语句
使用的ABAPSORT + DELETE ADJACENT DUPLICATES 代替
15、内标1批量插入内标2
INSERT LINES OF ITAB1 [FROM N1] [TO N2] INTO [TABLE] ITAB2 [INDEX IDX]
该语句要求两内表对象具有可以相互转换的行结构。如果不指定行数,则整个内表ITAB1被插入ITAB2中。不指定行数时,ITAB1可以为任意内表,ITAB2必须为索引表,但是如果需要指定起始行N1和终止行N2中的任意一个,则两个内表都必须是索引表。如果ITAB2前指定TABLE 附加项,则ITAB2可以是任意类型内表。使用该方式将一个内表插入到另个中的速度比用循环插入可以快20倍。
1、在我的电脑窗口,右击要清理的盘符-“属性”-“清理磁盘”--勾选要删除的文件--确定--是。 2、清除临时文件,开始-运行-输入 %temp% --确定。 3、用优化大师或超级兔子清理注册表和垃圾文件。 4、关闭一些启动程序, 开始-运行-msconfig---启动 ,除杀毒软件、输入法外一般的程序都可以关掉。 5、删除不用的程序软件。 6、整理磁盘碎片--开始 --所有程序--附件--系统工具--磁盘碎片整理程序--选定C--分析--碎片整理。 7、减轻内存负担 ,打开的程序不可太多。如果同时打开的文档过多或者运行的程序过多,就没有足够的内存运行其他程序,要随时关闭不用的程序和窗口。 8、加大物理内存,更换成质量高的内存,合理设置虚拟内存 。 虚拟内存设置方法是: 右击我的电脑-属性--高级--性能设置--高级--虚拟内存更改--在驱动器列表中选选择虚拟内存(页面文件)存放的分区--自定义大小--在“初始大小”和“最大值”中设定数值,然后单击“设置”按钮,最后点击“确定”按钮退出。 9、用优化大师或超级兔子优化电脑。下面是优化启动和关机的方法,因为涉及修改注册表,请有兴趣的朋友慎用。修改前请先行做好备份。首先,打开“系统属性”(在我的电脑上点右键-属性,或者在控制面板里打开“系统”,快捷键win+pause break)点“高级”选项卡,在“启动和故障恢复”区里打开“设置”,去掉“系统启动”区里的两个√,如果是多系统的用户保留“显示 *** 作系统列表的时间”的√。点“编辑”确定启动项的附加属性为 /fastdetect而不要改为nodetect,先不要加 /noguiboot属性,因为后面还要用到guiboot。 接下来这一步很关键,在“系统属性”里打开“硬件”选项卡,打开“设备管理器”,“IDE ATA/ ATAPI 控制器”,双击打开“次要IDE通道”属性,点“高级设置”选项卡,把设备1和2的传送模式改为DMA若可用,设备类型如果可以选择“无”就选为“无”,点确定完成设置,同样的方法设置“主要IDE通道”。 打开注册表(开始-运行-regedit),单击“我的电脑”打开“编辑”菜单的“查找”,输入AutoEndTasks,点“查找下一个”。双击打开找到的结果修改“数值数据”为1。然后在AutoEndTasks的下面可以找到HungAppTimeout,WaitToKillAppTimeout,把“数值数据”设为2000或者更小,在这里顺便也把菜单延迟的时间修改一下,在AutoEndTasks的下面找到MenuShowDelay,数值是以毫秒为单位,如果希望去掉菜单延迟就设为0。 修改后点“编辑”菜单,打开“查找下一个”(快捷键F3),把找到的结果都安装上一步的方法修改。 现在启动和关机的加速都已经完成,重启一下电脑感受一下极速启动的感觉吧,滚动条是不是只转一二圈就OK了。 享受了极速重启的乐趣后我们再进一步加速一下启动的速度,打开“系统属性”- “高级”-“启动和故障恢复”设置,打开“系统启动”区的编辑,在fastdetect的后面加上 /noguiboot,这样在启动的时候就不会再显示滚动条。如果你非常喜欢这个滚动条的显示这一步就不用做了友情提示:注册表修改错误 系统容易崩溃 修改前 请先导出注册表 存放于安全区域 以防不测
以上就是关于Java程序性能优化(3)全部的内容,包括:Java程序性能优化(3)、abap 如何去程序优化的、如何系统优化等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)