About效率。。。

41 views
Skip to first unread message

怀宇范

unread,
Oct 8, 2007, 11:49:59 PM10/8/07
to pon...@googlegroups.com
第一次发贴,问各位大牛一个关于效率的问题。
都说C++的效率(运行时)比Java、.Net(C#)要高。这种效率主要来自于什么地方(或者说其他一些语言做了写什么事情损失了效率)。比如由于库的封装,调用的函数更高层会损失效率,不停的安全检查也会,还有其他一些什么原因,谢谢指教:)

--
彪悍的人生,不需要解释。

bool ContactMe(person you)
{
    if(you.GoTo("14#344, Tsinghua") && you.Find("范怀宇"))return true;
    if(you.MailTo(" dugu...@gmail.com ") || you.MailTo(" fan...@mails.tsinghua.edu.cn "))return true;
    if(you.PhoneTo("13488810330") || you.PhoneTo("01062778689"))return true;
    if(you.QQTo("120628812") || you.MSNTo(" dugu...@hotmail.com"))return true;
    if(you.NetTo(" www.cnblogs.com/duguguiyu "))return true;

    if(you.DareToKiss("FuRongJJ"))
    {
        cout<<"I 服了 U"<<endl;
        return true;
    }
    if(you.GiveMeTwoTicketsFor("MayDay"))
    {
        cout<<"I love you!"<<endl;
        return true;
    }

    return false;
}

pongba

unread,
Oct 9, 2007, 12:11:54 AM10/9/07
to pon...@googlegroups.com
其实你都说了啊:间接层,语言模型的抽象层次、JIT的开销、GC、range check、other runtime checks... 也就不外乎这些原因了。

另外,C++标准网站上有一个Performance TR,可以看看。

其实我觉得以上这些性能因素会随着并发的普及逐渐变得不那么重要。

有谁做过大型统计的?或者看过有大型统计数据支持的文章的?出来吱一声啊 :P

On 10/9/07, 怀宇范 <dugu...@gmail.com> wrote:
第一次发贴,问各位大牛一个关于效率的问题。
都说C++的效率(运行时)比Java、.Net(C#)要高。这种效率主要来自于什么地方(或者说其他一些语言做了写什么事情损失了效率)。比如由于库的封装,调用的函数更高层会损失效率,不停的安全检查也会,还有其他一些什么原因,谢谢指教:)

--
彪悍的人生,不需要解释。

bool ContactMe(person you)
{
    if(you.GoTo("14#344, Tsinghua") && you.Find("范怀宇"))return true;
    if(you.MailTo(" dugu...@gmail.com ") || you.MailTo (" fan...@mails.tsinghua.edu.cn "))return true;

    if(you.PhoneTo("13488810330") || you.PhoneTo("01062778689"))return true;
    if(you.QQTo("120628812") || you.MSNTo(" dugu...@hotmail.com"))return true;
    if(you.NetTo(" www.cnblogs.com/duguguiyu "))return true;

    if(you.DareToKiss("FuRongJJ"))
    {
        cout<<"I 服了 U"<<endl;
        return true;
    }
    if(you.GiveMeTwoTicketsFor("MayDay"))
    {
        cout<<"I love you!"<<endl;
        return true;
    }

    return false;
}





--
刘未鹏(pongba)|C++的罗浮宫
http://blog.csdn.net/pongba
TopLanguage
http://groups.google.com/group/pongba

red...@gmail.com

unread,
Oct 9, 2007, 12:32:10 AM10/9/07
to pon...@googlegroups.com
我来抛几块Java 的砖

光写一点点简单的测试代码, Java 的性能不比 C++ 差, 但是实际的项目中复杂
了, java 的一些特点才会引起一些性能问题.

runtime range check 这些就不说了, 因为他们带来很多的好处.

Only OO:
Java 没有GP, 编程极度推崇 OO, 大量使用 interface, 这会造成低效, 一个函数
调用, 不仅仅是一个 call/ret语句的问题, 还有参数压栈, 寄存器压栈弹栈等开
销, 同时丢失了表达式重组优化甚至消除机会 (对 C++ 还有临时变量消除机会)
等等不良影响. 同时, 非常 OO & interface 话的代码, 会有一大堆很小的函数,
部分小函数还会有不止一个参数, 对于这种小函数, 参数压栈的代码可能比实际计
算的代码都大(例如 interface 里面的getter, setter), 造成程序 working set
上升, 这对性能也很不利.
这种影响, 在非内层循环, 造成程序 working set 上升对性能的影响可能还比执
行多了几条语句带来的影响大(现在的x86, 空等一个内存字节的到来, CPU 都够时
间执行几十甚至上百条语句了, 我用 TSC 计数器对我的程序进行纳秒级分析优化
的时候, 明显看到等待内存的影响) ; 在循环内层则是直接影响性能.

Java generic 是通过 OO 的类型消除实现的, 和 C++ GP 只有表面相似, 不是一
个东西.

C++ 的 STL 用于 native type 的时候, 效率是非常高的, Java 的容器还要
boxing, unboxing, 损失也很大.

GC:
现代的GC 能够带来比人工分配释放内存更少的总体内存管理消耗时间, 但是 Java
的 GC, 似乎却常常使用大量的内存, 先不管挤占了别的程序或者 OS cache,
buffer 的性能优化机会, 光是使用大量的内存, 造成的大 working set 就会导致
CPU 的 cache 工作不优化, 最终的结果有可能是总体内存管理消耗的时间少了,
但是程序运行却慢了.

C++ 里面几个优秀的 mallloc 库, 不但考虑到尽量重用最近释放的内存块(它们多
半在cache 中还有entry), SMP 环境中, 还能考虑 CPU 亲和性, 这对 CPU 的
cache 有很大的帮助,


其他, 例如 serilazation:
Java 不能直接操作内存, 将对象送到网络, 文件, 数据库, 或者从其中取出, 都
要用到 serialzation, Java 的 serialzation 似乎从一开头就很慢, 是一个性能
杀手, 而这个杀手的身影又常常出现.

Java 我懂得不多, 其他我就不怎么知道了.


怀宇范 写道:

Huafeng Mo

unread,
Oct 9, 2007, 12:47:34 AM10/9/07
to pon...@googlegroups.com
对于gc,我感觉性能的问题倒不算很大,boost的那几个智能指针性能都不怎么样。问题是现在的一些gc,Java的也好、C#的也好,都是不确定的。冷不定地出来鼓捣几下,把别人的时间都给占了。结果,即便你gc性能比手工的好,时不时地让系统停个一秒半秒的,也足够让用户骂娘了。
还有就是,C#吹嘘分配内存有多快,比C++的都快。可就是不说它回收内存和压缩内存有多慢。而且在你,最不希望慢的时候慢。

在07-10-9,red...@gmail.com <red...@gmail.com> 写道:
--
反者道之动,弱者道之用

pongba

unread,
Oct 9, 2007, 12:51:03 AM10/9/07
to pon...@googlegroups.com


On 10/9/07, Huafeng Mo <longsh...@gmail.com> wrote:
对于gc,我感觉性能的问题倒不算很大,boost的那几个智能指针性能都不怎么样。问题是现在的一些gc,Java的也好、C#的也好,都是不确定的。冷不定地出来鼓捣几下,把别人的时间都给占了。结果,即便你gc性能比手工的好,时不时地让系统停个一秒半秒的,也足够让用户骂娘了。
还有就是,C#吹嘘分配内存有多快,比C++的都快。可就是不说它回收内存和压缩内存有多慢。而且在你,最不希望慢的时候慢。

 
这个... 有数据吗?现在最牛逼的分代垃圾收集就是平摊时间复杂度的想法啊..

redsea

unread,
Oct 9, 2007, 12:54:27 AM10/9/07
to TopLanguage
我说的比较好的库, 并不是指 boost 里面的智能指针.

智能指针, 那玩意就是图个方便, 效率? 就别提了.


On 10月9日, 下午12时51分, pongba <pon...@gmail.com> wrote:
> On 10/9/07, Huafeng Mo <longshank...@gmail.com> wrote:
>
>
>
> > 对于gc,我感觉性能的问题倒不算很大,boost的那几个智能指针性能都不怎么样。问题是现在的一些gc,Java的也好、C#的也好,都是不确定的。冷不定 地出来鼓捣几下,把别人的时间都给占了。结果,即便你gc性能比手工的好,时不时地让系统停个一秒半秒的,也足够让用户骂娘了。

Huafeng Mo

unread,
Oct 9, 2007, 1:38:09 AM10/9/07
to pon...@googlegroups.com
数据没有。一直用C++,倒也不太操心这种事。
只不过有那么几次体会。都是在.net下调试程序,调一些循环,循环里有不少内存分配(.net里什么内存都得分配)。几次循环以后(大概10多次吧,具体记不清了),ide总要停顿那么一下,有点像死锁。大约不到半秒左右,又开始运行了。后来几个C#er告诉我,可能是在gc。由于在调试,系统不忙,gc就来劲了,很积极地回收。但让我惊讶的是系统停顿的时间,就这么点内存gc,非但感觉明显,而且是很明显。我说,这种效率要是关键时刻还不死人哪。他们告诉我,如果不想要他在最关键的时候打搅你,事先手工gc一下。这倒也不错。不过后一句话让人丧气:只是手工gc不一定会做。:(
然后,我查了msdn,里面说,.net的内存分配快,因为内存压缩过,只需移动内存池指针。这就明了,内存压缩比单回收内存可费时多了,外加我频繁分配内存,短期对象之类的鸡零狗碎多,内存压缩比较频繁。尽管.net的内存池分三代,可遇到频繁的短期对象,挡也挡不住。更何况.net没有栈对象,所有对象,再小也得在堆里,鸡零狗碎的更多。
另一个角度讲,Java和.net的gc不是gc本身慢,而是把原本不应该gc的东西也gc了,这样神仙也没办法。
想来想去,还是RAII好啊。:)

在07-10-9,pongba <pon...@gmail.com> 写道:



--
反者道之动,弱者道之用

Huafeng Mo

unread,
Oct 9, 2007, 2:12:58 AM10/9/07
to pon...@googlegroups.com
在07-10-9,redsea <red...@gmail.com> 写道:
我说的比较好的库, 并不是指 boost 里面的智能指针.
智能指针, 那玩意就是图个方便, 效率? 就别提了.

误会了,误会了。我不是拿智能指针当作内存库。我提到boost不是针对你所说的内存库。我是为了强调gc的问题核心不在单纯的内存分配和回收效率上,而是这些操作发生的时机上。
在手工分配下,内存用完了就回收,所有操作都分散了。而应用中大部分的小型或短期对象都可以在栈里分配,栈清理了,也就是放了。操作也是精确的、分散的。
但是Java和.net的gc迫使程序把所有的内存释放集中在一起,使得许多可以及时清理的内存延迟到gc的时候。大幅增加gc的负担。
所以我觉得,将来C++有了gc之后,也应该尽可能地使用栈对象和RAII,把gc作为一种补充,或者补漏。无论从性能,还是方便,都比用gc来的好。

 

On 10月9日, 下午12时51分, pongba <pon...@gmail.com > wrote:
> On 10/9/07, Huafeng Mo <longshank...@gmail.com> wrote:
>
>
>
> > 对于gc,我感觉性能的问题倒不算很大,boost的那几个智能指针性能都不怎么样。问题是现在的一些gc,Java的也好、C#的也好,都是不确定的。冷不定 地出来鼓捣几下,把别人的时间都给占了。结果,即便你gc性能比手工的好,时不时地让系统停个一秒半秒的,也足够让用户骂娘了。
> > 还有就是,C#吹嘘分配内存有多快,比C++的都快。可就是不说它回收内存和压缩内存有多慢。而且在你,最不希望慢的时候慢。
>
> 这个... 有数据吗?现在最牛逼的分代垃圾收集就是平摊时间复杂度的想法啊..
>
> --
> 刘未鹏(pongba)|C++的罗浮宫http://blog.csdn.net/pongba
> TopLanguagehttp://groups.google.com/group/pongba



--
反者道之动,弱者道之用

red...@gmail.com

unread,
Oct 9, 2007, 2:17:41 AM10/9/07
to pon...@googlegroups.com
我现在开始用D, 就是这样计划的.

容易释放的, 就做显式释放; 比较难进行生命期管理的(例如 多个线程进行共享的, 或者会多次出现在调用栈中的对象), 只要不是属于申请, 释放特别频繁那种, 就让 GC 去管释放.

Huafeng Mo 写道:
在07-10-9,redsea <red...@gmail.com> 写道:
我 说的比较好的库, 并不是指 boost 里面的智能指针.
智 能指针, 那玩意就是图个方便, 效率? 就别提了.

dugu...@gmail.com

unread,
Oct 9, 2007, 2:18:37 AM10/9/07
to TopLanguage
JIT损失会很大吗?
恩。有没有具体的一些比较数据啊,有时候看到一些数据和评论,动不动说性能上差上几十倍,头皮发麻。我个人的感觉倒还好,没遇到那么恐怖的性能瓶
颈。。。

On 10月9日, 下午12时11分, pongba <pon...@gmail.com> wrote:
> 其实你都说了啊:间接层,语言模型的抽象层次、JIT的开销、GC、range check、other runtime checks...
> 也就不外乎这些原因了。
>
> 另外,C++标准网站上有一个Performance TR,可以看看。
>
> 其实我觉得以上这些性能因素会随着并发的普及逐渐变得不那么重要。
>
> 有谁做过大型统计的?或者看过有大型统计数据支持的文章的?出来吱一声啊 :P
>

> On 10/9/07, 怀宇范 <dugugu...@gmail.com> wrote:
>
>
>
>
>
>
>
> > 第一次发贴,问各位大牛一个关于效率的问题。
>
> > 都说C++的效率(运行时)比Java、.Net(C#)要高。这种效率主要来自于什么地方(或者说其他一些语言做了写什么事情损失了效率)。比如由于库的封装 ,调用的函数更高层会损失效率,不停的安全检查也会,还有其他一些什么原因,谢谢指教:)
>
> > --
> > 彪悍的人生,不需要解释。
>
> > bool ContactMe(person you)
> > {
> > if(you.GoTo("14#344, Tsinghua") && you.Find("范怀宇"))return true;

> > if(you.MailTo(" dugugu...@gmail.com ") || you.MailTo (" fanh...@mails.tsinghua.edu.cn


> > "))return true;
> > if(you.PhoneTo("13488810330") || you.PhoneTo("01062778689"))return
> > true;

> > if(you.QQTo("120628812") || you.MSNTo(" dugugu...@hotmail.com"))return


> > true;
> > if(you.NetTo("www.cnblogs.com/duguguiyu"))return true;
>
> > if(you.DareToKiss("FuRongJJ"))
> > {
> > cout<<"I 服了 U"<<endl;
> > return true;
> > }
> > if(you.GiveMeTwoTicketsFor("MayDay"))
> > {
> > cout<<"I love you!"<<endl;
> > return true;
> > }
>
> > return false;
> > }
>
> --
> 刘未鹏(pongba)|C++的罗浮宫http://blog.csdn.net/pongba

> TopLanguagehttp://groups.google.com/group/pongba- 隐藏被引用文字 -
>
> - 显示引用的文字 -

red...@gmail.com

unread,
Oct 9, 2007, 2:20:33 AM10/9/07
to pon...@googlegroups.com
google language shootout, 有一个网站, 可以看到, 小规模简单代码的话, java
的时间性能并不差, 只是空间占用厉害, 比很多解释性语言都厉害很多.

dugu...@gmail.com 写道:

Atry

unread,
Oct 9, 2007, 4:57:27 AM10/9/07
to pon...@googlegroups.com
.net 有栈对象的, struct 就是。它叫 value type

在07-10-9,Huafeng Mo <longsh...@gmail.com> 写道:

Huafeng Mo

unread,
Oct 9, 2007, 5:15:15 AM10/9/07
to pon...@googlegroups.com
哎呀,把这茬给忘了。没错,value type是栈对象,除非对它box。它相当于C++的pod,没有构造和析构功能。所以通常用的不多,对内存管理没有太大的帮助。


在07-10-9,Atry <pop....@gmail.com > 写道:



--
反者道之动,弱者道之用

red...@gmail.com

unread,
Oct 9, 2007, 5:24:00 AM10/9/07
to pon...@googlegroups.com
D 1.0 的 struct 也没有构造和析构, 在广泛的要求下, 2.0 即将加入.

Huafeng Mo 写道:

pongba

unread,
Oct 9, 2007, 5:26:42 AM10/9/07
to pon...@googlegroups.com
说到这个,我猜D 1.0不支持RAII的原因是因为RAII的确是scope(exit)的特殊形式。所有RAII都可以用scope(exit)来实现。

但关键是RAII还有一个优点,就是RAII封装的资源是一个整体,其释放是隐式的,在代码主逻辑里面不出现,很干净。scope(exit)就做不到这一点了。

red...@gmail.com

unread,
Oct 9, 2007, 5:51:38 AM10/9/07
to pon...@googlegroups.com
D 支持 RAII, 但是它是用 class 来支持, scope class, 就能用作 RAII .
它的struct, 从 C++ 向 C 返祖得太厉害了, 比起C, 就只多了一个能加上非虚成员函数.

我是碰到另外的地方很期望 D 的 struct 可以有构造和析构.

程序中, 有一种对象, 数目会很大, 它内部, 是几个对象组合起来构造的, 如果使用class
来组合,

1. 那么会增加 n 倍的 "鸡零狗碎" 的对象申请, 释放
2. 这些子对象, 经常是几个都要先后访问到的, 如果分配在连续内存区中, 对性能很有帮助

但是 D 的 class 作为子对象的时候, 却不能和host 对象一起申请内存, 用 struct 又没有
构造和析构; 反正都没有好方法的情况下, 最后我用了 template mixin 来组合, string
mixin 去判断构造进行调用, 和上次给出的 Selector 例子差不多.

BTW:
2 的这点, 对象组合, Java 里面也是无法连续分配的, 因此这里的性能负面影响就无法避免, C++ 则可以避免掉.

再加上Huafeng Mo 着重指出的, Java 不支持 stack 变量, Java 的这个内存模型会造成很多时候, 程序没有C内存模型效率高.

至于执行代码的编译结果, Java 的优化还是可以的, JIT 的开销, 从 language shootout 的 http://shootout.alioth.debian.org/gp4/faq.php
What about Java dynamic compilation?  里面的数据看来, JIT 编译花费的时间也不是太高, 起码没有对shootout 的结果带来很大的影响.


pongba 写道:

Atry

unread,
Oct 9, 2007, 9:02:12 AM10/9/07
to pon...@googlegroups.com
完全可以用 struct 嘛,反正你都用了手动初始化。在外面的构造函数手动挨个调某个特定的成员函数就是了。

在07-10-9,red...@gmail.com < red...@gmail.com> 写道:

red...@gmail.com

unread,
Oct 9, 2007, 9:30:42 AM10/9/07
to pon...@googlegroups.com

Atry 写道:
> 完全可以用 struct 嘛,反正你都用了手动初始化。在外面的构造函数手动挨个
> 调某个特定的成员函数就是了。


你说的是正道, 但是我已经是破罐破摔了:

反正用 struct 也要手工逐个调用构造函数, 不是好的解决方案, 干脆我就用
mixin 了, 这样就省掉为了 struct 中需要 public 出来的函数写 wrapper 代码
转接调用.


Huafeng Mo

unread,
Oct 9, 2007, 10:21:10 AM10/9/07
to pon...@googlegroups.com
关于jit,现在似乎有了一些新的论调。java等语言通过中间码发布程序,最初是在vm上解释执行,效率自然大打折扣。而使用jit,在代码第一次被调用时编译成本机代码,效率大幅提高。是否可以jit的编译也可以省去呢?那就在安装时编译吧。
这样,便产生了一个推论。既然在安装时或调用时编译,那么此时已经知道系统特别是cpu的类型。于是,便可以面向特定的系统平台优化编译。得到的代码甚至比直接编译成本机代码的还要好。
这个思想逻辑上没有错,或许也是未来的发展方向。sutter在exceptional c++ style中,分析了在编码、编译、链接、安装、运行等时候,inline的可能性。同样的思路,也可以推广到性能优化上。
但是,就目前的技术水平而言,我觉得要让一个jit编译器能够达到一个真正编译器的优化能力,还很困难。而且中间码不是源代码,留给编译器发挥的空间小得多。源码能更多地体现程序员的意图,而中间码则失去了很多对优化有用的信息。而且受制于中间码的设计局限,也不可能面向所有平台系统都能达到很好的效果。
但是,不管怎么说,Java、.net的性能问题不会仅仅由单独的哪一个问题引发,而是众多缺陷和不足引起的。其中,愚蠢的对象模型和内存管理体系是罪魁祸首。

在07-10-9,dugu...@gmail.com <dugu...@gmail.com> 写道:
JIT损失会很大吗?
恩。有没有具体的一些比较数据啊,有时候看到一些数据和评论,动不动说性能上差上几十倍,头皮发麻。我个人的感觉倒还好,没遇到那么恐怖的性能瓶
颈。。。

On 10月9日, 下午12时11分, pongba <pon...@gmail.com> wrote:
> 其实你都说了啊:间接层,语言模型的抽象层次、JIT的开销、GC、range check、other runtime checks...
> 也就不外乎这些原因了。
>
> 另外,C++标准网站上有一个Performance TR,可以看看。
>
> 其实我觉得以上这些性能因素会随着并发的普及逐渐变得不那么重要。
>
> 有谁做过大型统计的?或者看过有大型统计数据支持的文章的?出来吱一声啊 :P
>
> On 10/9/07, 怀宇范 < dugugu...@gmail.com> wrote:
>
>
>
>
>
>
>
> > 第一次发贴,问各位大牛一个关于效率的问题。
>
> > 都说C++的效率(运行时)比Java、.Net(C#)要高。这种效率主要来自于什么地方(或者说其他一些语言做了写什么事情损失了效率)。比如由于库的封装 ,调用的函数更高层会损失效率,不停的安全检查也会,还有其他一些什么原因,谢谢指教:)
>
> > --
> > 彪悍的人生,不需要解释。
>
> > bool ContactMe(person you)
> > {
> >     if(you.GoTo("14#344, Tsinghua") && you.Find("范怀宇"))return true;
> >     if(you.MailTo(" dugugu...@gmail.com ") || you.MailTo (" fanh...@mails.tsinghua.edu.cn
> > "))return true;
> >     if(you.PhoneTo("13488810330") || you.PhoneTo("01062778689"))return
> > true;
> >     if(you.QQTo("120628812") || you.MSNTo(" dugugu...@hotmail.com"))return
> > true;
> >     if(you.NetTo("www.cnblogs.com/duguguiyu"))return true;
>
> >     if(you.DareToKiss ("FuRongJJ"))

> >     {
> >         cout<<"I 服了 U"<<endl;
> >         return true;
> >     }
> >     if(you.GiveMeTwoTicketsFor("MayDay"))
> >     {
> >         cout<<"I love you!"<<endl;
> >         return true;
> >     }
>
> >     return false;
> > }
>
> --
> 刘未鹏(pongba)|C++的罗浮宫 http://blog.csdn.net/pongba

red...@gmail.com

unread,
Oct 9, 2007, 10:52:31 AM10/9/07
to pon...@googlegroups.com
现在使用 gentoo, slackware, lfs 等版本的linux, 整个OS 带应用就是自行编译
的, freebsd 的 ports, 软件都是从源代码进行编译, debian, ubuntu 等debian
系的linux 也可以一个命令就可以简单地自行编译软件. 而这些系统的编译, 缺省
就是和系统的 CPU 一致的, 优化级别可以很高.

Java, .Net, 限于需要快速完成编译, 优化级别不可能太高; 即使它们的编译器选
择生成中间码的时候做深入优化, 删除很多中间码, 最终不过接近上述系统的优化
编译而已; 根本不算啥; 只是可以在 windows 这种 close 系统上面抖抖威风而已.

不过, 我以前做过一个编译器, 根据我的知识, 编译器的优化就是在中间码(&带上
符号表)上进行的啊, C/C++ 的编译器中间码, 优化之前, 并不会损失程序员的意
图, 难道 Java 的有所不同 ?

Huafeng Mo 写道:
> 关于jit,现在似乎有了一些新的论调。java等语言通过中间码发布程序,最初
> 是在vm上解释执行,效率自然大打折扣。而使用jit,在代码第一次被调用时编
> 译成本机代码,效率大幅提高。是否可以jit的编译也可以省去呢?那就在安装
> 时编译吧。
> 这样,便产生了一个推论。既然在安装时或调用时编译,那么此时已经知道系统
> 特别是cpu的类型。于是,便可以面向特定的系统平台优化编译。得到的代码甚

Atry

unread,
Oct 9, 2007, 11:45:23 AM10/9/07
to pon...@googlegroups.com
理论上说,运行的时候编译可能效率更高,比如说可以统计出不同分支路径的概率, 根据概率调整生成的代码,效率可能更高。

在07-10-9,red...@gmail.com < red...@gmail.com> 写道:

shark

unread,
Oct 9, 2007, 6:23:45 AM10/9/07
to pon...@googlegroups.com
请教下各位,现在的C++编译器(g++,vc8+,icc,...)对virtual function的优化
都做到什么程度了?也即能把多少virtual直接猜测出来?

Huafeng Mo

unread,
Oct 9, 2007, 8:17:48 PM10/9/07
to pon...@googlegroups.com


在07-10-9,red...@gmail.com <red...@gmail.com> 写道:
不过, 我以前做过一个编译器, 根据我的知识, 编译器的优化就是在中间码(&带上
符号表)上进行的啊, C/C++ 的编译器中间码, 优化之前, 并不会损失程序员的意
图, 难道 Java 的有所不同 ?

这只是我的感觉,没有分析和论证过。我对编译器优化技术不熟悉,只是随便猜猜。偶尔看过一点点材料,提到优化的事情。给我的映像似乎优化广泛分布于整个的编译过程中, 所以jit如果仅仅从中间吗开始优化,便丧失了编译早期的一些机会。大概是我理解错了。

Huafeng Mo 写道:
> 关于jit,现在似乎有了一些新的论调。java等语言通过中间码发布程序,最初
> 是在vm上解释执行,效率自然大打折扣。而使用jit,在代码第一次被调用时编
> 译成本机代码,效率大幅提高。是否可以jit的编译也可以省去呢?那就在安装
> 时编译吧。
> 这样,便产生了一个推论。既然在安装时或调用时编译,那么此时已经知道系统
> 特别是cpu的类型。于是,便可以面向特定的系统平台优化编译。得到的代码甚
> 至比直接编译成本机代码的还要好。
> 这个思想逻辑上没有错,或许也是未来的发展方向。sutter在exceptional c++
> style中,分析了在编码、编译、链接、安装、运行等时候,inline的可能性。
> 同样的思路,也可以推广到性能优化上。
> 但是,就目前的技术水平而言,我觉得要让一个jit编译器能够达到一个真正编
> 译器的优化能力,还很困难。而且中间码不是源代码,留给编译器发挥的空间小
> 得多。源码能更多地体现程序员的意图,而中间码则失去了很多对优化有用的信
> 息。而且受制于中间码的设计局限,也不可能面向所有平台系统都能达到很好的
> 效果。
> 但是,不管怎么说,Java、.net的性能问题不会仅仅由单独的哪一个问题引发,
> 而是众多缺陷和不足引起的。其中,愚蠢的对象模型和内存管理体系是罪魁祸首。
>







--
反者道之动,弱者道之用

Huafeng Mo

unread,
Oct 9, 2007, 8:21:31 PM10/9/07
to pon...@googlegroups.com


在07-10-9,red...@gmail.com <red...@gmail.com> 写道:
现在使用 gentoo, slackware, lfs 等版本的linux, 整个OS 带应用就是自行编译
的, freebsd 的 ports, 软件都是从源代码进行编译, debian, ubuntu 等debian
系的linux 也可以一个命令就可以简单地自行编译软件. 而这些系统的编译, 缺省
就是和系统的 CPU 一致的, 优化级别可以很高.

这个应该是未来的发展方向吧。很好的思路,我喜欢。 :)


--
反者道之动,弱者道之用

red...@gmail.com

unread,
Oct 9, 2007, 9:42:13 PM10/9/07
to pon...@googlegroups.com
这不是未来的方向, 现在已经如此, open source 软件就可以享受这个好处了, close source 软件当然不行.
Huafeng Mo 写道:


在07-10-9,red...@gmail.com <red...@gmail.com> 写道:
现 在使用 gentoo, slackware, lfs 等版本的linux, 整个OS 带应用就是自行编译

的, freebsd 的 ports, 软件都是从源代码进行编译, debian, ubuntu 等debian
系的linux 也可以一个命令就可以简单地自行编译软件. 而这些系统的编译, 缺省
就是和系统的 CPU 一致的, 优化级别可以很高.

这个应该是未来的发展方向吧。很好的思路,我喜欢。 :)


--
反者道之动,弱者道之用


red...@gmail.com

unread,
Oct 9, 2007, 9:49:06 PM10/9/07
to pon...@googlegroups.com
这个确实似乎是理论意义大.

现实上, C++ 用intel 的工具, 能够进行这些分析优化.

如果runtime 做这个分析,成本太高了, 因为这个粒度太细了.

如果不同分支路径的概率基本不变, 提前分析的方法已经 ok 了, 如果不同分析路
径的概率经常变, runtime 经常分析的成本无法承受; 要找一个合适的应用场合,
还是不容易的.

Atry 写道:
> 理论上说,运行的时候编译可能效率更高,比如说可以统计出不同分支路径的概
> 率, 根据概率调整生成的代码,效率可能更高。

Huafeng Mo

unread,
Oct 9, 2007, 9:57:13 PM10/9/07
to pon...@googlegroups.com
那么强化中间码,使其携带更多可用于优化的信息,是否可行呢?

在07-10-10,red...@gmail.com <red...@gmail.com > 写道:

red...@gmail.com

unread,
Oct 9, 2007, 10:50:30 PM10/9/07
to pon...@googlegroups.com
Huafeng Mo 写道:
> 那么强化中间码,使其携带更多可用于优化的信息,是否可行呢?

刚刚生成还没有优化的中间码, 再加上符号信息, 就可以有源代码想表达的全部的
信息了, 一般都是在这个的基础上做表达式优化, 常量从循环内抽离之类的优化.

整个程序的中间码都得到后, 会分析哪些代码根本不会调用到, 去掉它. 更先进的
分析, 似乎包括在全局代码都在的情况下, 可以分析出哪个函数的参数都是常量调
用的, 可以去掉这个参数的压栈, 这个值变成函数内部的常量; 某些 virtual 函
数的调用, 可以分析出具体调用的函数; 如果某个函数接受的函数指针在上下文可
以分析出来, 那么函数指针实际可以 inline 掉等等, 这些更高级的东西, 我懂得
不多.

这些高级的优化, 如果在 JIT 的时候做分析, 恐怕分析成本相对高了----- 当然
对于分析一次, 会执行半年的服务器, 也没有什么很大的关系.


Arty 提到的分支优化, 分析成本也相对有点高:

第一步要做代码热点分析, 大粒度分析的话代价不高, 正常数据输入的时候跑跑,
进行中断采样即可.
第二步要进行详细的路径分析, 对于大粒度分析出来的热点区域, 重新编译, 每个
汇编级别的判断语句之后, 加入代码记录执行次数, 对于内层循环, 这样的代价就
比较大了.

但是分支 JIT 分支优化有个好处 ---- 每个JIT程序都能够享受到, C++ 的程序,
如果没有购买 intel 的工具, 就没有办法做这种优化了.


Huafeng Mo

unread,
Oct 9, 2007, 11:01:13 PM10/9/07
to pon...@googlegroups.com
这就太好了。这类技术如果发展起来,那就太绝了,既解决了跨平台问题,又获得了最好的优化,而且还是动态的优化。
我的一个同事几个月前还在嘀咕,说现在的编程技术已经没得什么发展了,差不多到头了。应该让他来看看toplanguage。:)
再问一个,源码编译成中间码时,是否还可以做一些优化?有没有可能发生弄巧成拙的情况?


在07-10-10, red...@gmail.com <red...@gmail.com> 写道:

red...@gmail.com

unread,
Oct 10, 2007, 12:15:30 AM10/10/07
to pon...@googlegroups.com
Huafeng Mo 写道:
> 这就太好了。这类技术如果发展起来,那就太绝了,既解决了跨平台问题,又获
> 得了最好的优化,而且还是动态的优化。
> 我的一个同事几个月前还在嘀咕,说现在的编程技术已经没得什么发展了,差不
> 多到头了。应该让他来看看toplanguage。:)
现在是大宗商品化软件的战争都结束了, 互联网应用广泛, 编程应用领域也更散开了.

在很多其他领域可能很有进展, 只关注 Windows desktop 平台可能看不到这些变
化 ---- Windows 用复杂的方法解决复杂的问题, 用更复杂的方法解决它自身方法
带来的问题, 东西越来越庞大, 迟早跑不动.

现在的一些进步, 例如, multicore 跑到什么程度了 ? 已经有公司提供 64core
的pcie卡产品给video/networking 用了, 很快 128core 的产品就出来. 64core
的性能是 Intel Xeon 2core 的10倍, 价格只要 $435.

这么一个平台, 编程技术不发展, 根本就无法利用. 这个平台还很有趣, 所有的
core 的 L2 cache 综合起来, 作为所有 core 的 L3 cache ---- 既然这个cpu 是
设计来做 cpu bound 的处理, 大家干的活可能差得不多, 我的 cache 里面没有,
你的cache 里面就可能有了.


> 再问一个,源码编译成中间码时,是否还可以做一些优化?有没有可能发生弄巧
> 成拙的情况?
>

静态语言的优化, 一般是每个模块编译成中间码后优化一次, 整个程序各个模块都
编译完了, 整体信息齐备之后再优化一次. C++ 的模板也有一些相关的优化, 不过
我不懂.


优化当然可能会有弄巧成拙的可能, 例如, 你 google 一下 pointer alias, 可以
知道这个东西的影响, 但是gcc 有选项可以让它认为不用考虑这个问题. --> 你可
以告诉 gcc, 所有指针都没有别名, 真没有的话, 你的程序就跑得更快了, 而万一
有的话, 你的乐子就大了 ---- 可能搞来搞去就搞不出可以重复bug 的输入数据.

用危险优化的后果, 问问激进的gentoo 用户就可以知道不少: 一些激进的用户,
不管软件推荐的级别, 自己尝试更危险的优化, 会不时碰到编译结果有问题, 有些
问题可能是跑很长时间偶尔出现的.

对 gcc 而言, -o2 的优化一般还是安全的, -o3 包含的优化可能就有危险了.
c/c++ 发展的同时, 优化技术同时发展, 因此, 这个语言的设计本身没有考虑到很
多配合优化, 有一些可以带来收益的优化无法准确分析而无法使用, 或者 at your
own risk.

现在设计的D 语言, walter 本身是C++ 编译器老人了, 他知道这些问题, 所以他
设计的语言特性, 同时会考虑对用户的有用程度, 危险性, 以及对编译器的编译速
度, 优化的影响. const 语法语义的设置现在还没有定稿, 也是因为考虑太多
---- C++ 的const, 当年可能没有怎么考虑清楚就出来了, 变成了一个表面看起来
很有用, 实际上多数情况也是很有用, 但是在某些情况下, 却会误导程序员, 我还
不知道它会不会误导编译器, 不过编译器多半可能不甩它.


Linker M Lin

unread,
Oct 10, 2007, 7:40:41 AM10/10/07
to TopLanguage
以前做过网络处理器(NP)的开发.
那是种DSP(哈佛架构)的处理器.
多核多个硬件线程.
在这种环境中, 获得高效率的关键是无锁编程和隐藏内存访问延时(通过快速切换硬件线程).
我想:
以后,GPGPU和下一代CPU的架构一定会吸收哈佛架构的思想,更多核,硬件实现更多原子操作.
从而,也对基于栈的虚拟机提出了挑战.

C语言的硬件亲和性保证其可以很好的适应这个新架构.(原来在NP上开发用的就是MicroC(一种C方言)).
GPGPU也是最先支持了C语言和Lua语言.
目前,GPU的晶体管数目已经大大超过CPU.
所以,这种趋势应该会越来越明显吧.


On Oct 9, 11:49 am, "怀宇范" <dugugu...@gmail.com> wrote:
> 第一次发贴,问各位大牛一个关于效率的问题。
> 都说C++的效率(运行时)比Java、.Net(C#)要高。这种效率主要来自于什么地方(或者说其他一些语言做了写什么事情损失了效率)。比如由于库的封装 ,调用的函数更高层会损失效率,不停的安全检查也会,还有其他一些什么原因,谢谢指教:)
>

> --
> 彪悍的人生,不需要解释。
>
> bool ContactMe(person you)
> {
> if(you.GoTo("14#344, Tsinghua") && you.Find("范怀宇"))return true;
> if(you.MailTo(" dugugu...@gmail.com ") || you.MailTo("
> fanh...@mails.tsinghua.edu.cn "))return true;
> if(you.PhoneTo("13488810330") || you.PhoneTo("01062778689"))return true;
> if(you.QQTo("120628812") || you.MSNTo("dugugu...@hotmail.com"))return
> true;
> if(you.NetTo("www.cnblogs.com/duguguiyu"))return true;
>

> if(you.DareToKiss("FuRongJJ"))


> {
> cout<<"I 服了 U"<<endl;
> return true;
> }
> if(you.GiveMeTwoTicketsFor("MayDay"))
> {
> cout<<"I love you!"<<endl;
> return true;
> }
>
> return false;
>
>
>

> }- Hide quoted text -
>
> - Show quoted text -

bbsdkjdx

unread,
Nov 11, 2007, 11:02:41 AM11/11/07
to TopLanguage
请教楼主:
VC8可以支持托管和本地代码共存,那是不是可以将难以掌控生存期的对象用托管(gcnew),而容易掌控的则用纯C++的内存设施.不知一个程序中加
入了托管后,其本地代码部队会不会受效率的影响.

莫华枫

unread,
Nov 11, 2007, 7:14:41 PM11/11/07
to pon...@googlegroups.com


在07-11-12,bbsdkjdx <bbsd...@163.com> 写道:
请教楼主:
VC8可以支持托管和本地代码共存,那是不是可以将难以掌控生存期的对象用托管(gcnew),而容易掌控的则用纯C++的内存设施.

不行,除非你的托管部分和非托管部分不需要进行数据交换。因为托管和非托管两个部分是完全独立的内存模型,对象布局完全不一样。容易掌控的对象(确定性生命期)可以直接使用C++/CLI的栈语义:直接在代码段或一个类中定义或声明对象,其行为同标准C++的自动对象(局部对象)基本一致。 但是,Sutter曾经表示,vc团队正在努力,使得托管和非托管的类可以交互使用。
对于标准C++,基本上得不到托管的帮助,只能利用其本身的智能指针或gc。

不知一个程序中加
入了托管后,其本地代码部队会不会受效率的影响.

按理说应当不会,但没有测试过。

longsh...@gmail.com
http://blog.csdn.net/longshanks/

Googol Lee

unread,
Nov 11, 2007, 9:43:39 PM11/11/07
to TopLanguage
印象里,C#的struct出来的都是栈对象,比如Size,Point之类的,自己手工建的也都是栈对象。但我不知道struct里面能不能包含某个
class了,没试过。

另一个,C#有个Disposable的interface,实现了这个的class可以调用Dispose()做手工回收。

最后,这种循环内部的,用Pool不行么?

On Oct 9, 1:38 pm, "Huafeng Mo" <longshank...@gmail.com> wrote:
> 数据没有。一直用C++,倒也不太操心这种事。
> 只不过有那么几次体会。都是在.net下调试程序,
> 调一些循环,循环里有不少内存分配(.net里什么内存都得分配)。几次循环以后(大概10多次吧,具体记不清了),ide总要停顿那么一下,有点像死锁。大约不到半秒左右,又开始运行了。后来几个C#er告诉我,可能是在gc。由于在调试,系统不忙,gc就来劲了,很积极地回收。但让我惊讶的是系统停顿的时间,就这么点内存gc,非但感觉明显,而且是很明显。我说,这种效率要是关键时刻还不死人哪。他们告诉我,如果不想要他在最关键的时候打搅你,事先手工gc一下。这倒也不错。不过后一句话让人丧气:只是手工gc不一定会做。:(
> 然后,我查了msdn,里面说,.net的内存分配快,因为内存压缩过,只需移动内存池指针。这就明了,内存压缩比单回收内存可费时多了,外加我频繁分配内存,短期对象之类的鸡零狗碎多,内存压缩比较频繁。
> 尽管.net的内存池分三代,可遇到频繁的短期对象,挡也挡不住。更何况.net没有栈对象,所有对象,再小也得在堆里,鸡零狗碎的更多。
> 另一个角度讲,Java和.net的gc不是gc本身慢,而是把原本不应该gc的东西也gc了,这样神仙也没办法。
> 想来想去,还是RAII好啊。:)
>
> 在07-10-9,pongba <pon...@gmail.com> 写道:
>
>
>
>
>
> > On 10/9/07, Huafeng Mo <longshank...@gmail.com> wrote:
>
> > > 对于gc,我感觉性能的问题倒不算很大,boost的那几个智能指针性能都不怎么样。问题是现在的一些gc,Java的也好、C#的也好,都是不确定的。冷不定地出来鼓捣几下,把别人的时间都给占了。结果,即便你gc性能比手工的好,时不时地让系统停个一秒半秒的,也足够让用户骂娘了。
> > > 还有就是,C#吹嘘分配内存有多快,比C++的都快。可就是不说它回收内存和压缩内存有多慢。而且在你,最不希望慢的时候慢。
>
> > 这个... 有数据吗?现在最牛逼的分代垃圾收集就是平摊时间复杂度的想法啊..
>

> > --
> > 刘未鹏(pongba)|C++的罗浮宫
> >http://blog.csdn.net/pongba

莫华枫

unread,
Nov 11, 2007, 10:27:31 PM11/11/07
to pon...@googlegroups.com
C#的struct类似于C++的pod,缺少构造和析构功能。同时,一个更大的问题使得struct无法被广泛使用:对于struct(值类型),=操作符表示值拷贝,而对于class(引用类型),=操作表示引用的赋值。两者具有完全不同的语义。如果我在项目中定义了一个struct A,开发到一半后,发现A需要增加一些struct无法涵盖的功能,必须改成class。由于=对于两者的语义不同,那么存在=操作的代码都将可能成为bug,相关代码必须修改。所以,为获得开发中的自由度,一般很少使用struct定义稍具复杂性的类型。
而C++或C++/CLI从语义上无需区分值类型和引用类型,两者行为相同,不存在这些问题。所以,从这一点上讲,C++这种传统的内存模型更加灵活可靠。C++/CLI尽管为了适应.net平台,被迫将栈语义变成一种语法糖,但其带来的好处,是C#所无法比拟的。
Disposable是完全为了.net对象模型而生的,它导致了一个对象的内存清理必须手工实现。而C++的自动对象(栈对象、子对象)可以保证自动调用析构释放资源,这就是raii。相比C#的手工dispose、using和java的finalization,简洁优雅得多。(Sutter的blog上有一篇文章专门比较了他们的差异)。gc自动化了内存管理,但对于其他资源缺乏自动化的手段,这是C#和java思维的古怪之处:不相信程序员能够很好地手动管理内存,却认定他们能够手动地管好其他资源。
对于循环内部,基本上都是new出来的东西(非确定性内存分配),插入容器,pool起不了什么作用。对于gc而言,这些时必须承受的负担。但是,除此以外,在.net上(不仅仅是C#),所有引用类型(我们还敢用值类型吗?)都在栈中分配,由gc回收。编程中,多数的对象都可以有确定的生存期,比如局部对象、一个对象的子对象等等。这些对象通常都是些诸如string之类的小型对象。他们本该用完就释放,也能做到这一点。但鉴于.net的对象模型,这些鸡零狗碎都被迫由gc统一收集,gc的负担能不大吗?
另一个不容易看到的地方就是,C++中在一个类中声明的成员对象(不是指针或引用)通常都在宿主对象的内部构成子对象,宿主对象释放,子对象也释放。而.net中一切都是引用(我们不敢用值类型对吧),宿主对象和子对象是独立的,gc必须分两次加以回收,gc的负担又增加一块。
总之,gc的名声都是.net之类的蹩脚对象模型搞臭的。


在07-11-12, Googol Lee <goog...@gmail.com> 写道:



--
反者道之动,弱者道之用
m...@seaskysh.com
longsh...@gmail.com
http://blog.csdn.net/longshanks/

red...@gmail.com

unread,
Nov 11, 2007, 10:35:32 PM11/11/07
to pon...@googlegroups.com
D 目前也有这个问题, 计划中可能允许 class 的成员用 scope 定义子对象, 空间
一起分配, 但是, 目前的版本就会搞得对象太多.
我用mixin 的同时也避免了这个问题.

> 另一个不容易看到的地方就是,C++中在一个类中声明的成员对象(不是指针或

zhangy...@kedacom.com

unread,
Nov 11, 2007, 11:29:53 PM11/11/07
to pon...@googlegroups.com

1用过Java的人,需要用C++来写程序。
2C++基础不是太好
3觉得MFC太复杂,想用托管的C++加上Form来设计。
4另外他们需要调用一个多年前用C++写的通信类库(DLL形式)。

大家说说可行性,以及需要注意什么,或者有什么其它方案

pongba

unread,
Nov 11, 2007, 11:41:39 PM11/11/07
to pon...@googlegroups.com
我很怀疑他是不是真的需要C++。
用C#不好么?
仅仅因为需要调用C++写的DLL就要用C++吗?

zhangy...@kedacom.com

unread,
Nov 11, 2007, 11:36:47 PM11/11/07
to pon...@googlegroups.com

我想他们需要的是C#,我也说过多次,不过我LaoPo的领导说她们要用C++,所以来看看大家有什么看法

莫华枫

unread,
Nov 11, 2007, 11:54:32 PM11/11/07
to pon...@googlegroups.com
做自然能做,C++/CLI可以直接混合managed和native的。可以在managed代码中直接调用native的东西。
只是,冲着第2条,还是尽量少用C++的好。

Googol Lee

unread,
Nov 11, 2007, 11:57:21 PM11/11/07
to TopLanguage
多谢多谢,关于struct和class在赋值上的语义区别倒还真没想过。

对于你这种情况,不知道类似于StringBuilder的类有没有帮助。

On Nov 12, 11:27 am, "莫华枫" <longshank...@gmail.com> wrote:
> C#的struct类似于C++的pod,缺少构造和析构功能。同时,一个更大的问题使得struct无法被广泛使用:对于struct(值类型),=操作符表示值拷贝,而对于class(引用类型),=操作表示引用的赋值。两者具有完全不同的语义。如果我在项目中定义了一个struct
> A,开发到一半后,发现A需要增加一些struct无法涵盖的功能,必须改成class。由于=对于两者的语义不同,那么存在=操作的代码都将可能成为bug,相关代码必须修改。所以,为获得开发中的自由度,一般很少使用struct定义稍具复杂性的类型。
> 而C++或C++/CLI从语义上无需区分值类型和引用类型,两者行为相同,不存在这些问题。所以,从这一点上讲,C++这种传统的内存模型更加灵活可靠。C++/CLI尽
> 管为了适应.net平台,被迫将栈语义变成一种语法糖,但其带来的好处,是C#所无法比拟的。
> Disposable是完全为了.net对象模型而生的,
> 它导致了一个对象的内存清理必须手工实现。而C++的自动对象(栈对象、子对象)可以保证自动调用析构释放资源,这就是raii。相比C#的手工dispose、using和java的finalization,简洁优雅得多。(Sutter的blog上有一篇文章专门比较了他们的差异)。gc自动化了内存管理,但对于其他资源缺乏自动化的手段,这是C#和java思维的古怪之处:不相信程序员能够很好地手动管理内存,却认定他们能够手动地管好其他资源。
> 对于循环内部,基本上都是new出来的东西(非确定性内存分配),插入容器,pool起不了什么作用。对于gc而言,这些时必须承受的负担。但是,除此以外,
> 在.net上(
> 不仅仅是C#),所有引用类型(我们还敢用值类型吗?)都在栈中分配,由gc回收。编程中,多数的对象都可以有确定的生存期,比如局部对象、一个对象的子对象等等。这些对象通常都是些诸如string之类的小型对象。他们本该用完就释放,也能做到这一点。
> 但鉴于.net的对象模型,这些鸡零狗碎都被迫由gc统一收集,gc的负担能不大吗?
> 另一个不容易看到的地方就是,C++中在一个类中声明的成员对象(不是指针或引用)通常都在宿主对象的内部构成子对象,宿主对象释放,子对象也释放。
> 而.net中一切都是引用(我们不敢用值类型对吧),宿主对象和子对象是独立的,gc必须分两次加以回收,gc的负担又增加一块。
> 总之,gc的名声都是.net之类的蹩脚对象模型搞臭的。
>

> 在07-11-12,Googol Lee <googol...@gmail.com> 写道:

> longshank...@gmail.comhttp://blog.csdn.net/longshanks/

莫华枫

unread,
Nov 12, 2007, 12:15:42 AM11/12/07
to pon...@googlegroups.com
这得先看String。我稍微读了一点ms的.net BCL源码,String是个非常特殊的实现。因为同传统上的String实现(包括C++的std::string)不同,.net的String不再持有一个指向字符串的指针,而是本身就是这个字符串指针。基址位置是字符串长度,然后紧跟着整个字符串。这种情况下,无法在字符串长度不够的情况下,重新分配一块更大的,复制内容,然后释放老的。只能重新分配一个字符串,偷偷地替换原来的那个。这样, 原来的那个字符串按照.net内存模型,只能废弃,等待回收。也就是说,String是无法调整数据缓存大小,或者预留缓冲区空间的。每次字符串增量操作都必须创建新的字符串。
StringBuilder则更接近于std::string,它可以预留缓冲区空间和调整缓冲大小。所以在存在大量字符串拼接和增量操作的时候,StringBuilder有绝对的性能优势。

在07-11-12, Googol Lee <goog...@gmail.com> 写道:
多谢多谢,关于struct和class在赋值上的语义区别倒还真没想过。

怀宇范

unread,
Nov 14, 2007, 12:54:00 AM11/14/07
to pon...@googlegroups.com
应该说,大部分场合下,对内存的管理比对非内存资源的管理要多的多,犯了错误也不是那么容易发现。
而且,从技术上看,实现非内存资源的GC,会更加更加更加的麻烦,应该会是得不偿失的。
我想这就是为什么只做内存GC的原因吧。
--
bool ContactMe(person you)
{
   if(you.GoTo("14#344, Tsinghua") && you.Find("Fan Huaiyu"))return true;
   if(you.MailTo (" dugu...@gmail.com ") || you.MailTo(" fan...@mails.tsinghua.edu.cn "))return true;
   if(you.PhoneTo ("13488810330") || you.PhoneTo("01062778689"))return true;
   if(you.QQTo("120628812") || you.MSNTo("dugu...@hotmail.com"))return true;
   if(you.NetTo(" www.cnblogs.com/duguguiyu "))return true;
   return false;
}

怀宇范

unread,
Nov 14, 2007, 12:54:57 AM11/14/07
to pon...@googlegroups.com
CLR via C#里面有很详细的描述。
但有源码看的感觉真好^_^。。。
--
bool ContactMe(person you)
{
   if(you.GoTo("14#344, Tsinghua") && you.Find("Fan Huaiyu"))return true;
   if( you.MailTo(" dugu...@gmail.com ") || you.MailTo(" fan...@mails.tsinghua.edu.cn "))return true;

莫华枫

unread,
Nov 14, 2007, 1:18:34 AM11/14/07
to pon...@googlegroups.com
的确如此。
非内存资源的管理在无gc的C++中依赖于raii,实际上也是依附于内存管理的方法(严格地讲是对象生命期管理)。对于确定性生命周期的对象,当对象离开作用域,便结束了生命期。raii利用析构函数清理资源。而对于非确定性生命周期的对象,理论上也可以做到主动结束生命期。当每一个指向对象的引用全部销毁,也就表明了该非确定性对象生命的结束。此时,便可以释放对象,并且依靠对象的析构函数释放资源。这也是智能指针的思路。但是,两个问题导致这种"主动还贷"的失效。一个是循环引用,这是正常的情况。这种"狗咬狗"的情况只能依靠外界的干预才能解决,gc可以定期地清理这些东西。第二个则是非法的情况,就是将栈对象的引用传递到对象作用域以外。但现在还没有很好的方法阻止这种行为。
理论上,gc在最终回收对象的时候可以调用析构之类的函数,释放对象占用的资源。但是,很多非内存资源是珍贵的,需要及时返还。在这个地方,gc的不确定性会产生严重的副作用。为此,才会有finalization等机制,提供手动的非内存资源释放。
所以,资源的管理(包括内存)的核心问题就是对象生命期的管理——当对象结束生命是,它所持有的资源也就应该是放了(就像人死了一样)。尽管在多数情况下,我们都可以明确地知道对象生命期的结束,但是循环引用的破除还是不得不依赖于被动的对象回收,而这又是迟后的。这也就是非内存资源管理困难的根本原因。对内存管理适合的手法(gc)对于稀缺资源,就无法适应了。

在07-11-14,怀宇范 <dugu...@gmail.com> 写道:

怀宇范

unread,
Nov 14, 2007, 1:44:37 AM11/14/07
to pon...@googlegroups.com
恩。。这种情况下。。还是自己劳动一下:)
.net的Dispose模式一开始比较乱,现在还好了。
Reply all
Reply to author
Forward
0 new messages