Review: Delphi 2007 for Win32 (Beta) - part one and part two (翻译) ( 积分: 0 )

  • 主题发起人 主题发起人 monkeyking1983
  • 开始时间 开始时间
M

monkeyking1983

Unregistered / Unconfirmed
GUEST, unregistred user!
这两天上班的时候翻译了这东西,还差最后一篇。先贴出来给大家看看。

Delphi2007 for Win32 Beta 评论 Part One
From Hallvard's Blog

http://hallvards.blogspot.com/2007/03/review-delphi-2007-for-win32-beta-part.html
翻译:monkeyking(www.cnblogs.com/monkeyking)
转载请注明出处。翻译匆忙,如有不妥之处请留言共同探讨。



CodeGear的Nick Hodges联系我,并给我一个授权,允许我讨论一下即将发布的Delphi2007 for Win32(产品代号为Spacely)。需要注意的是,以下评论都是基于2月中旬的预发布Beta版本 Build 2063,所以如遇变化请以正式发布的版本为准。



安装程序


下面的几张截图为大家呈现了新安装程序的外观。安装程序是由InstalAware(Delphi2007中已捆绑此工具)制作的,它应该使得CodeGear能以更加容易和更加集成的方式发布补丁和新版本。

http://vassbotn.googlepages.com/SpacelyInstaller1.PNG
http://vassbotn.googlepages.com/SpacelyInstaller2.PNG
http://vassbotn.googlepages.com/SpacelyInstaller3.PNG





Delphi2007是一个non-breaking版本



啥叫“Delphi2007是一个non-breaking版本”?很奇怪吧!根据CodeGear的路线图,今年的晚些时候会有一个代号为Highlander的新版本BDS(或者应该叫CDS了)出现。为了减少由于一年之内至少出现两个新版本的Delphi而带来的麻烦(对于开发者,第三方组件厂商等),CodeGear决定发布一个non-breaking版本的Delphi2007。这就意味着你可以使用BDS2006或者Turbo Delphi2006中的代码和组件,而不需要重新编译任何.dcu(Delphi Compiled Unit)文件。因此,即使某个组件是以dcu文件的形式发布的,它仍能够正常工作。

(译者注:其后,我将non-breaking称之为“无缝”)





Delphi2007与BDS2006和Turbo Delphi 2006之间的无缝过渡很特殊,这意味着在.dcu层面上的二进制数据,Delphi2007对后两者具有兼容性,单元文件的interface部分也不存在因版本变化而带来的变化。所以你不需要修改任何已存在的类或者例程。请注意,Delphi单元文件的Interface部分所进行的检查,是允许你添加新类和标识的。(译者注:这个是指在编译代码时,编译器对interface部分的检查。当代码所引用的单元中出现了新的内容,比如一个新声明的类或者新的变量,此次检查仍能顺利通过,只要被引用代码所使用的变量或者代码没有变动即可。参照下面一段会有更加准确的理解)





这种方法带来的一个副作用就是它易于修改RTL和VCL的Bug(只需在实现部分中做修改即可),也能很方便的声明一个新类或者新组件,但是你却很难为一个已经存在的类声明新功能,方法或者属性。尽管“困难”,但也不是无法做到。比如CodeGear 就已经使用了几个小技巧(原文为hack)在TForm类中实现对Vista Glass效果的原生支持。Allen Bauer已经公开了这个事情,并且说了他是如何实现的。在后面的评论中,我们将会与Delphi2007(相对于BDS2006)的RTL和VCL新变化有更亲密的接触。



编译器有哪些新变化?





实际上,如果编译器有新变化,就有可能造成二进制数据层面上的不兼容性,所以普通意义上更新并不存在。不过,一些调查显示编译器确实有改进之处。例如,大量新的编译器提示,警告和错误信息。看起来就好象编译器已经有了XML文档生成功能。其中一部分新的错误消息能够有效帮助错误的修正。代码能够更早的生成内部错误,并有详细的编译时错误说明,用于解释代码究竟错在哪。下面就有一些新提示,警告和错误的例子。



New Hints:



H2445 Inline function '%s' has not been expanded because its unit '%s' is specified in USES statement of IMPLEMENTATION section and current function is inline function or being inline function

H2451 Narrowing given WideChar constant (#$%04X) to AnsiChar lost information

H2456 Inline function '%s' has not been expanded because contained unit '%s' uses compiling unit '%s'



New Warnings:



W1055 PUBLISHED caused RTTI ($M+) to be added to type '%s'

W1201 XML comment on '%s' has badly formed XML -- 'Whitespace is not allowed at this location.'

W1202 XML comment on '%s' has badly formed XML -- 'Reference to undefined entity '%s'.'

W1203 XML comment on '%s' has badly formed XML -- 'A name was started with an invalid character.'

W1204 XML comment on '%s' has badly formed XML -- 'A name contained an invalid character.'

W1205 XML comment on '%s' has badly formed XML -- 'The character '%c' was expected.'

W1206 XML comment on '%s' has cref attribute '%s' that could not be resolved

W1207 XML comment on '%s' has a param tag for '%s', but there is no parameter by that name

W1208 Parameter '%s' has no matching param tag in the XML comment for '%s' (but other parameters do)



New Errors:



E2447 Duplicate symbol '%s' defined in namespace '%s' by '%s' and '%s'

E2448 An attribute argument must be a constant expression, typeof expression or array constructor

E2449 Inlined nested routine '%s' cannot access outer scope variable '%s'

E2450 There is no overloaded version of array property '%s' that can be used with these arguments



Linker errors:



F2446 Unit '%s' is compiled with unit '%s' in '%s' but different version '%s' found



IDE的变化





新的IDE感觉很快,也易于使用。很显著得例子是在调试窗口和设计窗口切换时也很少有闪烁现象。



下面两张截图显示了IDE上的一些新内容。

http://vassbotn.googlepages.com/SpacelyIDE1.PNG


我已将变化之处编号:



1.我添加了一个工具条按钮,用于名为Notify on Language Exceptions的调试器设置。

2.TForm的新属性GlassFrame,用于控制Form的Vista Glass效果。它巧妙的使用了class helper,property injector和其他额外技术(hack)来实现的。

3.Tool Palette部分修改了搜索机制。只要组件的名字中包含了你输入的字符串,它们都会被显示在列表中。例如输入“but”,所有按钮组件都会显示出来。很棒!



这是另外一张屏幕截图。

http://vassbotn.googlepages.com/SpacelyIDE2.PNG


1.新的文件浏览器窗口极其顺手。它就像一个迷你版的浏览器(explorer),大大减少我们对外部浏览器或者使用文件菜单的需求。同时,这个窗口也能停靠在任何位置或者处于浮动状态。当你不需要使用时,点击图钉按钮,窗口就会自动划出屏幕。



2.这是当前工程的编译器选项窗口。编译器警告,链接器和目录/编译条件现在都能为发行版本和调试版本单独设置。



3.在这里你可以看到新的编译器警告。它在外部单独停靠。



4.我添加了一个Vista上专用的组件TFileOpenDialog,此时编译器给我一个有关于使用平台方面的警告。不错!

Review: Delphi 2007 for Win32 (Beta) - part two

Review: Delphi 2007 for Win32 (Beta) - part two
编译器的新变化



From Hallvard's Blog

http://hallvards.blogspot.com/2007/03/review-delphi-2007-for-win32-beta-part_06.html
翻译:monkeyking(www.cnblogs.com/monkeyking)
转载请注明出处。翻译匆忙,如有不妥之处请留言共同探讨。

新的published和$M+对比

新的编译器警告“W1055 PUBLISHED caused RTTI ($M+) to be added to type '%s'”非常有趣。它解决了我们之前讨论过的一个问题。在以前的编译器版本中,如果你编写这样的代码:

type
TMyClass = class
private
FName: string;
published
property Name: string read FName write FName;
end;



published属性不会产生RTTI ,它在后台被默认当作public属性来对待。这主要是因为TmyClass不是从一个使用了$M+编译指示字的类继承下来(比如TPersistent),它自己内部也没有使用$M+。现在,当你在Delphi2007里编译相同的代码时你会得到这样的警告:

[DCC Warning] ThSort.pas(13): W1055 PUBLISHED caused RTTI ($M+) to be added to type 'TMyClass'



这说明,尽管$M+被漏掉了,但是编译器仍然会将它作为标准published属性来处理,并为它产生RTTI。在类声明前面添加一个$M+指示字,就不会再有这个警告了。如果你只是想使用一个Public属性,那么就把published改成public好了。

$DYNAMICBASE 和 ASLR

编译器现在接受一个新的编译指示字——$DYNAMICBASE ON/OFF,它对应的命令行参数为“-dynamicbase”。它相当于已经存在的编译指示字$SetPEOptFlags的一个快捷方式。$DYNAMICBASE ON等同于$SetPEOptFlags $40,$40在Windows中的定义为:

const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = $0040;
// The DLL can be relocated at load time.



SetPEOptFlags指示字将在PE头中重开辟一个DllCharacteristics字段。它被用于Windows的装载程序确定某个被装载模块(比如DLL或者BPL)的大小。$40在Windows Vista中有特殊的意义,它将使用一个名为“随机地址空间分布(Address Space Layout Randomization,ASLR)”的特性。使用该特性后,OS会在装载模块时适当的随机偏移一定的地址(实际上偏移地址大致在0-255之间)以取代现在的这种精确装载于某个镜像基地址上的做法。这样做的主要目的是为了安全和抵御黑客针对DLL代码进行缓冲区溢出攻击。下面的链接讲解了更多关于这方面的知识http://blogs.msdn.com/michael_howard/archive/2006/05/26/address-space-layout-randomization-in-windows-vista.aspx



-description的命令行选项



编译器同样有一个新的命令行选项“-description:<string>”,它对应与$DESCRIPTION编译指示字。用于在PE头中设定模块描述入口。



RTL中有什么新内容?



运行时库(RTL)包含了Delphi系统中所有编译器层面之上的最底层的构建模块。SysInit和System单元与编译器和链接器的内部紧紧捆绑着。当包(package)被使用时,SysInit被编译到每一个模块中(Exe和包文件BPL),System单元仅仅被编译到rtl100.bpl中。这就是为什么它们会被分离为两个单元文件。



这是个基本的背景知识。那么现在,到底有什么新变化呢?事实上,SysInit并没有变化。我猜测这说明SysInit单元很稳定,不需要任何修改。这可是个好消息。接下来我们深入分析一下System单元所作的改变。



System单元的变化



有一个名字非常好记的全局布尔变量出现——NeverSleepOnMMThreadContention。System.pas单元的实现部分引用了一个getmem.inc文件,该文件使用了新的内存管理器FastMM进行内存管理,而这个变量正式作用于它的。下面这段注释与变量一同出现:



{Set this variable to true to employ a "busy waiting" loop instead of putting the thread to sleep if a thread contention occurs inside the memory manager. This may improve performance on multi-CPU systems with a relatively low thread count, but will hurt performance otherwise.}
NeverSleepOnMMThreadContention: Boolean;



当FastMM需要保护共享资源时,它会使用轻量级的原语操作(例如汇编指令lock cmpxchg)替代重型的OS级别的临界对象API。如果遇到冲突(某个资源已经被其他线程锁定),它通常会进入休眠状态,释放CPU控制权,并允许其他线程完成自己的工作和释放该资源锁。



如同上面的注释中所提到的,在一些多CPU的机器上(这正在变为主流),采用在循环中不停的检查某个“锁”是否可用(也可称作spin-lock)的方法,等待另外一个CPU执行完线程并释放“锁”时,会更加有效率。我们一起来看看这个逻辑的Pascal代码:



while LockCmpxchg(0, 1, @MediumBlocksLocked) <> 0 do
begin
if not NeverSleepOnMMThreadContention then
begin
Sleep(InitialSleepTime);
if LockCmpxchg(0, 1, @MediumBlocksLocked) = 0 then
break;
Sleep(AdditionalSleepTime);
end;
end;



另外一个改进是关于spin-lock的汇编版本(默认情况下使用该版本)。它使用了pause x86指令,以便更好的兼容处理器和操作系统。

asm
//...
{The pause instruction improves spinlock performance}
pause
//...
end;



此外,通过对一些汇编代码采用类似method-extract重构方法(重新分配大内存块的逻辑已经被重构到ReallocateLargeBlock例程的内部了),FastMM的代码体积好像略有减少(我没有仔细计算过)。

这时,看起来它对大片段内存块的支持逻辑是有所改进的。Pierre在代码里做了以下注释:

{Is this large block segmented? I.e. is it actually built up from more than one chunk allocated through VirtualAlloc? (Only used by large blocks.)}



已优化过的RTL代码

正如Steve Threfethen在博客中写的那样,RTL已经包含了一些新的更新并用一些FastCode中代码替换原有的功能。当你比较字符串时,编译器魔法中System单元的例程 _LStrCmp 将被使用,这会成为代码性能至关重要的一环。Pierre le Richie为这个例程编写了一个新的更快的版本(依据FastCode大赛中CompareStr挑战赛的获胜代码编写),并提交到Quality Central中,编号为 #31328。该代码已经集合到RTL中。



_LStrCmp是进行字符串比较时都要用到的例程,包括字符串操作符>,>=,=,<>,<和<=。在Pierre的QC报告里,他建议修改编译器以便于调用不同的具有针对性的函数(_LStrEqual)。多数情况下,它只需要对比字符串的长度即可得知结果。但是这样的修改会影响二进制文件.dcu的兼容性,所以这项建议没有包含在Spacely中,但是很有可能应用于Highlander(Highlander或许会成为BDS2007)。

其他来源于FastCode的代码应用于SysUtils单元。BDS2006中,UpperCase和LowerCase都已经使用来源于FastCode的代码了(作者:Aleksandr Sharahov)。而在Delphi2007里,John O'Harrow又为它们开发了更快的版本。此外CompareStr和StrLen也使用了由Pierre le Riche编写的高效代码。

另外,FileAge和FileSearch函数也被优化。FileAge函数现在使用更加有效率的API GetFileAttributesExA (如果该API能够使用)替代原有的FindFirst/FindClose。如果FileSearch的Name参数为空值,它也会直接返回。这两个变化有助于改进编译器和链接器的速度。



最后,CheckForDuplicateUnits中使用了哈希表的逻辑思想,在装载包(package)时有更多的优化效果。这段代码在BDS2006中有很大的改进,但是现在,它会更快。当应用程序在启动时需要动态装载许多包时,它有助于缩短启动时间(比如Delphi IDE)。

桌面窗口管理器API

DwmAPI单元是一个新出现的单元,它由Vista的DWMAPI.DLL导出。在其他平台上,这些代码会返回错误代码E_NOTIMPL。本单元中的所有常量和代码都是Delphi IDE和VCL中新添加进来的有关Vista新功能和Glass特殊效果的基础。比如里面就有这些例程DwmExtendFrameIntoClientArea 和DwmUpdateThumbnailProperties,大多数情况下VCL已经屏蔽了我们直接使用这些基本例程的需求,但我们还是应该知道在哪找到它们。

Math单元和完整的布尔值计算(complete boolean evaluation)

Math单元里的三个InRange函数(重载的Integer,Int64和Double版本)有两个很有趣的变化。主要是代码的布置从(BDS2006版本):

function InRange(const AValue, AMin, AMax: Integer): Boolean;
begin
Result := (AValue >= AMin) and (AValue <= AMax);
end;



变成了(Delphi2007版本):

function InRange(const AValue, AMin, AMax: Integer): Boolean;
var
A,B: Boolean;
begin
A := (AValue >= AMin);
B := (AValue <= AMax);
Result := B and A;
end;



代码的变化,迫使编译器在设置Result变量前,计算出所有布尔表达式的值。这可以减少指令的条件判断后跳转(conditional jump)次数,以优化执行性能(一个明显的例子,如果Inrange返回True,它都需要计算出所有表达式)。编译出来的代码的不同之处可以参照下面(这是由BDS2006产生的汇编代码):

Result := (AValue >= AMin) and (AValue <= AMax);
//0040841C 3BD0 cmp edx,eax
//0040841E 7F04 jnle $00408424
//00408420 3BC8 cmp ecx,eax
//00408422 7D03 jnl $00408426
//00408424 33C0 xor eax,eax
//00408426 C3 ret



新版本函数的汇编代码如下:

A := (AValue >= AMin);
//0040842C 3BD0 cmp edx,eax
//0040842E 0F9EC2 setle dl
B := (AValue <= AMax);
//00408431 3BC8 cmp ecx,eax
//00408433 0F9DC0 setnl al
Result := B and A;
//00408436 22C2 and al,dl
end;
//00408438 C3 ret



如你所见,第二段代码没有任何分支,而第一段代码由两个条件分支指令。现在处理器在无分支代码上能工作的更有效率,所以第二段代码的实际效果更好。也许某天我们会再遇到这个问题,此时还有另外一种方法来解决它——使用 $B+ 编译指示字。它会命令编译器完整的计算布尔值。



评论的第二部分到此结束,第三部分即将发布。
 
好东西,顶一下,原文我也看了,只不过没翻译,哈哈。谢谢楼主的无私奉献。期待后面继续的文章。
 
其实很伤感的。一直在说,DelphiBBS沉沦了。但是却不愿意面对。
这一次,自己发表文章,再次让我面对冷冰冰的现实 。就像从前讨论的那样,越来越多上DelphiBBS的人抱着强烈的目的性,他们只想快速知道答案,而不愿意探索技术。

如果是从前,我想这篇帖子应该能引起热烈讨论。而现在,仅仅浏览20次,就沉下去啦。
感谢楼上的回复。不过我也不打算再发表第三篇了。
 
楼主不要伤感,我们不应放弃DFW,任何事物的发展必然有个起伏过程,DFW的命运并不掌握在任何人手上,但又是掌握在每个人的手上,如果我们放弃它,那它也许就真的沉沦了。

其实DFW上充斥着查查帮助,搜搜离线数据库,用用google就能找到答案的问题已经有很长一段时间了。对待这样的问题,如果没人回答,提问者会“抱怨”大富翁已经没有高手且认为大富翁水平下滑。这并不是DFW的错,我们也不可能苛求别人不发出这样的提问。况且这样的现象也不仅仅是DFW独有的,稍微留心一下国外的BBS,讨论组,新闻组,也会发现同样的现象。其实这也好比是一个市场,有低端用户群就有高端用户群,整齐划一的情况是不会出现的。

与其抱怨它,不如坦然一点的面对它。DFW既属于所有人,也属于每个人自己,当我们把它当作自己的一部分看待的时候,就更不应该放弃它,兄弟说对吗?

这里我倒是有个建议提供给DFW坛主,是不是可以模仿一下现在博客的圈子形式,增加一些小团体组织,让大家可以在这里找到兴趣相投、志同道合的朋友一起研究技术呢?
 
看来codegear果然出了一个类似D2006 SP补丁的稳定版本,没有让大家失望(每次升级都是提心吊胆,这次不一样了,呵呵)
支持楼主一下!
 
呵呵,zqw0117说的既是。正所谓爱之深恨之切。我从高中开始就经常上DelphiBBS,虽然那个时候没有真正去理解Delphi。但是这么多年,也陪伴我成长起来了。这么一块阵地又如何想它丢失呢。常说铁打的营盘流水的兵。老兵已走,新兵的补充又有些断档,怎能不着急。
怀着希望,然后let it be...
 
我也是很早以前认识DFW的,当时还没有上网,买了个教学光盘,里面有许多Delphi的第三方控件和DFW离线数据库,从那里面看到了99年的DFW,上面的帖子几乎每个都质量很高,讨论也非常积极,技术性学术性也很强。虽然当时的我并不能看懂那么多帖子讲到的技术知识,但DFW的讨论气氛却是对我最大的吸引。后来上网后,就立刻来DFW注册了!

记得很早的离线数据库中,我印象最深的是这里的斑竹和几个大侠一起讨论怎么养乌龟的帖子,哈哈,不知道现在还找得到不?
 
谢谢楼主
 
顶,大富翁论坛 功能比较简单,管理员又少,所以帖子沉的快。

即使DELPHI有无数的缺点,我不会抱怨他,我首先感觉到是自己需要再努力。
 
顶,相当的好啊
太好了
Delphi2007感觉真的不错啊,希望Borland不会让我们失望啊
 
我们很多人都在用老版本的Delphi,那些都是已很熟悉的功能,我们没有更换开发工具是因为在我们现有的工作当中Delphi还是最好的最熟悉的开发工具。
我想很多人和我一样都在观注着Delphi2007吧,毕竟之前的几个版本没有让大家感到更多的兴奋和自豪,这需要有升温的时间的。当Delphi成为又一次的明星时大家的注意力会会回来的。在次谢谢楼主。
 
不知道2007有没有Twinsocket的组件,
 
说说Delphi 7以后版本的几个让人觉得很不舒服的地方:
一、IDE界面布局变化太大,现有的使用者要使用得改变自己的使用习惯,如果高低版本同时用,那么两种操作习惯都得用,不晕才怪;中间代码编辑窗口太窄,一行的代码写的稍微长一点就看不到(必须滚屏)了;我就有过一次查找Bug的痛苦经历:当时客户要求马上得改好,而代码是别人留下来的,找来找去没有问题,最后在超出屏幕的部分找到了Bug。

二、必须安装.NET:我想大概很多人都和我一样经历过一次麻烦的安装后就再也不想来第二次了。

三、跨平台方面:那个kylix已经好久没有更新过了,在一些新的Linux上安装会很麻烦,要去搞定一个个的安装问题;Delphi已经到了11版了吧,kylix还停留在3(相当于D6.9)版;启动很慢,给人的印象不好,如果不是使用wine模拟而是一个“原生”的kilix多好啊。。。
如果你想跨平台,不想用B/S模式而是使用Web Service等本来用kylix是一个很好的选择,不知道为什么Kylix不更新了?

四、价格太高:想当年的Turbo pascal以几十美元的价格风靡一时,现在的高价策略只能是造就一大堆盗版用户;即使没有盗版也是曲高和寡啊,没有大量的用户群这个产品还怎么生存和发展?大概Delphi的现状就是这个样子?
 
强啊,E文厉害!佩服
 
Piao?
你不会是XB吧?呵呵。
 
后退
顶部