Robert C. Martin博客中文版

面向对象设计、模式、UML、敏捷方法学和极限编程领域。Robert C. Martin是Object Mentor公司总裁,面向对象设计、模式、UML、敏捷方法学和极限编程领域内的资深顾问。他不仅是Jolt获奖图书《敏捷软件开发:原则、模式与实践》(中文版) 、(《敏捷软件开发》(英文影印版))的作者,还是畅销书Designing Object-Oriented C++ Applications Using the Booch Method的作者。Martin是Pattern Languages

翻译 三大编程语言的性能PK--Java, C/C++和Ruby (原文最终修订于 2006-09-05 下午06:19:40)收藏

新一篇: 使用Mock Object危险么?(原文最终修订于 2006-09-02 下午03:53:51) | 旧一篇: 性能调优--永远超乎想象 (原文最终修订于 2006-08-28 晚上11:48:38)

译者序

本文虽然标题略有争议,但Bob大叔撰写此文并非是要说明Java>C/C++>Ruby,而是延续上篇“性能调优--永远超乎想象”的风格,借以说明程序的性能一般都超乎我们想象的观点,因此请读此文的C/C++爱好者少安毋躁:-)

正文

你可能会觉得下面的图表比较有意思,因为它是分别用三种编程语言(Ruby, Java, C/C++)写的埃拉托色尼质数过滤算法(译注:Sieve of Eratosthenes)的性能分析图,如图:(本文的最后附有相应代码)

好,很明显Ruby是慢的,而且慢了大概有1.5个数量级(译注:即约30倍)。这对于Ruby爱好者来说可不是个好消息。不过换个角度看,呼!Ruby与五、六年前的顶级电脑一样快。还记得第一次在时钟周期不到一兆赫的机器上跑程序的神奇情景吗...我们还为此兴奋得直往山顶跑!

注意一下,这三条曲线是同样形状的,我们可以从上篇blog中了解到为何曲线会呈线性。最后要关注的是,Java的曲线以极其微小的优势快于C++。你可以抱怨那是因为没有用gcc编译器优化编译的缘故(我用的是cygwin(译注:gcc编译器移植到windows的版本)),可是,如果现在还有任何C++程序员还会嘲笑Java的性能的话,我劝你最好还是再重新掂量掂量吧。

而对于那些因为他们自己的开发环境比Ruby快上30倍而洋洋自得的Java程序员来说,我肯定更优的ruby实时编译器即将问世了。不管如何,相比那快上1.5个数量级的情形来说,我本人还是更喜欢干净、简洁、易维护的代码。

Ruby
require 'benchmark'
def sievePerformance(n)
  r = Benchmark.realtime() do
    sieve = Array.new(n,true)
    sieve[0..1] = [false,false]
   
    2.upto(Integer(Math.sqrt(n)) do |i|
      if sieve[i]
        (2*i).step(n,i) do |j|
          sieve[j] = false
        end
      end
    end
  end
  r
end

Java
public class GeneratePrimes {
  public static double generate(int max) {
    long start = System.currentTimeMillis();
    boolean sieve[] = new boolean[max];
    Arrays.fill(sieve, true);
    sieve[0] = false;
    sieve[1] = false;
    for (int i = 2; i < Math.sqrt(max); i++) {
      if (sieve[i]) {
        for (int j = 2*i; j < sieve.length; j+=i) {
          sieve[j]= false;
        }
      }
    }

    return (System.currentTimeMillis() - start)/1000.0;
  }

C++
#include <iostream>>
#include <math.h>
#include <sys/time.h>

using namespace std;

double generate(int max) {
  struct timeval start;
  struct timezone tz;
  gettimeofday(&start, &tz);

  bool *sieve = new bool[max];
  for (int i=0; i<max; i++) sieve[i] = true;
  sieve[0] = false;
  sieve[1] = false;
  for (int n=2; n<sqrt(max); n++) {
    if (sieve[n]) {
      for (int j=2*n; j<max; j+=n)
        sieve[j] = false;
    }
  }

  struct timeval end;
  gettimeofday(&end, &tz);
  
  double startSecond = start.tv_usec/1000000.0;
  double endSecond = (end.tv_sec - start.tv_sec) + end.tv_usec/1000000.0;
  return endSecond - startSecond;
}


int main(int ac, char** av) {
  for (int i=100000; i<=5000000; i+=100000) {
    double time = generate(i);
    cout << time << endl;
  }
}

 (原文链接网址:http://www.butunclebob.com/ArticleS.UncleBob.SpeedOfJavaCppRuby; Robert C. Martin的英文blog网址: http://www.butunclebob.com/ArticleS.UncleBob 

作者简介:Robert C. MartinObject Mentor公司总裁,面向对象设计、模式、UML、敏捷方法学和极限编程领域内的资深顾问。他不仅是Jolt获奖图书《敏捷软件开发:原则、模式与实践》(中文版)(《敏捷软件开发》(英文影印版))的作者,还是畅销书Designing Object-Oriented C++ Applications Using the Booch Method的作者。MartinPattern Languages of Program Design 3More C++ Gems的主编,并与James Newkirk合著了XP in Practice。他是国际程序员大会上著名的发言人,并在C++ Report杂志担任过4年的编辑。

发表于 @ 2006年08月30日 11:36:00|评论(loading...)|编辑

新一篇: 使用Mock Object危险么?(原文最终修订于 2006-09-02 下午03:53:51) | 旧一篇: 性能调优--永远超乎想象 (原文最终修订于 2006-08-28 晚上11:48:38)

评论

#myan 发表于2006-08-30 18:26:00  IP: 218.247.0.*
Hi Uncle Bob, I'm not defending C++ but I truely believe that its inferior proformance is due to cygwin's bad implementation of iostream library.

Sure, Java is almost as fast as C and C++ now regarding to its execution speed. But its memory consumption is far larger not only than C and C++, but sometimes Python and Ruby. A realistic big Java application can easily eat up your gigabytes of memeory, which leads to frequent memeory-disk swap, and results in very bad overall performance. So I think the popular performance comparison with mathematical algorithms is not very convincing. That's my cent of point.

BTW, I fully appreciate your opinion and enthusiasm about Ruby, I hope and believe the future of programming belongs to freedom languages like Ruby and Python.
#ilovevc 发表于2006-08-30 21:07:00  IP: 58.60.214.*
同楼上不同,我确实在维护C/C++。
第一,除了C++外,我没有找到你是如何实现main函数的。如myan所说,C++的iostream由于在编译时可以知道变量类型,因此“理论”上比printf快,但是××实际××上比printf慢数量级。
第二,cygwin确实可能比较慢,如果在Linux下,你当然可以使用GCC,但是既然在Windows下,我觉得使用VC还说主流些。
第三,如果在generate函数中Java使用 Arrays.fill(sieve, true),那么为什么C++就要显式使用for手动循环?而不是更加具有效率的memset?我发现大部分网上流传的代码在实现C/C++版本的时候总是“有意无意”的使用蹩脚的写法。这个也不例外。从而可以得到一个“最后要关注的东西“。
因此,我劝你也可以再重新掂量掂量。

#阿呆 发表于2006-08-31 08:51:00  IP: 192.168.0.*
Java的热衷者:用C/C++转过来的人.
#captainwh 发表于2006-08-31 08:51:00  IP: 221.9.35.*
可笑的比较
任何语言, 深挖底层都能看到都是用c语言实现的
用c写的java, 执行起来比c还快? 有没有脑子?
#henry 发表于2006-08-31 01:43:00  IP: 38.96.144.*
This benchmarking has nothing to do with implementation of iostream -- the time has been obtained before calling any iostream functions.
#UKO 发表于2006-08-31 09:19:00  IP: 218.80.84.*
同意楼上的。

bool *sieve = new bool[max];
for (int i=0; i<max; i++) sieve[i] = true;
这条显然不优雅。效率也不好
#igray 发表于2006-08-31 09:20:00  IP: 58.61.149.*
一个简单的算法能说明什么?作者C++编码能力,我只想,的确很差!用for循环,来填数组,真是服了你了。max的值增大时,C++的性能完全就折耗在这里了。再好的程序设计语言,也不能避免被人写出垃圾代码。单从效率与性能上来讲,C++无益是最快的,Java也不谈了,在.net面前,除了还剩点跨平台的优势(真的跨平台么?说直了就是骗子),还能有些什么?别跟我扯C语言速度快,那用汇编还更快了。
#hehe 发表于2006-08-31 10:09:00  IP: 61.189.35.*
平常如果没有性能要求,都是这样写C++的吧,应该可以反映出 *平常* 的速度。
#xxx 发表于2006-08-31 09:39:00  IP: 222.66.38.*
哈哈,看了这种C++的代码,真是笑死我了。
我还可以写出比ruby更慢的c++代码呢。
#hehe 发表于2006-08-31 10:09:00  IP: 61.189.35.*
平常如果没有性能要求,都是这样写C++的吧,应该可以反映出 *平常* 的速度。
#ahhy 发表于2006-08-31 09:41:00  IP: 218.94.57.*
无语,连这样的“人物”也在评论,“认真”的比较语言的“优劣”,连代码都不会写,还在那“自鸣得意”!

他分明是在用 C 写 Java 的代码,用 Java 写 C++ 的代码,然后开始评头论足:(
#duzhe  发表于2006-08-31 10:06:00  IP: 222.174.139.*
让事实说话,请用自己喜欢的语言,写出完成上述任务的代码测试之!
#jadedrip 发表于2006-08-31 10:25:00  IP: 60.186.189.*
for (int i=0; i<max; i++) sieve[i] = true;
还是在循环中....

这样的代码居然还是和 Java 的速度相似?作者从侧面证明了 Java 的速度到底有多么的慢!
#YaYapei 发表于2006-08-31 10:49:00  IP: 220.229.43.*
同意楼上的,除了那个循环比较蠢外,楼主分配的那快内存也没有释放。请楼主把内存分配那块改改,然后不要往屏幕输出,改成往文件里输出,楼主就会发现C++的程序跟火箭一样快,而java顶多就是保时捷,而ruby就是拖拉机了。
#C++ User 发表于2006-08-31 10:27:00  IP: 219.134.89.*
第一、这个C++代码写得真是差!
第二、要测试性能,却把I/O算进去了。难道不知道I/O很慢吗?
第三、作者没有释放C++的内存,你以为是java啊。
第四、取时间也不是这样取的吧,C++取时间的函数不会用啊,凭空多了一组浮点运算。我想他的CPU是Inter的,如果是AMD的话,这点会好些。


#非典型秃子 发表于2006-08-31 10:53:00  IP: 202.95.81.*
int main(int ac, char** av) {
for (int i=100000; i<=5000000; i+=100000) {
double time = generate(i);
cout << time << endl;
}
}
--------------------------
改成这样试试看:
int main(int ac, char** av) {
vector<int> arr;

for (int i=100000; i<=5000000; i+=100000) {
double time = generate(i);
}
copy(arr.begin(), arr.end(), ostream_iterator<int>(cout, "\n");
}
#fengj 发表于2006-08-31 10:32:00  IP: 219.220.210.*
其实用循环赋值是C和C++的常用方法,使用memset函数是有限制的,如分配的数值都不相同又怎么办?赋值的是类的对象能用memset或memcpy吗?
关键是每种语言实现的是相同的算法,即Java也是循环赋值,这就是在同一个基础上进行比较。
我到是认为,应该进行复杂运算比较,不要只是用循环来比较,这样意义不大!
#fangrk 发表于2006-08-31 11:05:00  IP: 61.177.61.*
C++代码写的不怎么样

空间性能怎么不做比较?
#phoenixsh 发表于2006-08-31 11:35:00  IP: 222.67.9.*
奇怪,贴上来缩进都不见了.
#phoenixsh 发表于2006-08-31 11:27:00  IP: 222.67.9.*
何以见得Java就一定会浪费很多内存?拜托给点证据。其次,用C实现的Java,确实有可能比C还要快。这里不谈了,我们做点正经事。

为了方便测试,我把代码调整了一下:第一不把数组初始化的时间计入(测试数据表明,这样对C++没有好处。第二,循环中每次都去调用sqrt(max),其实是个循环常量,提取出来(测试数据表明影响不大)。第三,统计全部时间,而不是在循环中每次计时。

调整后的Java和C++代码分别如下。在我的机器上,Java版使用的时间为3.5秒,而C++版的为4.0秒。如果不做第一点改动,则时间分别是4.3秒和4.8秒;注意Java的Arrays.fill是以for循环实现的。如果把C++版本的赋值改为memset,时间也就是4.3秒。改成VC版本之后,C++的测试数据基本上没有什么变化。这里把代码也列上了。

不过以上C++版本全部是未优化过的 (Java前面确省已经使用了)。下面的代码在打开全部优化之后的时间分别是:
Cygwin 3.3 (使用g++ -O3选项)
VC 3.4 (使用release版本)

可见在这里C++还是比Java快一点一点的。C++粉丝们可以睡个安稳觉了。

JAVA:
public class GeneratePrimes {
public static double generate(int max) {
//long start = System.currentTimeMillis();
boolean sieve[] = new boolean[max];
Arrays.fill(sieve, true);
sieve[0] = false;
sieve[1] = false;
int maxsqrt = (int)Math.sqrt(max);
long start = System.currentTimeMillis();
for (int i = 2; i < maxsqrt; i++) {
if (sieve[i]) {
for (int j = 2*i; j < max; j+=i) {
sieve[j]= false;
}
}
}

return (System.currentTimeMillis() - start)/1000.0;
}

public static void main(String args[]) {
double time = 0.d;
for (int i=100000; i<=5000000; i+=100000) {
time += generate(i);
}

System.out.println(time);
}
}

Cygwin/C++:
#in
#beyking 发表于2006-08-31 11:48:00  IP: 219.136.98.*
这样而比较没有任何意义;

我相信普遍来说,还是C、C++的程序最快,现在是,以后也是!

如果为了代码的干净、简洁、易维护,我会使用Python,而不是Ruby
#vcclass 发表于2006-08-31 11:49:00  IP: 222.66.84.*
他妈的鸟人,JAVA不就是用C++封装的嘛,还能比C++更快,撤鸡巴弹。至于什么Ruby的什么烂语言,Ruby也能叫语言,说不定是他妈的用JAVA封装的,另外说白了,就因为他妈的是小日本做的,即使全世界的人都用,老子我也不用。
#sb 发表于2006-08-31 12:30:00  IP: 218.17.221.*
sb
#ilovevc 发表于2006-08-31 12:35:00  IP: 152.104.165.*
to henry:
确实看错了,与IO无关。楼上myan误我。

#hyifeng 发表于2006-08-31 12:39:00  IP: 202.105.135.*
乱七八糟

csdn的人到底是怎么了, 都不看程序就发高论.

什么时候把IO的时间算进去了?
什么时候把浮点运算的时间算进去了.

拜托那些风言风语的增大眼睛看清楚先好不好.
#hyifeng 发表于2006-08-31 12:42:00  IP: 202.105.135.*
用c++的内存分配器来和java斗一斗.
#什么跟什么哦 发表于2006-08-31 12:44:00  IP: 222.209.220.*
白痴都知道
c/c++做的东西
按同等优化的程序
不晓得比java 还有吗个什么ruby 快
那里去了
#apathy 发表于2006-08-31 13:09:00  IP: 192.168.21.*
抵制ruby,日本人的东西!!!
#CHen 发表于2006-08-31 13:11:00  IP: 155.35.248.*
感觉比较基本公平。
附:
Arrays.fill()
public static void fill(boolean[] a, boolean val) {
fill(a, 0, a.length, val);
}

public static void fill(boolean[] a, int fromIndex, int toIndex,
boolean val) {
rangeCheck(a.length, fromIndex, toIndex);
for (int i=fromIndex; i<toIndex; i++)
a[i] = val;
}
#chen 发表于2006-08-31 13:20:00  IP: 155.35.248.*
public class GeneratePrimes {

// compiled from: GeneratePrimes.java

// access flags 1
public <init>()V
L0 (0)
LINENUMBER 3 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init>()V
RETURN
L1 (4)
LOCALVARIABLE this LGeneratePrimes; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1

// access flags 9
public static generate(I)D
L0 (0)
LINENUMBER 6 L0
ILOAD 0
NEWARRAY T_BOOLEAN
ASTORE 1
L1 (4)
LINENUMBER 7 L1
ALOAD 1
ICONST_1
INVOKESTATIC java/util/Arrays.fill([ZZ)V
L2 (8)
LINENUMBER 8 L2
ALOAD 1
ICONST_0
ICONST_0
BASTORE
L3 (13)
LINENUMBER 9 L3
ALOAD 1
ICONST_1
ICONST_0
BASTORE
L4 (18)
LINENUMBER 10 L4
ILOAD 0
I2D
INVOKESTATIC java/lang/Math.sqrt(D)D
D2I
ISTORE 2
L5 (24)
LINENUMBER 11 L5
INVOKESTATIC java/lang/System.currentTimeMillis()J
LSTORE 3
L6 (27)
LINENUMBER 12 L6
ICONST_2
ISTORE 5
L7 (30)
GOTO L8
L9 (32)
LINENUMBER 13 L9
ALOAD 1
ILOAD 5
BALOAD
IFEQ L10
L11 (37)
LINENUMBER 14 L11
ICONST_2
ILOAD 5
IMUL
ISTORE 6
L12 (42)
GOTO L13
L14 (44)
LINENUMBER 1
#读者 发表于2006-08-31 10:36:00  IP: 222.174.139.*
有人用惯了镰刀割麦子,他尽职尽责的磨刀刃,找好的木棍做手柄,为此他感到很高兴,对那些不安分寻求别的割麦工具的人说三道四.他一割倒了一片了,看那寻求别的割麦工具的人一根麦子还没有割倒,更坚信自己的选择是正确的,寻求别的割麦工具的人开来了收割机,不一会就割了大半,用惯了镰刀的人看到用收割机的人快割完了,心理一阵烦躁,仔细一看用收割机的人正对着一块小边角地发呆又笑了,不久,有人来请用收割机的人去收割麦子,支付订金,用惯了镰刀割麦子的人又愤愤不平起来,说收割机有什么了不起,还不是在镰刀的基础上发展起来的吗?
#Aaron 发表于2006-08-31 14:03:00  IP: 155.35.248.*
真开心看到大家热火朝天的技术讨论,希望通过此文大家的对于编程语言、性能等方面会有更深的理解。说实在的,我本人在翻译过程中也都感觉增进不少。
不过咱们是不是也别光在这儿自己讨论了,也问问看原作者是怎么想的。
我这儿已经帮着把一些提问转发给了Uncle Bob(包括myan帖子的),大家看看还有什么希望直接问Uncle Bob的,或是有什么对他说的都可以贴出来,我会尽力帮助询问的!(如果帖子确实有意义,我会翻成英文发给Uncle Bob)
期待各位更多有内容的帖子!
#良少 发表于2006-08-31 14:21:00  IP: 211.144.96.*
C++的这些人呢!又跳起来了!
Bob大叔的编程水平不如你?你省省吧!Bob大叔纵横江湖40年,他称霸江湖的时候,你丫的还没生呢!
他写的C++代码,我看应该是C代码。都没有用类。
至于,使用的for循环,我不认为有什么不对。难道现在用C++编程,都不用for循环了吗?
至于I/O,只是最后向屏幕输出了运行时间而已,而且大家都向屏幕输出了,这有什么不对?
你们自己写出认为最好的C++代码,贴出来好了!
连Bob大叔的大名都没听过,我真为你们感到悲哀!

#henry 发表于2006-08-31 14:50:00  IP: 24.193.79.*
何以见得Java就一定会浪费很多内存?拜托给点证据。
Java allows programs to leak memories. To be able to do so, Java has to take much more memory than what is actually used by the program. Furthermore, a sad reality of this world is that producing garbage is always faster than cleaning it up. And for Java (and other garbage-creation (gc) encouraged languages), this means large memory waste is almost doomed.

#sinall 发表于2006-08-31 14:28:00  IP: 218.97.242.*
嗯,观点:
1)这个c++代码确实有问题。
2)这可能正是作者要说明的问题——“我本人还是更喜欢干净、简洁、易维护的代码”。可能是他想从侧面反映c++代码的复杂和不易维护。
3)我本人是支持c++的。^_^
#xreborner 发表于2006-08-31 15:12:00  IP: 218.1.245.*
Both the algorithm and the implementation is bad.
You should test the c++ performance using my code:

#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

void compute_primes(int Bound) // written by xreborner
{
bool* Marks = new bool[Bound];
fill(Marks, Marks + Bound, true);
int Sqrt = (int)sqrt(Bound - 1.0);
for (int I = 2; I <= Sqrt; I++)
if (Marks[I])
for (int J = I * I; J < Bound; J += I)
Marks[J] = false;
delete[] Marks;
}

int main()
{
vector<double> Times;
Times.reserve(50);
double Time = clock();
for (int I = 100000; I <= 5000000; I += 100000)
{
compute_primes(I);
double Temp = clock();
Times.push_back(Temp - Time);
Time = Temp;
}
for (int I = 0; I < (int)Times.size(); I++)
cout << Times[I] / CLOCKS_PER_SEC << endl;
}
#良少 发表于2006-08-31 14:31:00  IP: 211.144.96.*
越看越窝火!C++er个个污言秽语,真他妈的受不了! 用C写的语言,就一定比C慢? 用铁做的轮船,一定会沉下去?
白痴!
不懂即时编译器的原理,就不要胡说八道!即时编译器可以把生成的机器代码根据概率存放在内存中,直接调用!越是大的程序,运行的越是快。这是以空间换速度。你们懂不懂?!傻鸟!不和你们治气了!
#sinall 发表于2006-08-31 14:56:00  IP: 218.97.242.*
素质,注意你的素质!
#xreborner 发表于2006-08-31 15:13:00  IP: 202.120.224.*
Both the algorithm and the implementation is bad.
You should test the c++ performance using my code:

#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

void compute_primes(int Bound) // written by xreborner
{
bool* Marks = new bool[Bound];
fill(Marks, Marks + Bound, true);
int Sqrt = (int)sqrt(Bound - 1.0);
for (int I = 2; I <= Sqrt; I++)
if (Marks[I])
for (int J = I * I; J < Bound; J += I)
Marks[J] = false;
delete[] Marks;
}

int main()
{
vector<double> Times;
Times.reserve(50);
double Time = clock();
for (int I = 100000; I <= 5000000; I += 100000)
{
compute_primes(I);
double Temp = clock();
Times.push_back(Temp - Time);
Time = Temp;
}
for (int I = 0; I < (int)Times.size(); I++)
cout << Times[I] / CLOCKS_PER_SEC << endl;
}
#xreborner 发表于2006-08-31 15:14:00  IP: 202.120.224.*
The C++ code is too BAD!!!
Both the algorithm and the implementation is bad.
You should test the c++ performance using my code:

#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

void compute_primes(int Bound) // written by xreborner
{
bool* Marks = new bool[Bound];
fill(Marks, Marks + Bound, true);
int Sqrt = (int)sqrt(Bound - 1.0);
for (int I = 2; I <= Sqrt; I++)
if (Marks[I])
for (int J = I * I; J < Bound; J += I)
Marks[J] = false;
delete[] Marks;
}

int main()
{
vector<double> Times;
Times.reserve(50);
double Time = clock();
for (int I = 100000; I <= 5000000; I += 100000)
{
compute_primes(I);
double Temp = clock();
Times.push_back(Temp - Time);
Time = Temp;
}
for (int I = 0; I < (int)Times.size(); I++)
cout << Times[I] / CLOCKS_PER_SEC << endl;
}
#xreborner 发表于2006-08-31 15:16:00  IP: 202.120.224.*
sorry. 不小心发重了
#phoenixsh 发表于2006-08-31 15:16:00  IP: 222.67.9.*
to henry:
No language allows programs to leak memories. Java frees programmers from fruitless manual memory management and it helps a lot, both in terms of development efficiency and defect numbers.

Then I suppose you know nothing abouut generational garbage collection. Believe it or not, with that method allocation could be done in constant-time and freeing is, free! That says, it's much faster than manual management of C/C++.

By the way, garbage collection has longer history than C++ or C.
#xreborner 发表于2006-08-31 15:18:00  IP: 202.120.224.*
sorry. 不小心发重了
#airy 发表于2006-08-31 16:27:00  IP: 211.167.237.*
语言不是问题,关键在于怎么去写.
#阿呆 发表于2006-08-31 17:20:00  IP: 192.168.0.*
一个不错的技术Blog:
http://blog.csdn.net/cxxsoft/
#C++ Fan 发表于2006-08-31 17:29:00  IP: 155.35.248.*
比较没有意义.C++的new使用的是系统调用.Java的new是Java启动时事先分配好的内存再次分配.所以那么多的new就是那么多次的系统调用,明显偏慢.没什么稀奇.如果都同时使用一块事先分配好的内存,再比比就知道结果了.
#phoenixsh 发表于2006-08-31 17:48:00  IP: 222.67.9.*
>C++的new使用的是系统调用
这句话恐怕有失C++ Fan的水准。
#derek 发表于2006-08-31 18:04:00  IP: 58.246.25.*
别忘了作者写这三个程序的出发点是什么,只要三个程序都用for,都输出到屏幕上,那么运行时间是有可比性的,如果对某个程序做了优化的算法后和其他两个比,那么就忽略了作者写这三个程序的根本目的.
每种语言都有其适合的东西,取其所长就好,就像大部分人会用VB去写GUI,用C++去写后台处理一样,前者方便后者高效.个人觉得C绝对是写系统级程序的首选,Java/C++各有所长.
还是那句话,看你需要什么了,符合你需要的就是好的
#hehehe 发表于2006-08-31 19:58:00  IP: 218.0.122.*
Bob 大叔的编程水平确实不怎么样,也就是江湖骗子这个级别吧,写几本书弄弄咨询之类的。
就那本敏捷软件开发里面,代码写的也是惨不忍睹,逻辑错误比比皆是
#猫哥哥 发表于2006-08-31 21:37:00  IP: 202.104.18.*
fucking the c++er
#phoenixsh 发表于2006-08-31 21:29:00  IP: 218.82.52.*
I really don't understand why so many C++ fans find this article offensive. Yeah it is true that Uncle Bob draw a conclusion counter-intuitive, which says Java is a bit faster than C/C++. But he also stated that he didn't turn on optimization for C++ code, right? So before pointing your fingers at him, why don't you grab the code, compile it with all possible optimizations, run and test its performance, and then compare it with its Java version? Is it that hard to do so? In case you are really lazy, you could refer to my code above, which shows optimized C++ code is slightly faster than its Java version. If you are still upset, please write a faster C++ program to invalidate his point.

No more bad words! Or it will be consider definition of "C++ fan".
#sheismylife 发表于2006-08-31 23:07:00  IP: 58.246.244.*
SGI STL首先会分配内存池,因此不会重复的调用new,用deque来管理数组效率会提高很多,代码也很优雅。
c的写法更夸张memset搞定。
c/c++的代码效率看程序员的水平,感觉bob是在故意贬低c++
#sheismylife 发表于2006-08-31 23:13:00  IP: 58.246.244.*
xreborner 的c++代码里面不应该用vector,而应该用deque,vector太慢了。
#无聊……………… 发表于2006-09-01 00:11:00  IP: 172.16.128.*
一群无聊的哥们,C++也好,JAVA也罢,两者各有其用,都为我所用不更好吗?为什么一定你斗我?我打你?
#henry 发表于2006-09-01 00:17:00  IP: 38.96.144.*
to phoenixsh,

Look, I am not a newbie, so don't bother educating me with some basics you gotta know. You obviously didn't get my points.

My word "leak memories" there is of general sense. Simply speaking, it means make the memory unusable for some time. In C/C++, this usually means the memory remains at an unusable state until the execution is finished. For Java, this means until the next garbage collection cycle is finished. Despite of the difference, they are the same in essense. Producing memory garbages is leaking memory, like it or not.

The rest of my point has little to do with garbage-collection speed. It simply says:

Garbage takes space.

This is true in both reality and in programs, and I assume you have this common sense. Because of that, Java and some other with-gc languages is doomed to waste a lot of memory for most time. The last point leads to answering your question: 何以见得Java就一定会浪费很多内存.

BTW, For your naive belief about generational gc, I suggest you catch up some of its basics.
#gccr 发表于2006-08-31 23:52:00  IP: 219.236.76.*
同意楼上一位兄弟的话,Bob大叔写程序几十年,从C/C++还始写,出过一本95年就出过C++面向对象程序编程的书,<敏捷软件开发>更是牛书一本,所以,其写程序的水平是不用怀疑的.

C++也就是一门语言,C++效率低,C++ 的Fans就不乐意了,其实C++可能还不如Delphi快呢.
#winbondowen 发表于2006-09-01 08:56:00  IP: 218.4.53.*
无论中编程语言,最大优化自身的代码,在加一个理想的编译器,程序的性能就能得到提升。
对于提升的多少,是设计这下语言与编译器的家伙要思考的,语言存在的也是他们考虑的。我们可以选择适当的语言写相当的程序。
Java能写firmware吗?
用汇编能写WEB程序吗。
汇编相对其他语言运行的快,是因为他直接对应机器码,
其他语言要通过很复杂的步骤才对应到机器码。
#gussing 发表于2006-09-01 09:01:00  IP: 220.248.25.*
java程序员可真有意思,往高的说要比.net好无数倍,往低的说要比c++快无数倍,反正一句话,java语言天下无敌!
金庸小说中也有类似的门派,那就是星宿派。让我们一起来喊,java老仙,千秋万代,一统江湖!
#yjh1982 发表于2006-08-31 22:29:00  IP: 218.64.182.*
离开csdn多年,javer sb依然没少.
#phoenixsh 发表于2006-09-01 09:15:00  IP: 222.67.9.*
楼上,Java确实可以写firmware,比如给Java Card写程序。
#phoenixsh 发表于2006-09-01 09:54:00  IP: 222.67.9.*
to henery:

Well, it's not newbies' patend to sometimes forget the obvious fact that memory fraction also takes space. Oh no, those experienced can build their own memory pools to fight against that, if it is considered beneficial. Can I naively consider that as degenerated GC?

You point heavily depends on how you define "a lot of memory" and "waste". I hate to remind experienced developers of basic points but I have to tell you that, Java doesn't prevent you from reusing memory. Check out IBM Secure Shell Library for Java if you are still skeptical.

Finally, isn't the fundamental idea behind generational GC is that most objects die young? Is it waste to trade in a little memory for CPU cycles?
#Aaron 发表于2006-09-01 11:13:00  IP: 208.232.182.*
大家注意了,以下是大师间思维的碰撞,我已翻为中文,请关注: myan vs. Uncle Bob

[myan]-- Uncle Bob你好,
[myan]-- 我不是有意冒犯C++,可是我相信这么差劲的性能是原自cygwin编译器对iostream库的糟糕的实现。
[Bob对上文回复]-- 很可能,虽然这个算法没有涉及到太多的iostream。
[myan]-- 当然,就执行速度而言,Java现在已经和C/C++相仿了。可是,内存上的开销却远比仅用C/C++写的程序要大得多,Python和Ruby有时也是。一个真正的大型Java应用程序会很容易吃掉上GB的内存,甚至还会导致内存泄漏,因而导致整体性能变得很糟糕。所以,我认为这种普遍通过算法来比较性能的方式并不是很有说服力。以上是我的个人观点。
[Bob对上文回复]-- 我同意你所说的JVM可能会占用很大内存的说法。然而,如果你假设已经有了这么多内存在那儿,那这个应用程序所占用内存就一点儿也算不上是非常大。况且,你也可以把堆内存的占用约束在一个相对较小的内存范围内,这样就能防止内存泄漏。所以在大多数情况下,出于经济上的考量,人们往往会选用Java开发应用而舍弃C++。

[myan]-- 除此之外,我完全赞成你对Ruby的观点和那份热情,我希望也相信程序设计的明天会属于那些像是Ruby或Python的自由语言...
#Aaron 发表于2006-09-01 11:17:00  IP: 208.232.182.*
由于中美间时差关系(正好相差12小时左右),我们白天的帖子转到Bob大叔手里已是晚上,往往我们睡了他才能回复。
所以大家少安毋躁,欢迎更多精彩的技术讨论。
#sinall 发表于2006-09-01 08:36:00  IP: 218.97.242.*
作者如果拿java和c做性能比较的话,甚至可以得出java可以写unix的结论!
#phoenixsh 发表于2006-09-01 11:01:00  IP: 222.67.9.*
to heney again:

If you define "leak memories" that way, then I wonder whoelse can understand your point. Usually when developers talk about memory leaking, they mean a chunk of memory you could never use for the program running. If you use terms in an uncommon way, please define it clearly so that the argument could be more constructive.

>Furthermore, a sad reality of this world is that producing garbage is always faster than cleaning it up.
Talking about GC speed is a valid response to your above assertion, which is essential part of your point regarding "large memory waste". Besides, many C++ programmer propose "allocate many times, free once", which is ultimately a primitive kind of generational GC.
#derek 发表于2006-09-01 12:54:00  IP: 58.246.25.*
引用:henry 发表于2006-09-01 12:23:00

"producing garbage is always faster than cleaning it up." no matter how fast your gc is.
#phoenixsh 发表于2006-09-01 14:18:00  IP: 222.67.9.*
to Aaron: 能否把Bob的原文也贴出来?谢谢!
#henry 发表于2006-09-01 11:56:00  IP: 24.193.79.*
What do you try to argue here by talking about memory fraction? Are you trying to say memory fraction is memory leak or to argue that Java saves memory or to correct me about memory faction (but I didn't mention it here before this one)? If you want to talk about memory frags, pools, etc, you are welcome to bring them up in a sensible way. Your words here don't make any sense to me.

"a lot of memory" and "waste" are just of common meanings. Needly to say, their precise meanings are case-dependent. The bottom line is that gc-based programs are doomed to consume more memory than they actually need. In reality, Java applications consume really **a lot** more memory than equivalent C/C++ ones. You may be able to do a benchmark if you haven't any experience of this yet.

I didn't say Java would prevent reusing memory. Memory can of course be reused after garbage is cleared. This is very basic, and I don't have to check out some Java program in order to be aware. You have to stop assuming in this way.

I am not a Java fan, and so, sorry, no interest in checking out IBM blah. I don't know why you mention it. If you want to argue/discuss effectively, make your point clear and relevant, or I have to ignore.

Finally, there is nothing wrong with gGC as being a GC. I don't hate/love GC. GC is in general a worthwhile idea, though not without limitations.
#phoenixsh 发表于2006-09-01 14:08:00  IP: 222.67.9.*
>I believe most of experienced programmers will understand what I mean by that sentense.
Well, readers will judge by themselves.

>You can't clean garbage right after it is produced.
True. But this is not the most effective way regarding execution speed. For a typical server, after a long time of running, old objects should be very stable and most objects just got allocated and then freed (or become garbage) very soon (die young). With manual mem mgnt you have to fight against fraction, traverse among the linked list and it's time consuming. This is the reason I brought up fraction. It's just totally relevant. gGC can adddress this problem (I didn't say it is allmighty). It's also true that you have to use additional memory for gGC/GC. A lot more? Don't make assumptions before you multiply average life of die-young objects by their average size (and then object count).

>In reality, Java applications consume really **a lot** more memory than equivalent C/C++ ones. You may be able to do a benchmark if you haven't any experience of this yet.
You are the one making assertion here, so it's your responsibility to show me your proof.

>Memory can of course be reused after garbage is cleared.
It's a true pity that you interpreted mem reusing that way.
#winbondowen 发表于2006-09-01 12:18:00  IP: 218.4.53.*
To phoenixsh:
你认为JAVA是万能的吗?
  用一个哲人的话说
  一个全能的人就是全面庸才
  什么多行,什么多不精


#minjun 发表于2006-09-01 15:26:00  IP:
myan也算大师,
还大师间的碰撞?

别恶心了.


另,你们这些学java的理智一点可以吗?
ok?
don't be naive!
#henry 发表于2006-09-01 12:23:00  IP: 24.193.79.*
I believe most of experienced programmers will understand what I mean by that sentense. And note I didn't try to redefine its meaning, but use this phrase to express a similar meaning. This is a common usage of words...

You can't clean garbage right after it is produced. As long as this is true, it will stand that "producing garbage is always faster than cleaning it up." no matter how fast your gc is.
#shengfang 发表于2006-09-01 15:00:00  IP: 218.5.3.*
0910 C# WIN VS vc++ 性能PK

Robert C. Martin博客中文版 面向对象设计、模式、UML、敏捷方法学和极限编程领域
三大编程语言的性能PK--Java, C/C++和Ruby

我懒得装JAVA了,以前的什么JB/ECLIPSE什么的好像被干掉了,
都是用的DEBUG
Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.
P:\测试代码\cctest\ConsoleApplication1\ConsoleApplication1\bin\Debug>ConsoleApplication1.exe
6140.625
P:\测试代码\testvc\Debug>testvc
6.329

RELEASE:
P:\测试代码\testvc\Release>testvc
6.123

P:\测试代码\cctest\ConsoleApplication1\ConsoleApplication1\bin\Release>ConsoleApplication1.exe
5765.625

呵呵,C#比C快!
http://www.shengfang.org/blog/p/0910CcWINVSvcpK.php
#phoenixsh 发表于2006-09-01 12:29:00  IP: 222.67.9.*
to winbondowen:
我从来没有说Java是万能的。
#henry 发表于2006-09-01 12:40:00  IP: 24.193.79.*
Not sure what is going on, but Bob seems to make pretty lame replies.

First of all, iostream implementation has nothing to do with these benchmarks. Saying 很可能 is obviously an error.

Second, a key point that myan's post actually implies is that this benchmark is not representative of the reality since memory consumption, which can greatly affect performance, is not taken into account. Bob's reply to this is nearly unrelevant to this point.
#To phoenixsh 发表于2006-09-01 16:52:00  IP: 208.232.182.*
因为Bob大叔的blog跟我们的不一样,他那里可以直接在评论上在给批注的。
所以想看原文的朋友还是直接去Bob大叔网站好了,另外,Bob也一定会欢迎英文好的朋友直接给出英文的评论。
http://www.butunclebob.com/ArticleS.UncleBob.SpeedOfJavaCppRuby
#Aaron 发表于2006-09-01 16:52:00  IP: 208.232.182.*
To phoenixsh
因为Bob大叔的blog跟我们的不一样,他那里可以直接在评论上在给批注的。
所以想看原文的朋友还是直接去Bob大叔网站好了,另外,Bob也一定会欢迎英文好的朋友直接给出英文的评论。
http://www.butunclebob.com/ArticleS.UncleBob.SpeedOfJavaCppRuby
#phoenixsh 发表于2006-09-01 17:14:00  IP: 222.67.9.*
to Aaron: 多谢!
#awarak 发表于2006-09-01 21:04:00  IP: 218.106.82.*
J2ME真恶心。

完毕。
#h 发表于2006-09-02 00:03:00  IP: 38.96.144.*
to arron,

Possibly, although iostream had very little to do with this algorithm. -UB

[Bob对上文回复]-- 很可能,虽然这个算法没有涉及到太多的iostream。
This is a mistranslation of UB's reply. "Possibly" means there is tiny chances to be true. It is a polite way to say "impossible". "had very little to do" is almost the same as "had nothing to do". Your translation has an opposite meaning.
#henry 发表于2006-09-02 07:34:00  IP: 38.96.144.*
to phoenixsh

> True. But this is not the most effective way regarding execution speed...

Not necessarily. What you said is only partially true. A counta-example can be very easy to cook up: say a linked list whose nodes are scatterred crossing different generations, when the list is leaked, how the gc will clean up? You will have to scan all generations to clean it completely, won't you?

There are ways for C++ programmers to release memory right away without imposing a big runtime overhead, believe it or not. Java guys don't seem to know and won't be able to get (pity).

A final remarks: When talking about efficiency (space and speed), Java and dynamic languages are always the loser because these languages are not designed to be so. This is just not the field these lang can beat C/C++. So why not be smart and avoid being beat up?
#henry 发表于2006-09-02 07:37:00  IP: 38.96.144.*
> these languages are not designed to be so

by "be so", I mean "be space and speed efficient".
#phoenixsh 发表于2006-09-02 10:13:00  IP: 218.82.55.*
to henry:

>a linked list whose nodes are scatterred crossing different generations

No language could save your fate from bad design. But, suppose unfortunately you have already put objects with different life cycles into the same container, then why would you like to collect the container again and again? Or are you refering to the contained object? ("the list is leaked" is still ambiguous even with your version of "leak") First it's programmer's responsibility to remove it from container when it is no longer needed in the program. Second, after it is removed from container, collecting it is nothing to do with the container. Finally, do you know objects could be moved by GC in Java?

>This is just not the field these lang can beat C/C++.

Now you are cheating and changing the topic. Nobody is try to beat C/C++ here (in space and time efficiency, but still there are exceptional cases), so don't be defensive. (Did Uncle Bob say he didn't turn on optimization options?) The point here simply is, Java program is not times of slower or times of bigger than C/C++, as you blindly suppose. But if you consider ten or twenty percent as "a lot" or "much", you should state it at the beginning since this is not common sense.

>Java guys don't seem to know and won't be able to get (pity).

Face the fact. You don't even understand memory reusing and you dare to claim yourself experienced C/C++
#xreborner 发表于2006-09-02 12:37:00  IP: 202.120.224.*
To phoenixsh:

Java program is really times of slower and times of bigger than C/C++, as long as you compare them on some more complicated algorithm or program. The tested program here is too simple, it just proves that for some very simple program Java can be as fast as C++.

I have tested Java and C++ on a more complicated algorithm, which shows that Java is much slower and space wasteful. In practice you can also see that CBuilder X is much slower than CBuilder 6.
#dwbclz 发表于2006-09-02 14:45:00  IP: 192.168.0.*
我的一些见解……
http://blog.csdn.net/dwbclz/archive/2006/09/02/1159882.aspx
#phoenixsh 发表于2006-09-02 20:22:00  IP: 58.33.22.*
to xreborner:

Could you please show us your codes? I would certainly like to take a look.
#fdyjfd 发表于2006-09-02 21:14:00  IP: 61.149.96.*
最直接的比较就是看编译完后的汇编码,让大叔把汇编码列出来不就得了。省得从源代码看不出原因。
另说一句,效率与高级语言的语法无关,只与编译器有关。可以写一个垃圾C++编译器让它比Ruby慢100倍,不知谁有这个兴趣实现一个。
#xreborner 发表于2006-09-02 21:11:00  IP: 218.1.245.*
I have written a convex polygon computing algorithm, which computes the smallest convex polygon containg a given set of n points on the plane in O(n*log(n)) time. I implemented and tested it in C++ and Java. The result shows that Java is at least 5 times slower than C++, and is sometimes 10 times slower. Moreover, Java used much more memory than C++. In my 512MB RAM machine, the c++ program runs normally when n is larger than 20,000,000, while the Java program throws OutOfMemoryError exception when n=12,000,000.

The codes are here:

C++ ( compiled in GCC with option -O3 ):

include <iostream>
include <cstdio>
include <algorithm>
include <ctime>

using namespace std;

struct point
{
int X, Y;
};

struct point_less
{
bool operator()(const point& A, const point& B) const
{
return A.X < B.X || A.X == B.X && A.Y < B.Y;
}
};

long long cross_mul(const point& O, const point& A, const point& B)
{
return (long long)(A.X - O.X) * (B.Y - O.Y) - (long long)(B.X - O.X) * (A.Y - O.Y);
}

int compute_convex(int N, point Points[])
{
sort(Points, Points + N, point_less());
if (N <= 1) return N;
int UN, LN;
point* Ups = new point[N];
point* Lows = new point[N];

UN = 1;
Ups[0] = Points[0];
for (int I = 1; I < N - 1; I++)
if (cross_mul(Ups[UN - 1], Points[I], Points
#xreborner 发表于2006-09-02 22:16:00  IP: 202.120.224.*
语言和效率还是有点关系的,语言的某些内在缺陷会对效率有所限制
#henry 发表于2006-09-03 01:25:00  IP: 24.193.79.*
to phoenixsh,

You don't seem to understood a thing that I have said so far. Maybe it was my English. Anyways, let me try to clarify once more.

My linked list example was just for correcting your naive belief that gGC could, bang, magically collect your garbage for free (your words here: "with that method allocation could be done in constant-time and freeing is, free!"). This kind of things won't happen in both reality and in theory. Even for die-young objects, you still have to scan the corresponding generation blocks to find out. That is nothing close to "free" -- you need to know.

when I said "the list is leaked", I meant the list, not the nodes. A dictionary can help if you can't distinguish.

FYI, the meaning of leak here is not my invention. You don't seem to know much outside Java, do you?

My word "This is just not the field these lang can beat C/C++." is a general comment. It has nothing to do with you or UB, and why do you think I cheat and change topic? Your response is odd.

BTW, if you agree with that statement, then I think you sound smart in this regard. And if you are really smart, you need to do smart thing by refraining yourself from saying things like the following to experienced C/C++ programmers in the future:

"But this is not the most effective way regarding execution speed.",

"fruitless manual memory management",

&quo
#henry 发表于2006-09-03 01:59:00  IP: 24.193.79.*
效率与高级语言的语法无关,只与编译器有关。

In reality, the two are more or less related. This is mainly because langs have to make assumptions about a few key things, e.g., memory. The closer the assumptions to the reality, the higher potential for programs to be efficient (in run and space).

For example, Fortran, C/C++, Pascal assume a flat finite memory, which is very close to reality. And programs of these langs don't have too much memory-related overhead and normally are not allowed to leak memory. Lisp assumes a list type of memory structure. An intermediate layer transforming this view to the real memory cannot be avoided. Java assumes a flat infinite memory, so programs are allowed to leak memory as much as they want and the VM will have to do the dirty work to guarrantee the "infinite memory" assumption to the programs. This dirty work is not an easy feat and often doing it slows the whole machine down.

#fdyjfd 发表于2006-09-03 06:00:00  IP: 61.149.96.*
to henry
那只不过编译器没做好罢了,比如对本文这个算法来说。不管java也好C++也好,要做的事情都是一样的,又假设目标平台也是一样的,那么最完美的编译器会编译出一样的也是再也不能更快的代码了,这样编译器就是我说的那种,只是现在无法实现罢了
#dwbclz 发表于2006-09-03 10:00:00  IP: 192.168.0.*
大叔的代码的效率主要体现在这一句:
for (int j=2*n; j<max; j+=n)
sieve[j] = false;
实际上C++的代码比Java还是要优化一些,因为
无需作太多RuntimeCheck。
不过由于处理器的高速缓存命中率的问题,导致
导致两者效率相差无几。
楼上有提到memset和iostream的,其实仔细看一下
代码就知道跟iostream无关的。测试一下便可以找到
关键性代码了。

有兴趣的可以看一下我的测试,链接如下:
http://blog.csdn.net/dwbclz/archive/2006/09/02/1159882.aspx
#xreborner 发表于2006-09-03 13:04:00  IP: 218.1.245.*
to chengmeng:

我给的代码里早就把i*2改成i*i啦,你这个old了
#chengmeng 发表于2006-09-03 13:06:00  IP: 221.226.2.*
没看到。毕竟这么多人评论,一条一条看不现实
#xreborner 发表于2006-09-03 12:49:00  IP: 218.1.245.*
to fdyjfd:

首先,你要明白,不存在最完美的编译器。
其次,你要明白,即使存在最完美的编译器,编译的结果仍然受语言的某些特性如运行时的动态特性或某些对外接口所限制。
#xreborner 发表于2006-09-03 12:50:00  IP: 218.1.245.*
to fdyjfd:

最后,你还要明白,最完美的编译器必然需要最高的人工智能,此时就不需要人来编程也不需要编程语言了,因此,最完美的编译器也就不会存在了。
#phoenixsh 发表于2006-09-03 13:07:00  IP: 218.82.49.*
谈到编译器,C/C++的编译器作者经常抱怨别名、副作用操作符等等妨碍他们优化。

蒋先生的文章很有意义,不过高速缓存是个复杂的问题。我对C#不了解,听说使用了move around的GC来对付碎片问题,同时可以获得更好的缓存命中率,不知道是不是这样,效果如何?另一方面,C/C++的栈对象确实有助于提高命中率。
#chengmeng 发表于2006-09-03 12:55:00  IP: 221.226.2.*
很多人都在关心memset或者cache的问题,其实他的代码里有个显然的可改进的地方,就是把内循环的2*i改为i*i,性能可以提高一倍。

I found many people pay most attention to the performance related to specific language features,such as memset.In my view,there is a serious problem in Uncle Bob's code:

require 'benchmark'
def sievePerformance(n)
r = Benchmark.realtime() do
sieve = Array.new(n,true)
sieve[0..1] = [false,false]

2.upto(Integer(Math.sqrt(n)) do |i|
if sieve[i]
(2*i).step(n,i) do |j|
sieve[j] = false
end
end
end
end
r
end

the inner loop can be improved:
2.upto(Integer(Math.sqrt(n)) do |i|
if sieve[i]
(i*i).step(n,i) do |j|
sieve[j] = false
end
end
end
because of the mere fact that numbers less than i*i have been sieved already.
#fdyjfd 发表于2006-09-03 17:32:00  IP: 221.217.73.*
to xreborner:
完美的编译器没那么难吧,至少到不了无法实现的程度,
譬如对于这个问题,人是可以得出最佳方案的,那么编译器只要和人一样聪明或者稍差一点也就行了,那么人类又有多聪明呢?也不能是宇宙中至高无上的吧,所以完美编译器是可以存在的。
#fdyjfd 发表于2006-09-03 17:36:00  IP: 221.217.73.*
to xreborner:
你要明白,最完美的编译器并不需要最高的人工智能,只需要最高人工智能的 13.24% 就可以了:)
#xreborner 发表于2006-09-03 18:50:00  IP: 202.120.224.*
to fdyjfd:

你要明白,至少,可以做出最完美编译器的人工智能肯定比能够代替人编程的人工智能还要高级,所以,最完美的编译器是不存在的
#xreborner 发表于2006-09-03 18:52:00  IP: 202.120.224.*
to fdyjfd:


按照你对最完美编译器的定义:“最完美的编译器会编译出一样的也是再也不能更快的代码”,只有和人同等高度的人工智能是做不出最完美的编译器的,因为即使是人也不能写出绝对最好的代码。
#dwbclz 发表于2006-09-03 19:03:00  IP: 192.168.0.*
to phoenixsh
您所说的缓存优化是一个通用的优化手段,但是
跟这个程序不太相关。

在下面的代码里,j+=n跨度很大。以至于很容易访问
到缓存外的数据。
for (int j=2*n; j<max; j+=n)
sieve[j] = false;
据我所知,当你访问到某块内存的时候,并不是只有
访问到的内存才会被加载到缓存里,而是附近的一个
某大小的数据块被整个加载到缓存里。
所以,max大到一定程度的时候,高速缓存的命中率
就变得很差。

我记得Intel的优化手册里提到过,把同时需要访问
的数据放在一起可以提高效率,这段代码显然违背
了这个原则。对于读内存而言,缓存命中的话,会有
四个时钟周期的延迟,反之则会有九个时钟周期甚至
更长的延迟(PentiumIII的数据)。不晓得写内存
的延迟是多少。

大家可以看一下我的测试数据,链接如下:
http://blog.csdn.net/dwbclz/archive/2006/09/02/1159882.aspx

实际上,只有使用的内存足够大的时候,C#才会与C++
拥有同等效率。因为那个时候缓存失效所带来的损耗占
据了主导地位。
#fdyjfd 发表于2006-09-03 20:37:00  IP: 221.217.73.*
to xreborner:
最优的代码只有一种,你怎知一定写不出来呢?
#fdyjfd 发表于2006-09-03 20:39:00  IP: 221.217.73.*
to xreborner:
你又如何能证明“只有和人同等高度的人工智能是做不出最完美的编译器的”?
#fdyjfd 发表于2006-09-03 20:41:00  IP: 221.217.73.*
to xreborner:
还有,你能确定人就不能作出比人更高的人工智能吗?
#xreborner 发表于2006-09-03 21:25:00  IP: 202.120.224.*
最优代码是只有一种,但只有人的智能的编译器是不可能找得出来的。例如给出一个解决NP类问题的指数时间复杂度的程序,要找出其最优代码至少要可以证明其代码最快,这首先要解决NP是否等于P的问题。只有人的智能的编译器,即使能够证明这个问题,也不一定在可接受的短时间内可以解决的,更何谈编译出最优代码呢。事实上,如果把编译器看作一个图灵机,其编译的代码也看作图灵机,那么找出最快的图灵机是一个理论上就不可计算的问题,所有最完美的编译器不存在。

我没有说做不出比人更高的人工智能,我只是说最完美的编译器需要比人更高的人工智能,然而这样的人工智能根本就不需要人来编程了,也就不需要语言和编译器了,于是最完美的编译器也不存在了。
#chengmeng 发表于2006-09-03 23:08:00  IP: 221.226.2.*
同志们,不用争论了。离题太远。再说这个问题早已有前辈解决了,称为

编译器作者之不可能失业定理

大意就是说最优化的编译器使不存在的
具体的陈述记不得了
#chengmeng 发表于2006-09-03 23:12:00  IP: 221.226.2.*
很不幸,又没看上面xreborner的留言,最完美的编译器使不存在的。这次又old了
#phoenixsh 发表于2006-09-04 01:10:00  IP: 218.82.49.*
Quoted from Wiki:

"In computer science, a memory leak is a particular kind of unintentional memory consumption by a computer program where the program fails to release memory when no longer needed."

See? Your (acceptance of the) definition of mem leaking tags yourself the opposite side of profession. Sticking to it worsens that. It further pushes yourself off what you claim to be by keeping shooting at your own imagination instead of what I really mean. I simply did NOT say that Java is ALWAYS faster or smaller than C/C++.

Look at what you said:
>...This kind of things won't happen in both reality and in theory.

They do happen. You don't seem to understand the idea behind gGC (although you pretend to), which I will try to explain to you again: for most OO programs about 92% to 98% of objects become garbage soon after they were born. In the youngest generation, GC promotes only tiny percent of objects to older generation, then could be able to reclaim the whole generation. Compare this to manual mgnt with each one of them, the cost is practically free (for most objects). We are living in a world full of probability, henry. It's fine if you don't believe me, but there are research papers and science studies out there.

It follows that when I said "But this is not the most effective way regarding execution speed.", or "That says, it's much faster than manual management of C/C++.", my point is well
#fdyjfd 发表于2006-09-04 03:56:00  IP: 61.149.101.*
to chengmeng:
只怕你所说的“编译器作者之不可能失业定理”也有被推翻的一天,你确定不是吗?:>
#fdyjfd 发表于2006-09-04 04:04:00  IP: 61.149.101.*
to xreborner:
看你的留言感觉你比较专业,语言和编译器等等我是门外汉了,支持我继续我的观点的唯一原因是我认为“变化是绝对的,不变是相对的”。目前人类的各种科学理论在未来的岁月里可能都会被推翻。所以现在所下的一些结论也受限于目前人类对世界的认识。不是吗?:)。我就此打住。
#fdyjfd 发表于2006-09-04 04:06:00  IP: 61.149.101.*
to xreborner:
看你的留言感觉你比较专业,语言和编译器等等我是门外汉了,支持我继续我的观点的唯一原因是我认为“变化是绝对的,不变是相对的”。目前人类的各种科学理论在未来的岁月里可能都会被推翻。所以现在所下的一些结论也受限于目前人类对世界的认识。不是吗?:)。我就此打住。
#dwbclz 发表于2006-09-04 07:59:00  IP: 192.168.0.*
有兴趣的话可以测试一下这两段代码:
条件一的情况:C++:7.5s C#:20.2s
另外一种情况:C++:1.82s C#:2.00s
测试结果可以说明缓存所带来的问题。注意,跟内存分配关系不大的,
即使我把C#的“bool[] p = new bool[i];”提出来,也要耗时14s多。
// C++
int main(int ac, char** av)
{
unsigned time = GetTickCount();
#if 1
for(int i = 100000; i < 200000; i += 1)
#else
for(int i = 1000000; i < 2000000; i += 1000)
#endif
{
bool* p = new bool[i];

for(int j = 0; j < i; j += 2)
{
p[j] = false;
}

delete [] p;
}
time = GetTickCount() - time;
cout << time << endl;
}
// C#
static void Main(string[] args)
{
DateTime start = DateTime.Now;
#if true
for(int i = 100000; i < 200000; i += 1)
#else
for(int i = 1000000; i < 2000000; i += 1000)
#endif
{
bool[] p = new bool[i];

for (int j = 0; j < i; j += 2)
{
p[j] = false;
}
}
TimeSpan c = DateTime.Now - start;
System.Console.WriteLine(c.TotalMilliseconds);
}

我的文章里有更详细的说明:
http://blog.csdn.net/dwbclz/archive/2006/09/02/1159882.aspx
#xreborner 发表于2006-09-04 09:30:00  IP: 202.120.224.*
to fdyjfd:

你认为严格证明的数学理论也会被推翻吗?
一些问题本质上就可以从数学上来严格证明是图灵不可计算的。
建议你先去学一下计算理论基础。
#phoenixsh 发表于2006-09-04 14:50:00  IP: 222.67.1.*
>...That definition is consistent with "my" memory-leak...

You should be ashamed of yourself for writing such a big block of text before checking out what "unintentional" means. (No, I am not the same kind of people with you and won't cast dirty words to you for this.)

>I must be crazy explaining this elementary concept again and again.

You are crazy shooting false targets (to gain a feeling of heorism?).

>You were talking about ways of cleaning it up. That is unrelevant to my point ...
>"how to find out the 'tiny percent of objects' that are not garbage?"

So what's your point? To prove GC's slowness? Or to assert non-existence of intergenerational algorithms? GC just won't be as stupid as you are. Oh, I mean GC writers. I don't know why it is so hard for your to appreciate probability.

>the Mr. GC-expert
>you know little about C/C++

Stop assuming.

>Evidence?

:)

>I knew you think I am ignorant of the basics...
>Memory can of course be reused after garbage is cleared.

It's very funny putting these two lines together. Thanks for proving what I think you are.

I think I should stop argueing with programmers who:
i> Don't respect the common understanding of daily terms among the community.
ii> Don't listen to or try to understand what their peers are talking about.
iii> Don't respect
#fdyjfd 发表于2006-09-04 12:51:00  IP: 61.149.101.*
to xreborner:
>>你认为严格证明的数学理论也会被推翻吗?
我认为确有可能
#chengmeng 发表于2006-09-04 12:54:00  IP: 221.226.2.*
to fdyjfd:
对于一个数学定理,最好的办法是看证明。仅仅用“变化是绝对的”这种哲学理由是完全站不住脚的。照你说来,目前的一切知识都是不可靠的。这种说法我认为是狡辩
#xreborner 发表于2006-09-04 12:54:00  IP: 202.120.224.*
to fdyjfd:

严格证明的数学理论是不可能被推翻的,有可能的只是适用公理的改变导致结论的不同
#fdyjfd 发表于2006-09-04 12:55:00  IP: 61.149.101.*
to xreborner:
你能否想像到了某一天,整个世界的物理,数学规律荡然无存?
没有可能吗?未必。
#fdyjfd 发表于2006-09-04 12:59:00  IP: 61.149.101.*
to chengmeng:
我好像是在狡辩:)。 大家在讨论现实问题,我却在说缥缈的问题,对不住了。
#henry 发表于2006-09-04 05:06:00  IP: 24.193.79.*
那只不过编译器没做好罢了,比如对本文这个算法来说。

It is right only in theory (in-the-heaven kind of theory). In practice, it is in general really hard, if not impossible. Talking in complete theoretical sense is not very interesting, because in this sense one could even argue the optimization doesn't matter as the computer was infinitely fast. Optimization only makes sense for reality.

to phoenixsh,

You need to pay attention to what I meant. Your reading comprehension really needs improvement. I am tired to correct your misunderstandings. This is the last time I respond to you.

For linked list, what I said is "say a linked list whose nodes are scatterred crossing different generations, when the list is leaked, how the gc will clean up? You will have to scan all generations to clean it completely, won't you?"

You were talking about ways of cleaning it up. That is unrelevant to my point because no matter which way: sooner or later, once or multiple times, you have to "scan all generations to clean it ***completely***".

For gGC, let me ask you, the Mr. GC-expert, a very simple question:"how to find out the 'tiny percent of objects' that are not garbage?". Don't tell me you have to scan the memory. I am expecting you show us a magic, but I doubt you are able to do that.

- "In computer science, a memory leak is a particular kind of unintentional memory consumption by a computer program where the program fail
#xreborner 发表于2006-09-04 17:01:00  IP: 202.120.224.*
to fdyjfd:

即使整个世界的物理、数学规律荡然无存,但现有数学理论仍然不会被推翻,只不过是公理变了,所以结论也不同了。而编译器的定义是依赖于图灵机和数学的定义的,如果公理变了,那么编译器就再也不是编译器了,因为旧的概念、定义和理论不能沿用到用新公理构筑的系统上,然而,这并不能称之为原有的理论被推翻了。

所有,你首先要学的,是你思考的逻辑。
#chengmeng 发表于2006-09-04 19:22:00  IP: 221.226.2.*
to fdyjfd:
这里便有两个问题:
1.图灵机的理论和最优编译器不存的定理,作为一个数学上的定理的正确性,或者说逻辑上的正确性。这不存在疑问。
2.这些理论能否应用到现实中去。我觉得到目前为止,图灵机的理论以及关于最优编译器的定理都是可靠的,因为它们所依赖的前提并没有变,即目前的计算机还逃不了图灵机的范畴。如果将来出现超越图灵机的计算体系,那就……呵呵,暂时无法想象了
#h 发表于2006-09-05 00:34:00  IP: 24.193.79.*
sorry, I can't help to reply, lol:

To tell you the truth, pheononsh, I knew you gonna argue on the unimportant "unintentional". You are really predictable.

This wrod is the most insignificant one throughout the whole definition, and it can be dropped without any problem.

Say,

void foo() { int* p= new int[1000000]; return; }

Is there memory leak in this code? Yes. But I did that intentionally! So it is not memory leak? No, this is still memory leak no matter I do it intentionally or not.

Now, what else can you argue about memory leak? Try to argue Java programs release memory that it leaks. That is the essential part of the whole definition. I don't believe you are capable to do though.

You have a very superfacial understanding of many basic concepts although you pretend to be an gc expert. Sorry saying this may let you lose face, but if you are not shamed of showing it off, then you should not be embarassed by being pointed out.

>"how to find out the 'tiny percent of objects' that are not garbage?"

Poor pheonosh, I was asking you this question so that you got a chance to show off your magic. Got it? Do you on earth have a magic? I guess not from your response.

- You are crazy shooting false targets (to gain a feeling of heorism?).

Of couse I won't have a feeling of heorism, because you are a too easy (and thus false) target.

- Stop assuming.
#h 发表于2006-09-05 00:57:00  IP: 24.193.79.*

add another one:

- >You were talking about ways of cleaning it up. That is unrelevant to my point ...
- >"how to find out the 'tiny percent of objects' that are not garbage?"

- So what's your point? To prove GC's slowness? Or to assert non-existence of intergenerational algorithms?

It seems you are a very bad thinker -- you just try to strike back, but without using your brain. My point is very clearly stated: "say a linked list whose nodes are scatterred crossing different generations, when the list is leaked, how the gc will clean up? You will have to scan all generations to clean it completely". You didn't use your brain when asking that very stupid question.

- GC just won't be as stupid as you are.

That is what you think I was. Maybe I am "stupid", but I can "take care" of you very well.

- Oh, I mean GC writers.

Right, GC writers of JVM are perhaps never Java programmers like you.
#fdyjfd 发表于2006-09-05 04:24:00  IP: 61.149.102.*
to xreborner:
>>“即使整个世界的物理、数学规律荡然无存,但现有数学理论仍然不会被推翻...”
我说的就是“现有数学理论会被推翻”的情况。你莫要说这个不可能。:)
#fdyjfd 发表于2006-09-05 04:26:00  IP: 61.149.102.*
to chengmeng:
正是因为我们局限于目前的世界而无法跳出,所以很难接受“现有数学理论会被推翻”的情况存在。但是“一切皆有可能”:)
#fdyjfd 发表于2006-09-05 04:51:00  IP: 61.149.102.*
to phoenixsh:
你看起来好像生气了,讨论问题嘛,别在意.
#phoenixsh 发表于2006-09-05 09:29:00  IP: 222.67.1.*
to fdyjfd:
没什么。到了这个地步,再说什么都已经没有意义了。

另外,我觉得讨论现有理论会不会被推翻,是不是太空泛了。大多数时候,理论是被超越而不是推翻。
#xreborner 发表于2006-09-05 12:25:00  IP: 202.120.224.*
to fdyjfd:

你真的是什么都不懂。新的理论可以被建立,旧的理论可以被抛弃,但永远不会被推翻。因为理论本身是一个自洽的系统,它由自己给定的公理进行推演发展起来。如果被推翻,那就是理论本身有错的地方,但因为数学理论是严格的,那么就必定是因为某些公理的错误造成结果的错误,但公理会错吗?公理只是一种假设,而不是对事实的描述。理论的所有定理都是在假设公理成立的前提下建立的,如果因为公理不再适用而改变公理建立起新的理论,那也不能说旧的理论被推翻了,因为旧的理论在假设它的公理成立的前提下仍然是正确的。

你的“一切皆有可能”理论就不会被推翻吗?会的,因为你的理论不严格,甚至没有公理,只是随便的陈述一个臆测的事实。
#chengmeng 发表于2006-09-05 13:07:00  IP: 221.226.2.*
to fdyjfd:
“一切皆有可能”,对,但注意不是推翻现有数学理论,而是现有数学理论不适用于现实问题。
我前面说过了,如果照你的态度,那么任何科学理论都是白搭,因为将来会被推翻。这个理由太哲学了,实际上一无所指,除了我们大家在这儿吹牛时有用,没别的任何价值。所以我说是狡辩。
不说了,如果你不了解自动机方面的理论,最好还是找点资料看一看,比在这儿空谈一切理论都有可能被推翻强多了。
#chengmeng 发表于2006-09-05 15:44:00  IP: 221.226.2.*
谁叫你不delete
#runforu 发表于2006-09-05 16:33:00  IP: 59.37.58.*
其实,对于这样的程序c/c++ 和java谁快都不足为奇。因为我以前也做过比较。主要的原因是,这里的计算都是简单的计算,把如此简单的计算,生成目标代码其实是差不多的,循环再多次都不会有太大的差异。但是如果你做工程就不一样了。

我敢肯定对于 i:=1+1这样的语句c/c++ 和java执行效率没有什么差别,循环再多也一样(因为这样的语句执行太局部性了)。

大量的调用系统调用时由于java虚拟机的存在会变慢。因为系统调用对于c是原生的。
大量的绘图语句时由于java虚拟机的存在会变慢。

用java的反射java的垃圾回收都会变慢。
#fdyjfd 发表于2006-09-05 17:55:00  IP: 221.217.70.*
to xreborner:
讨论问题时请不要进行人身攻击,你干吗要说 “你真的是什么都不懂...”呢,最起码我还会上网,还会打字呀。你的态度就没有chengmeng 好,你看他说的“如果你不了解自动机方面的理论,最好还是找点资料看一看,比在这儿空谈一切理论都有可能被推翻强多了......”这才是互相帮助的态度嘛.
#phoenixsh 发表于2006-09-05 17:48:00  IP: 222.67.1.*
to runforu:
除了最后一句话有所保留,其它的我完全同意。

垃圾回收就不谈了。反射的话,我想首先这是一种很有效的提高部署和开发灵活性的手段,可以解除部分耦合,对于组件化开发尤为有利。

谈到反射的速度,要看你怎么样使用它。如果每次都拿着字符串去寻找对象或者方法,那样真的是很慢(但是也许真的有需要这样用的场合)。如果仅仅是把类的装载延迟到运行时,之后按照普通Java代码的方式去使用,我想至少相比其它Java代码而言不会慢或者快。

凡事有利必有弊,虚拟机的存在也一样。单就执行速度而言,虚拟机可以在运行时动态优化编译后的代码,这是静态编译语言做不到的,因为有些信息只有在运行时才能得到。根据80/20法则,80%的时间会消耗在20%的代码上面,虚拟机可以把这部分代码编译成本地代码(原生代码),并予优化,而其余代码仍然是解释执行。编译和优化的代价可以依靠程序的长时间运行得到稀释,也就意味着虚拟机不会一上来就尝试优化。这样,对于需要长时间运行的程序(比如持续数年以上的服务器程序),总体上的速度不一定比相应的C/C++快,但是也不会差到哪里去。
#没有意义的比较,在消耗了100M内存的情况下,根本没有可比性 发表于2006-09-05 15:28:00  IP: 58.61.63.*
当我把下面的程序输入输入结果后,我就明白,我浪费了半个小时....
#include <iostream>>
#include <math.h>
#include <time.h>
#include <windows.h>
using namespace std;

double generate(int max)
{
// struct timeval start;
// struct timezone tz;
// gettimeofday(&start, &tz);
int nTickStart = GetTickCount();
bool *sieve = new bool[max];
for (int i=0; i<max; i++) sieve[i] = true;
sieve[0] = false;
sieve[1] = false;
for (int n=2; n<sqrt(max); n++)
{
if (sieve[n])
{
for (int j=2*n; j<max; j+=n)
sieve[j] = false;
}
}


return GetTickCount() - nTickStart;
}


int main(int ac, char** av)
{
for (int i=100000; i<=5000000; i+=100000)
{
double time = generate(i) * 1000 / i;
cout << time << endl;
}
}

输出结果是:
0
0
0.0533333
0
0.03
0.0266667
0.0214286
0.02
0.0177778
0.015
0.0290909
0.0516667
0.06
0.0557143
0.0626667
0.068125
0.0735294
0.0694444
0.0826316
0.078
0.0742857
0.0781818
0.0817391
0.0779167
0.0876
0.0842308
0.0866667
0.0835714
0.0917241
0.0833333
0.0858065
0.0878125
0.09
0.0873529
0.0891429
0.0869444
0.0886486
0.0944737
0.0920513
0.09
0.095122
0.0930952
0.0909302
0.0922727
0.0937778
0.0
#yl 发表于2006-09-06 09:05:00  IP: 220.231.35.*
如果现在还有任何C++程序员还会嘲笑Java的性能的话.我劝你最好还是再重新掂量掂量吧
=======================================
java的编译器与vm会针对许多特定的编程模式做优化。这叫动态编译。在一些特定编程模式或代码上,动态编译比c++的静态编译编出的东西执行要快。有的情况会快很多。但把所有代码情况做为整体的话。c++比java快。

劝菜鸟不要自鸣得意。