MindScape

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  43 随笔 :: 4 文章 :: 44 评论 :: 4 引用

2009年5月20日 #

当GCC以优化方式编译代码的时候,它会执行Dead Code Elimiation(DCE), 就是把那些源代码中定义但是却从未调用到的函数从中间目标文件中去掉.(.o文件)

例如下面这段代码:

#include <stdio.h>

static void test() {

printf ("this code is never called.");

}

int main() {

printf("this is main function.");

return 0;

}

这里我们定义了一个static函数和一个main函数.按照C语言的约定,static 函数是只在当前模块可见, 非static函数则可被其它模块所包含. 

然后我们通过检查使用和不使用DCE时,GCC的汇编输出来观察DCE的作用.

不使用DCE:

gcc -S -fno-builtin -fdump-ipa-cgraph test.c  -o test.S

这里生成汇编结果说明了DCE的过程是在编译阶段已经完成, 命令中

-fdump-ipa-cgraph, 这是个调试输出选项,会生成一个.cgraph文件,我们后面会进一步查看这个文件.

查看test.S可以发现_test这个函数的定义出现在汇编代码中, 


 1     .cstring
 2 LC0:
 3     .ascii "Hello World\12\0"
 4     .text
 5 _test:
 6     pushl   %ebp
 7     movl    %esp, %ebp
 8     subl    $24, %esp
 9     call    L3
10 "L00000000001$pb":
11 L3:
12     popl    %ecx
13     leal    LC0-"L00000000001$pb"(%ecx), %eax
14     movl    %eax, -16(%ebp)
15     leave
16     ret
17 .globl _main
18 _main:
19     pushl   %ebp
20     movl    %esp, %ebp
21     pushl   %ebx
22     subl    $20, %esp
23     call    L6
24 "L00000000002$pb":
25 L6:
26     popl    %ebx
27     leal    LC0-"L00000000002$pb"(%ebx), %eax
28     movl    %eax, (%esp)
29     call    L_printf$stub
30     movl    $0, %eax
31     addl    $20, %esp
32     popl    %ebx
33     leave
34     ret
35     .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
36 L_printf$stub:
37     .indirect_symbol _printf
38     hlt ; hlt ; hlt ; hlt ; hlt
39     .subsections_via_symbols
40 
41 

 

如果编译生成.o文件的话,使用nm工具可以看到中间目标文件中的符号定义中也存在test这个函数.

nm test.o

00000017 T _main
              U _printf
00000000 t _test

 

接下来打开DCE开关看看:

gcc -O -S -fno-builtin -fdump-ipa-cgraph test.c -o test.S

test.S

 

 

 可以看到,test函数已经不在了.nm中也不见了_test符号.

00000000 T _main
              U _printf

 

随汇编过程,GCC还会生成一个.cgraph的文件,这里面记录了gcc移除函数过程.


 1 Initial entry points: main
 2 Unit entry points: main
 3 
 4 Initial callgraph:
 5 
 6 main/416 insns needed tree inlinable
 7   called by:
 8   calls: printf/3
 9 printf/3:
10   called by: main/4
11   calls:
12 test/2: tree
13   called by:
14   calls:
15 __sputc/1: tree
16   called by:
17   calls:
18 __swbuf/0:
19   called by:
20   calls:
21 
22 Reclaiming functions: test __sputc
23 
24 Reclaimed callgraph:
25 
26 main/416 insns needed tree inlinable
27   called by:
28   calls: printf/3
29 printf/3:
30   called by: main/4
31   calls:
32 __swbuf/0:
33   called by:
34   calls:
35 
36 Marking local functions:
37 
38 Marked callgraph:
39 
40 main/416 insns needed tree inlinable
41   called by:
42   calls: printf/3
43 printf/3:
44   called by: main/4
45   calls:
46 __swbuf/0:
47   called by:
48   calls:
49 
50 Deciding on inlining.  Starting with 16 insns.
51 
52 Inlining always_inline functions:
53 
54 Deciding on smaller functions:
55 
56 Deciding on functions called once:
57 
58 Reclaiming functions: __swbuf
59 Reclaimed 0 insns
60 Inlined 0 calls, eliminated 0 functions, 16 insns turned to 16 insns.
61 
62 Optimized callgraph:
63 
64 main/416 insns needed tree inlinable
65   called by:
66   calls: printf/3
67 printf/3:
68   called by: main/4
69   calls:
70 
71 Final callgraph:
72 
73 main/416 insns needed inlinable asm_written
74   called by:
75   calls:
76 printf/3:
77   called by:
78   calls: 

 

 

posted @ 2009-05-20 23:59 Jonny Yu 阅读(18) | 评论 (0)编辑

2008年4月20日 #

讲讲我的一些教训吧。
我所参与的应用开发是一款桌面应用程序,为了良好的用户体验,产品设计使用了许多自定义窗口和自绘控件,在最早的需求说明书中,软件的界面的需求只是一些PhotoShop做的截图。大伙儿很快就按照截图做出了界面。但是立刻就被QA组拒收了,因为截图中和我们的开发环境用的都是XP Luna Silver的theme, 而QA组用的是XP Luna blue theme以及Windows 2k, 这样用户界面上有些系统控件的颜色随着theme改变了而有些自绘控件却仍然是银灰色,非常不协调。产品设计,开发都忽略了theme这个细节因素对整体界面风格的影响,大家只好重新讨论实现theme的支持。

另一个,有一个自定义窗口需求里面要求在屏幕左半边的时候边框的滚动条靠左,反之在屏幕右半边的时候滚动条靠右。某位哥们实现的时候直接就按WorkingArea的一半来判断,WorkingAreas是个好东西它还能正确处理Taskbar在侧边的情形。当然这个代码在绝大多数的机器上的确表现良好,包括QA组的测试。结果最后一个Beta客户发现了问题,这个窗口在他的副显示器上工作不正常。天,还有多显示器这回事。。。第二天开发组和QA组就加了几台显示器。



posted @ 2008-04-20 02:11 Jonny Yu 阅读(76) | 评论 (1)编辑

2007年12月16日 #

博主主要谈的是如何优化系统性能

其实我觉得这些技术本身都是很好的,但是一般来说出现性能问题并不是因为缺乏优化的意识和技术,而更多的是由于没有发现的性能瓶颈或者忽视了这个瓶颈的重要性。

对于开发一个长期使用的应用,在其生命周期中会功能会不断的添加和修改,实际运行环境的变化也会导致不同的性能瓶颈产生,因此加入应用服务质量指标的检测的目标是很有必要的。

我觉得架构层次上的性能设计应该首先考虑应用性能的刻度量性,定义明确的性能目标这样可以指导性能优化设计采取适当的优化设计。并且在压力测试中通过性能验证模块验证优化设计是否有效。

posted @ 2007-12-16 23:10 Jonny Yu 阅读(43) | 评论 (0)编辑

如果把技术比作金融资产,那么你会发现经典投资法则依然是那么正确:

1.定期投资:把学习新技术作为一种的习惯,无论投资量多小。

2.多元化投资:学习不同方面的技术,接触面越广机会也会越多。

3.风险管理:不要把所有的技术鸡蛋都放在一个篮子里。

4.低买高卖:锻炼自己的感觉预测新兴技术的流行趋势,当然这很困难而且没有指标可循。

5.周期性的重新评估和平衡资产:不断评估你所在投入研究的技术,分析你需要投资的新技术,放弃研究一些过时的技术。

 

-- 摘自《程序员修炼之道》

posted @ 2007-12-16 23:05 Jonny Yu 阅读(32) | 评论 (0)编辑

2007年7月5日 #

     摘要:  要求:为一个WinForm程序暴露一个COM接口,让其它应用程序能够以COM服务器(LocalServer)方式启动这个程序并且对其进行操作如果发现已经在运行的应用程序,则直接重用当前运行的应用程序进行操作。分析:根据要求,分解具体需要解决的技术问题如下:在WinForm程序中定义一个COM visible接口并实现。将这个Winform程序变为COM服务器(LocalServer)。... 阅读全文
posted @ 2007-07-05 22:41 Jonny Yu 阅读(2052) | 评论 (4)编辑

2007年5月27日 #

WinForm应用里经常会使用一些自绘的非标准窗口来改善软件的观感,由于不再使用标准窗口的标题来和边框,那么窗口的Move和Resize的功能就需要自己来实现。在我写这个功能的时候是直接在OnMouseMove中进行Location和Size的改变。这种使用这种方式后发现在Resize和Move的时候CPU占用率有时会到100%,因为MouseMove消息的产生频率非常高,基本上鼠标每移动一个像素位置都会发出一个MouseMove消息,由于我是在MouseMove中进行Resize,那么Resize的频率也会很频繁,这在一些简单的窗口中(控件少,自绘逻辑简单)的窗口中可能问题不大,但是对于一些较复杂的窗口来说,频繁的Repaint和layout的代价是巨大的。

后来尝试在Idle Event中进行Resize这样,经过一些实验发现Idle event的触发频率比MouseMove少40%,而效果却保持不变。更好的是Idle event是根据应用程序是否空闲来决定其发生频率的,这样在系统繁忙的时候,窗口resize的反应慢一点也是可以接受的,这样可以把更多的CPU资源用于需要的计算中。

这只算记个笔记备忘吧,如果有做过自绘窗口的resize功能的欢迎一起交流讨论。:)

posted @ 2007-05-27 13:15 Jonny Yu 阅读(241) | 评论 (1)编辑

2006年9月8日 #

i.e.和 e.g.这两个缩写在英语中用的很多,都是表示举例说明的意思。
但是同是举例,可是意思却是不同的。

e.g.仅仅列举一部分情况
例如:

The default item (e.g. the first item in the row) .....

这样的话是:缺省项(例如每行的第一项)....


i.e.列举了所有情况
例如:
把前面句子中e.g.改成i.e.

The default item (i.e. the first item in the row) .....

这里的确切意思就是:缺省项(即每行第一项)....

这里缺省项其实已经不是一个简单的举例说明而是定义了,大家读英文文档的时候一定要小心。


www.basic-learning.com/wbwt/tip116.htm
posted @ 2006-09-08 13:28 Jonny Yu 阅读(122) | 评论 (0)编辑

2005年12月4日 #

How can I hide a user from the Welcome Screen in Windows XP?

To hide a user's account from the welcome screen in Windows XP:

  1. Open Registry Editor.

  2. In Registry Editor, navigate to the following registry key:

  1. Create the following entry:

Username: REG_DWORD

(Where Username is the username of the user you want to hide from the Welcome Screen).

  1. Assign a value of 0.

  2. Close Registry Editor.

  3. Reboot.

This will prevent the user from showing up on the welcome screen. You will need to press CTRL-ALT-DEL twice at the logon screen to get the old W2K logon style box to be able to logon to the account you've hidden. Adding a username and setting the value to 1 will cause that user, such as Administrator, to show up on the Welcome screen as well.

posted @ 2005-12-04 23:26 Jonny Yu 阅读(259) | 评论 (0)编辑

2005年8月24日 #

在Window上主要有三种方法得到Client Area的一个HDC句柄。
1.在WM_PAINT消息中调用 BeginPaint()方法,BeginPaint方法返回一个当前无效区域的HDC句柄,并把该无效区域设置为有效区域。所谓无效区域就是需要应用程序重新绘制的区域,反之则为有效区域。BeginPaint被调用时同时返回了一个PAINTSTRUCT结构,其中给出了本次重绘的Clip Rectangle,所有在这个rectangle之外的绘制操作都不会显示。值得注意的是Petzold在砖头里面反复强调在WM_PAINT消息处理函数中BeginPaint方法需要和EndPaint方法配对使用,还有BeginPaint中返回的HDC不能缓存起来使用。
2.调用GetDC(hwnd)/ReleaseDC()来获取释放对应Client Rectangle的HDC句柄, 这个句柄没有什么预定义的Clip rectangle, 整个Client Rectangle都可以绘制。但是GetDC()得到的句柄也同样不能缓存起来,也就是说GetDC和ReleaseDC函数要在一个消息处理函数中配对出现。
一个类似的API是GetWindowDC(),它用于获取整个Window的DC,(client area + non-client area)
和GetDC一样必须在一次WndProc执行中释放掉,不能缓存。

3.调用CreateDC方法。。。还没看到,以后再写。

posted @ 2005-08-24 00:51 Jonny Yu 阅读(491) | 评论 (2)编辑

2005年8月23日 #

Wndows中Window Management 的设计
是很符合OO思想。

首先每个Window的定义由WNDCLASS结构定义。在WNDCLASS中我们需要给出
Window class name, Window的class style, 以及Wndow Procedure,WNDCLASS还提供了申请
extra class bytes 和extra window byte的能力。这两个空间可以类比的理解为class static fields和
object fields。和一般的class定义一样,WNDCLASS结构定义了Window对象的状态和行为。
这样凡是同类的Window不论它的位置,大小以及窗口属性如何都可以使用同一个WNDCLASS.
而对于行为有所不同的Window我们亦可以通过Sub-classing的方式通过改变其中一些消息
的行为得到所需的效果,这个方式事实上等同于override virtual method了,当然还有super-classing的说法。
每一个WNDCLASS在使用之前必须先注册到Win32 User Module中,随后用户即可使用CreateWindow创建Window实例了,值得注意的是在CreateWindow是我们并不是获取该WNDCLASS结构的指针来说明所使用的WNDCLASS的,而是通过Window class name, 如果将这些API在C#里面重写一下就可以看到一个很熟悉的设计。
class WindowManager
{
     public static void RegisterWindowClass(WindowClass wc);
     public static IWindow CreateWindow(string windowClassName, CreateWindowParameters params);
     //...
}
没错,Factory method, 事实上我们也正是靠这个方式重用了Common Controls.
这里我将返回的HWND写成IWindow接口,因为我觉得hwnd对于一系列Window function就如同this指针对于成员方法一般。hwnd应该被认为是C函数中的this指针,而不是Window对象的私有数据成员,事实上Window对象的数据封装做的非常到位,没有暴露出一个内部数据结构。
思路断掉了,以后再写。。。
posted @ 2005-08-23 00:48 Jonny Yu 阅读(305) | 评论 (0)编辑