自己涂鸦

http://yingbo.donews.net/yingbo/posts/14868.aspx 从一段话谈起(编译优化相关)

这是Inside the Intel Compiler中的一段话,从事编译优化的人应该非常熟悉,但是如何把这段话更清楚地解释给初学者:)。我try一下。(最近一直在思考如何更清楚的解释问题。)

 

Decreasing the number of instructions that are dynamically executed and replacing instructions with faster equivalents are perhaps the two most obvious ways to improve performance. Many traditional compiler optimizations fall into this category: copy and constant propagation, redundant expression elimination, dead code elimination, peephole optimizations, function inlining, tail recursion elimination and so forth.

(未完成 ……)

2004年4月27日 0:36

评论

# 回复: 从一段话谈起(编译优化相关) 2004-4-27 1:31 张锟

两种最明显的改进程序性能的方法应该是:1.减少动态执行的代码数量;2.用快速的等价指令代替慢速指令。
许多种传统的编译器优化方式都可以归结于这两种方法,比如说:copy and constant propagation(用常数取代程序中不变化的变量), 冗余表达式消去,死代码消去,Peephole优化(不知道),Inline函数,尾部递归消去(展开在程序尾部的递归,减少堆栈消耗)

# 回复: 从一段话谈起(编译优化相关) 2004-4-27 8:57 Yingbo

谢谢张锟 。本来我打算白天完成这些工作,这下省了:)。
peephole optimizations一般翻译成窥孔优化,就是在一个小的指令序列内进行优化,用更短更快的指令序列来代替原有的指令序列。

http://java.mblogger.cn/wuyu/posts/1552.aspx

急用,google半天终于找出来的一个命令

今天服务器上连接太多,netstat -an出来狂滚屏,想知道究竟有多少个1521端口的连接,总不能加more以后一行一行的数吧?印象中记得王坚是netstat -an|grep 1521|xxxx的用法,怎么都想不起来xxxx是什么,在QQ上问半天,最后差点想打电话吵王坚同志去:)

硬着头皮乱凑了组关键字“linux grep 统计 数目”,碰运气似的在结果里面翻,还真让我翻到了,哈哈!

cat sample.text | grep "High" | wc -l

这个管道将把 cat 命令(列出一个文件的内容)的输出送给grep命令。
grep 命令在输入里查找单词 High,grep命令的输出则是所有包含单词 High的
行,这个输出又被送给 wc命令。带 -l选项的 wc命令将统计输入里的行数。

嘿嘿,这下子,要解决俺的问题就是

netstat -an|grep 1521|wc -l

 

2004年3月16日 22:00

评论

# 回复: 急用,google半天终于找出来的一个命令

老兄 wc 是 unix里经常使用的指令啊。
我通常用他来计算所有代码的行数。

wc `find . -name "*.c"`
在最后一行wc会给出总数

``很值得学习!





2004-5-4 3:23   by 张锟--
http://yulchina.donews.net/yulchina/posts/22456.aspx
这几天一直在考虑一个问题,就是我在JSP里写一个scope为session的JavaBean,但是,不知道怎么在其它页面获得那个JavaBean里的值啊?前些日子一直都用的是scope="request"|"page",觉得很容易理解。可是最近为了解决跟踪系统里用户登陆后,跟踪用户行为的功能,就想到采用会话了,可是现在又不得方法。郁闷ING。。。查了很多的书,也没找到合适的解释。飞思的书难怪被骂,〈〈JSP应用详解〉〉真是垃圾!还有脸说是详解,里面的概念都是一笔带过,能学什么?!不过骂完以后,还是要反思一下。其实,能把书写出来,就一定有它优秀的地方。我太浮躁啦!我的心太急了!不过,我也没办法啊,问了几个大论坛,几个专业的群,都没有人知道这个问题的合理解释。哎~~~出书的只为赚钱,工作的只为完成任务,在校的只为考试及格,55555……真痛苦!难道就找不到答案了吗?必须尽快解决这个问题。
假如在JSP里直接对session对象进行操作的话,就违背了MVC的思想了。问题虽然可以得到解决,但是也太让人不舒服了。现在不能为了解决问题而解决问题,要找到解决问题最优的方法才好,至少是我知道的几个方法里最好的方法也好啊!再不能因为取得小小成绩而沾沾自喜,要时刻发现更优的东西来。很多的前辈都说过“如果什么时候有时间,再写这个产品,一定会让代码简单许多”的话,可见每样东西的潜力都是很大的,必须深深的挖掘。
我的基础是差,但是并不说明我就不能把代码写好。计算机领域太宽广了,仅仅一个小小方面都应该用博大精深来形容!我必须多和朋友们交流思想,靠我自己的能力是不可能成为高手的。呵呵,好象跑题了。算了,谁让我没找到答案呢。等找到答案了再整理一篇完整的出来。
2004年5月26日 11:45
评论
  • # 回复: JSP调用JavaBean的scope属性设置时有很大的疑问
    张锟
    2004-5-26 13:07
    简单点说:

    HttpSession session = request.getSession(true);
    YourBean ybean = (YourBean )session.getValue("beanid");

    就能够取到你的JavaBean了。



    ============详细信息==================
    http://www.jguru.com/faq/view.jsp?EID=53309



    <jsp:useBean class="foo.Counter" scope="application" />
    In this example, when the Counter bean is instantiated, it is placed within the servlet context, and can be accessed by any JSP or servlet that belongs to the application (i.e. belongs to the same servlet context).

    The servlet equivalent of the above useBean action is:


    foo.Counter counter = (foo.Counter)getServletContext().getAttribute("counter");
    if (counter == null) {
    counter = new foo.Counter();
    getServletContext().setAttribute("counter", counter);
    }


    ----------------------------------------------------------------------

    <jsp:useBean id="counter" class="foo.Counter" scope="session" />
    In this example, when the Counter bean is instantiated, it is placed within the current session, and can be accessed by any JSP or servlet during a subsequent request by the current user.

    The servlet equivalent of the above useBean action is:


    HttpSession session = request.getSession(true);
    foo.Counter counter = (foo.Counter)session.getValue("counter");
    if (counter == null) {
    counter = new foo.Counter();
    session.putValue("counter", counter);
    }


    ----------------------------------------------------------------------

    <jsp:useBean id="counter" class="foo.Counter" scope="request" />
    In this example, when the Counter bean is instantiated, it is placed within the current request object, and can be accessed by any JSP or servlet during a the same request; e.g., if a RequestDispatcher is used, or if <jsp:include> or <jsp:forward> sends the request to another servlet or JSP.

    The servlet equivalent of the above useBean action is:


    foo.Counter counter = (foo.Counter)request.getAttribute("counter");
    if (counter == null) {
    counter = new foo.Counter();
    request.setAttribute("counter", counter);
    }


    ----------------------------------------------------------------------

    <jsp:useBean id="counter" class="foo.Counter" scope="page" />
    In this example the Counter bean is instantiated as a local variable inside the JSP method. It is impossible to share a page scope variable with another JSP or Servlet.

    The servlet equivalent of the above useBean action is:


    foo.Counter counter = new foo.Counter();

http://kedy.donews.net/kedy/posts/21032.aspx

听了大马的课让我感觉汗颜

int main(int argc, char* argv[])
{
 int a[5],i;
 for(i=0;i<=5;i++)
 {
  a[i]=0;
 }
 return 0;
}

int main(int argc, char* argv[])
{
 int i,a[5];
 for(i=0;i<=5;i++)
 {
  a[i]=0;
 }
}

这两段代码有什么差别?有什么错误?

以前我从来没有想过,今天晚上听大马讲了以后想到如果让自己去做程序真的是很危险。汗颜ing...想想昨天发上来的那个有关MS研发中心招聘的文章,自己需要走的路太长了。

2004年5月20日 22:41

评论

# 回复: 听了大马的课让我感觉汗颜

1. 下面的没有return
2. 下面的数组越界i[5]不存在

2004-5-20 23:01   by henry3--

# 回复: 听了大马的课让我感觉汗颜

没有return是我没有copy上来。下边的不越界,而是一个死循环。上边的在VC6下编译会出错误。说是非法操作。

2004-5-20 23:25   by kedy--

# 回复: 听了大马的课让我感觉汗颜

这个例子学校的老师也讲过。

2004-5-21 0:04   by 程序状态字--

# 回复: 听了大马的课让我感觉汗颜

在java下应该越界

为什么死循环?

2004-5-21 0:13   by henry3--

# 回复: 听了大马的课让我感觉汗颜

1.这个例子明显是C语言,不会是Java
Java里的 main 一定是 public static void main(String[] args)
另外Java里是没有 char* 这个东西的

2.如果死循环是因为数组越界后将i变量置为0了。

不过这与编译器很有关系,有些环境下变量和数组是由高地址向低地址存放的。有些编译器则会永远将单个变量放置在数组前面(比如Linux下的gcc)

不管怎么说,数据越界是非常严重的错误。

如果你们感兴趣,可以看看下面这个扩展的例子,这个例子会打印出所有变量的地址,检查一下 a[5] 和 i 的地址是否一致
如果一样,越界就会导致死循环了。

int main(int argc, char* argv[])
{
int a[5],i;
printf("addr of i = %X", &i);
for(i=0;i<=5;i++)
{
a[i]=0;
printf("addr of a[%d] = %X", i, &a[i]);
}
return 0;
}

3.给出这个例子的老师,应该说明这与编译器是很有关系的。
int a[5],i;
int i,a[5];
对某些编译器是没有区别的,尤其是现在编译器大多数采用自动优化。
根据变量定义顺序假定变量在运行时的地址顺序是不正确的。
这位老师如果没有强调这一点的话,真是有点误人子弟了。


4.某些编译器可能会发现这一越界并给处警告,有可能无法通过编译。






2004-5-21 4:25   by 张锟--

# 回复: 听了大马的课让我感觉汗颜

TO 张锟:
为什么说不同的编译器会有不同的结果呢?计算机给a[5]和i分配内存的时候是根据编译器的吗?我觉得应该是由计算机自己分配吧。

2004-5-21 11:03   by kedy--

# 回复: 听了大马的课让我感觉汗颜

多数的C/C++编译器都会导致这么个结果,诸位可以试一试。
有关这个问题的详细讨论,大家可以参考《C陷阱与缺陷》这本书中的内容。

2004-5-21 11:18   by 李马--

# 回复: 听了大马的课让我感觉汗颜

嗯,大意了。
好久没写C了。



2004-5-21 21:29   by henry3--

# 回复: 听了大马的课让我感觉汗颜

C 语言源代码 -> 机器可执行代码 的转换是通过编译器完成的。如果你没有学过编译原理,应该看看。编译原理对你会很有帮助的。

我在Linux下用gcc编译这两段程序就没有区别。变量i的地址都在数组a的前面。

在高级语言中,根据变量定义顺序推断变量地址是不对的。

出题的时候,至少应该加上此前提:
“假定编译器根据变量定义顺序分配变量地址”


2004-5-22 1:55   by 张锟--

# 回复: 听了大马的课让我感觉汗颜

仔细看了一下结果:

一点更正, Linux下用gcc编译这两段程序还是有差别的.

int a[5],i;
i的地址: BFFFF7DC
a[0]: BFFFF7E0
a[1]: BFFFF7E4
a[2]: BFFFF7E8
a[3]: BFFFF7EC
a[4]: BFFFF7F0
a[5]: BFFFF7F4
i反而在数组的前面

int i,a[5];
i的地址: BFFFF7FC
a[0]: BFFFF7D0
a[1]: BFFFF7D4
a[2]: BFFFF7D8
a[3]: BFFFF7DC
a[4]: BFFFF7E0
a[5]: BFFFF7E4
i反而在数组的后面,而且a[5]越界也不会覆盖i


不管怎么说,这两段代码的结果是取决于编译器的。

2004-5-22 2:08   by 张锟--

# 回复: 听了大马的课让我感觉汗颜

To Kedy,

在程序运行的时候,这个程序使用的数据段地址是由操作系统分配的。但是程序内部变量的先后顺序是由编译器决定的。

具体细节 可能如下 (汇编已经有很多年没有用了,也许不准确,但是你可以看一个大概)

for(i=0;i<=5;i++)
{
a[i]=0;
}

; ds地址是由操作系统分配的
; 内部绝对地址
; i = 0000
; a[0] = 0004 ... 是由编译器决定的

mov ax, 0
mov ds[0000], ax ; i=0
loop:
mov bx, ax ; ax = i
mul bx, 0004 ;
add bx, 0004 ; 计算 a[i] 的地址
mov ds[bx], 0 ; a[i] = 0
inc ax
mov ds[0000], ax ; i++
cmp ax, 0005
jle loop ; i<=5,继续


编译器完全可以选择另外一种地址分配。






2004-5-22 2:22   by 张锟--

# 回复: 听了大马的课让我感觉汗颜

gcc -S -o test.s test.c
会在test.s中生成汇编语言
(windows平台下的编译器也有此功能)

你有兴趣的话可以研究研究


============= test.c ================

int main(int argc, char* argv[])
{
int a[5],i;

printf("Addr of i = %X\n", &i);

for(i=0;i<=5;i++)
{
a[i]=0;
printf("Addr of a[%d] = %X\n", i, &a[i]);
}
return 0;
}


============= test.s ================

.file "test.c"
.version "01.01"
gcc2_compiled.:
.section .rodata
.LC0:
.string "Addr of i = %X\n"
.LC1:
.string "Addr of a[%d] = %X\n"
.text
.align 4
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $56, %esp
subl $8, %esp
leal -44(%ebp), %eax
pushl %eax
pushl $.LC0
call printf
addl $16, %esp
movl $0, -44(%ebp)
.p2align 2
.L3:
cmpl $5, -44(%ebp)
jle .L6
jmp .L4
.p2align 2
.L6:
movl -44(%ebp), %eax
movl %eax, %eax
leal 0(,%eax,4), %edx
leal -40(%ebp), %eax
movl %eax, %eax
movl $0, (%edx,%eax)
subl $4, %esp
leal -40(%ebp), %edx
movl -44(%ebp), %eax
movl %eax, %eax
sall $2, %eax
leal (%eax,%edx), %eax
pushl %eax
pushl -44(%ebp)
pushl $.LC1
call printf
addl $16, %esp
leal -44(%ebp), %eax
incl (%eax)
jmp .L3
.p2align 2
.L4:
movl $0, %eax
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)"


============= test1.c ================

int main(int argc, char* argv[])
{
int i,a[5];

printf("Addr of i = %X\n", &i);

for(i=0;i<=5;i++)
{
a[i]=0;
printf("Addr of a[%d] = %X\n", i, &a[i]);
}
return 0;
}


============= test1.s ================

.file "test1.c"
.version "01.01"
gcc2_compiled.:
.section .rodata
.LC0:
.string "Addr of i = %X\n"
.LC1:
.string "Addr of a[%d] = %X\n"
.text
.align 4
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $56, %esp
subl $8, %esp
leal -12(%ebp), %eax
pushl %eax
pushl $.LC0
call printf
addl $16, %esp
movl $0, -12(%ebp)
.p2align 2
.L3:
cmpl $5, -12(%ebp)
jle .L6
jmp .L4
.p2align 2
.L6:
movl -12(%ebp), %eax
movl %eax, %eax
leal 0(,%eax,4), %edx
leal -56(%ebp), %eax
movl %eax, %eax
movl $0, (%edx,%eax)
subl $4, %esp
leal -56(%ebp), %edx
movl -12(%ebp), %eax
movl %eax, %eax
sall $2, %eax
leal (%eax,%edx), %eax
pushl %eax
pushl -12(%ebp)
pushl $.LC1
call printf
addl $16, %esp
leal -12(%ebp), %eax
incl (%eax)
jmp .L3
.p2align 2
.L4:
movl $0, %eax
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)"





2004-5-22 2:44   by 张锟--

# 回复: 听了大马的课让我感觉汗颜

谢谢张锟和其他各位。看了这么多回复也让我知道了更多。
谢谢。

2004-5-22 7:23   by kedy--

第1页,共1页