不测不知道,一测吓一跳!
JAVA字符串性能比DELPHI字符串性能还好?
循环次数          Java 1.2  Java 1.2     Java 1.2     gcc 2.95
                  String    StringBuffer  StringBuffer STL-string
                           不分配内存    预先分配内存
外层1000000内层1  6190      480          450          1270  
外层100000内层10  8230      310          300          2180   
外层50000内层20   10620     310          290          1830  
外层20000内层50   14780     310          290          1300 
外层10000内层100  22500     310          290          1100 
外层1000内层1000  性能极差  330          290          1120  
外层100内层10000            360          360          1710  
外层10内层100000            540          440          1220 
外层1内层1000000            1570         900          910   循环次数          Delphi 6  BCB 6        BCB 6        SQL SERVER 2000
                  String    STL-string   AnsiString   (10万数据)
外层1000000内层1  490       810          1310    
外层100000内层10  390       580          2010         2300(内层1)
外层50000内层20   380       580          1900         1650(内层2)
外层20000内层50   380       560          1560         1540(内层5)
外层10000内层100  380       560          1450         1200(内层10)
外层1000内层1000  380       560          1240         1240(内层100)
外层100内层10000  440       600          1300         1250(内层1000)
外层10内层100000  420       640          1270         (最大8000字符)
外层1内层1000000  420       870          7400    代码:(JAVA,其他的类似。)
int a=Integer.parseInt(args[0]);
int b=1000000 / a
System.out.println("start...");
long t1=System.currentTimeMillis();
/*
for (int j=0; j<a; j++)
{
String s="";
for (int i=0; i<b; i++)
s += "aabbzzz";
}
*/
StringBuffer s = new StringBuffer(b*2);
for (int j=0; j<a; j++)
{
s.setLength(0);
for (int i=0; i<b; i++)
s.append("aabbzzz");
}
long t2=System.currentTimeMillis();
System.out.println( t2-t1);JAVA-String的性能级差,但StringBuffer的性能出人意料的好。
DELPHI性能仅仅次于StringBuffer,同时速度一直都很稳定。BCB下的STL-string性能也比较好。

解决方案 »

  1.   

    测试环境:赛扬II900,128M
    单位:ms
      

  2.   

    JAVA-String的性能级差,但StringBuffer的性能出人意料的好。Java的string只负责表示某个字符串,本身是无法对string修改的,你在添加的时候实际上是几个操作,创建新字符串并把原来的和要添加的连上去,当然性能就差多了。而StringBuffer则不同,预先分配多一些内存,添加字符串就在这分配的内存中,当这分配的内存“满”了后再来增加内存,所以StringBuffer添加字符串的内存分配次数比Java少,故效率高。没用过Java,也许说错高手见谅。(我说的Java的string是从IBM的Java教程上看到的,StringBuffer则是延续我在.net中对StringBuilder的理解,所以可能有误)
      

  3.   

    若你再Delphi中也学StringBuffer、StringBuilder的方法,效率也可以超越STL-String和StringBuffer的。
      

  4.   

    估计您还是在单线程下测的,如果多线程情况下,Delphi字符串的操作更慢如果用预分配内存,我们也可以用Delphi版的预分配内存字符串类来比,这没什么好比的
      

  5.   

    Java 中对于 String 操作符"+"的处理很糟糕。性能不好,一般推荐用 StringBuffer 代替。基本上说,很多人不用 String 操作符"+"。
    对于 String 操作符"+"的处理, 只有 ANSI C++ 处理还算可以。VB 的字符串性能也不好。
      

  6.   

    用汇编写了一个TStringBuilder类,呵呵,我的电脑配置和楼主不同,独自测试和楼主的数据无法比较。郁闷死了,用汇编写了后面忘了前面,调试了半天,好多地方可以优化但代码让我自己看的眼睛发麻了。unit lxcStringBuilder;interface
    uses Windows,Classes;
    type TStringBuilder=class
      private
        m_Capacity:Integer;
        m_Memory:String;
        procedure Allocate(dwSize:DWORD);
        procedure AllocateNCopy(const Value:String;Capacity:Integer);
        function FGetLength:Integer;
        function FGetChar(Index:Integer):Char;
        procedure FSetChar(Index:Integer;c:Char);
        procedure Enlarge(bytes:dword);    
      public
        property Chars[Index:Integer]:Char read FGetChar write FSetChar;default;
        property Length:Integer read FGetLength;
        property ToString:String read m_Memory;
        constructor Create(Capacity:Integer);overload;
        constructor Create(const Value:String;Capacity:Integer);overload;
        constructor Create(const Value:String);overload;
        constructor Create();overload;
        procedure Append(const Value:String);end;
    implementation
    //overloaded constructor
      constructor TStringBuilder.Create(Capacity:Integer);
      begin
        Allocate(Capacity);
      end;
      constructor TStringBuilder.Create(const Value:String;Capacity:Integer);
      begin
        AllocateNCopy(Value,Capacity);
      //  mov ecx, TStringBuilder.AllocateNCopy;
      end;
      constructor TStringBuilder.Create(const Value:String);
      begin
        AllocateNCopy(Value,System.Length(value)+4096);
      end;
      constructor TStringBuilder.Create();
      begin
        Allocate(4096);
      end;
      procedure TStringBuilder.AllocateNCopy(const Value:String;Capacity:Integer);
      asm
        push esi
        push ebx
        push eax//保护this指针
        mov dword ptr [eax.m_Capacity],Capacity
        mov esi,dword ptr [Value-4]//获取Value长度
        cmp esi,ecx
        jg @@next
        mov esi,ecx//Capacity>Length(Value)
        @@next:
        add esi,4100//将Capacity和Length(value)的最大值加上4100字节(4K缓存和4Byte的长度)
        push Value
        //申请内存
        push PAGE_READWRITE
        push MEM_COMMIT
        push esi
        push 0
        call VirtualAlloc
        //复制字符串并修改相关内容
        pop esi//Value
        pop ebx//this
        mov ecx,dword ptr [esi-4]//get length of value
        mov dword ptr [eax],ecx//修改新字符串长度
        add eax,4
        mov dword ptr [ebx.m_Memory],eax
        mov edi,eax
        rep movsb
        mov dword ptr [edi+2],0
        pop ebx
        pop esi
        xor eax,eax
        ret;
      end;
      procedure TStringBuilder.Allocate(dwSize:DWORD);
      asm
        mov [eax.m_Capacity],edx
        push eax
        add edx,4//增加一个保存长度的DWORD
        push PAGE_READWRITE
        push MEM_COMMIT
        push edx
        push 0
        call VirtualAlloc
        mov [eax],0//头一个DWORD保存String的长度
        add eax,4
        pop ecx
        mov [ecx.m_Memory],eax
        ret
      end;
      procedure TStringBuilder.Enlarge(bytes:dword);
      asm
        push esi
        push eax
        add edx,[eax.m_Capacity]//新内存长度
        mov [eax.m_Capacity],edx//修改新长度
        push self//
        push PAGE_READWRITE
        push MEM_COMMIT
        push edx
        push 0
        call VirtualAlloc
        pop ecx//self
        mov esi,[ecx.m_Memory]
        push esi
        mov edi,eax
        mov edx,[ecx.m_Memory]
        push [edx-4]
        pop [eax]
        add eax,4
        mov [ecx.m_Memory],eax//指向新地址
        mov ecx,[edx-4]
        mov edi,eax
        rep movsb
        pop esi
        sub esi,4
        push MEM_RELEASE
        push 0
        push esi
        call VirtualFree//释放原来内存
        pop eax
        pop esi
        ret
      end;
      procedure TStringBuilder.Append(const value:string);
      asm
        push esi
        push edi
        mov esi,[eax.m_Memory]//获取现在的字符串的长度
        mov esi,[esi-4]
        mov edi,[eax.m_Capacity]//获取已申请内存的大小
        sub edi,esi
        cmp edi,2048//若剩余空间长度不足2K则进行扩展
        jg @WithouExtend
        push edx
        push esi
        mov edx,[eax.m_Capacity]
        add edx,4098//添加4K内存
        push eax
        call TStringBuilder.Enlarge//扩展
        pop eax
        pop esi
        pop edx//value
        @WithouExtend:
        mov ecx,[edx-4]//获取value长度
        mov edi,esi
        add edi,ecx
        push edi
        mov edi,esi
        add edi,[eax.m_Memory]//用于复制的新地址
        mov esi,edx//原来地址
        rep movsb
        pop esi
        mov edx,[eax.m_Memory]
        mov [edx-4],esi
        mov eax,[eax.m_Memory]
        mov [eax-4],esi//修改长度
        pop edi
        pop esi
        ret
      end;
      function TStringBuilder.FGetLength:Integer;
      asm
        mov eax,[eax.m_Memory]
        mov eax,[eax-4]
      end;
      function TStringBuilder.FGetChar(Index:Integer):Char;
      asm
        mov ecx,[eax.m_Memory]
        add ecx,edx
        xor eax,eax
        mov al,[ecx]
      end;
      procedure TStringBuilder.FSetChar(Index:Integer;c:Char);
      asm
        mov eax,[eax.m_Memory]
        add eax,edx
        mov [eax],cl
      end;
    end.
      

  7.   

    又要郁闷。Mozilla发贴把代码缩进都弄没了
      

  8.   

    还是要郁闷,Append没写好。没有考虑value的长度。懒的改了
      

  9.   

    -_-|
    用汇编写……高手啊:)
    你写好后,和DELPHI内建的string比较一下,然后可以得到相对数据。
      

  10.   

    测试时正在用BT下载DOOM、横扫千军,Net Transport下载三部电影,Mozilla浏览器开了4个窗口,UltraEdit打开了6个文件,瑞星防火墙打开了内存和文件监控,一个资源管理器一个QQ,除了必要的后台服务其他全部已经关闭配置:Althlon 2500+, 256MB DDR 400×2, Win XP Pro
    Delphi写的,D7编译,测试我前面写的 TStringBuilder,速度最快的时候100外层循环达到耗时16微妙,所有代码统一采用timeGetTime计时H:\>for %x in (1,10,100,1000,10000,100000) do @dstrtest stringbuilder %x
    StringBuilder外层1内层1000000耗时间60微秒
    StringBuilder外层10内层100000耗时间29微秒
    StringBuilder外层100内层10000耗时间27微秒
    StringBuilder外层1000内层1000耗时间26微秒
    StringBuilder外层10000内层100耗时间27微秒
    StringBuilder外层100000内层10耗时间33微秒
    我的电脑上Delphi里字符串的测试:
    H:\>for %x in (1,10,100,1000,10000,100000) do @dstrtest string %x
    String外层1内层1000000耗时间145微秒
    String外层10内层100000耗时间146微秒
    String外层100内层10000耗时间148微秒
    String外层1000内层1000耗时间142微秒
    String外层10000内层100耗时间140微秒
    String外层100000内层10耗时间145微秒
    C#代码,使用 .net framework 1.1编译
    H:\>for %x in (1,10,100,1000,10000,100000) do @cstest stringbuilder %x
    StringBuilder外层1内层1000000耗时间166微秒
    StringBuilder外层10内层100000耗时间98微秒
    StringBuilder外层100内层10000耗时间79微秒
    StringBuilder外层1000内层1000耗时间72微秒
    StringBuilder外层10000内层100耗时间78微秒
    StringBuilder外层100000内层10耗时间77微秒.net framework自带编译器加优化编译:
    H:\>for %x in (1,10,100,1000,10000,100000) do @cstest stringbuilder %x
    StringBuilder外层1内层1000000耗时间137微秒
    StringBuilder外层10内层100000耗时间85微秒
    StringBuilder外层100内层10000耗时间80微秒
    StringBuilder外层1000内层1000耗时间77微秒
    StringBuilder外层10000内层100耗时间79微秒
    StringBuilder外层100000内层10耗时间78微秒
    Mono不带优化编译同样代码(不支持中文额):
    StringBuildería2?1?ú2?1000000o?ê±??146?¢??
    StringBuildería2?10?ú2?100000o?ê±??87?¢??
    StringBuildería2?100?ú2?10000o?ê±??75?¢??
    StringBuildería2?1000?ú2?1000o?ê±??73?¢??
    StringBuildería2?10000?ú2?100o?ê±??74?¢??
    StringBuildería2?100000?ú2?10o?ê±??80?¢??与上面同样的EXE,不过用Mono的CLR而不是MS的CLR执行:
    H:\>for %x in (1,10,100,1000,10000,100000) do @mono cstest.exe stringbuilder %x
    StringBuilder????1????1000000???±??301????
    StringBuilder????10????100000???±??110????
    StringBuilder????100????10000???±??77????
    StringBuilder????1000????1000???±??78????
    StringBuilder????10000????100???±??77????
    StringBuilder????100000????10???±??82????使用MONO来执行MS编译器编译(已优化)的测试程序:
    H:\>for %x in (1,10,100,1000,10000,100000) do @mono cstest.exe stringbuilder %x
    StringBuilder外层1内层1000000耗时间292微秒
    StringBuilder外层10内层100000耗时间108微秒
    StringBuilder外层100内层10000耗时间78微秒
    StringBuilder外层1000内层1000耗时间77微秒
    StringBuilder外层10000内层100耗时间76微秒
    StringBuilder外层100000内层10耗时间79微秒使用MONO来执行MS编译器编译(未优化)的测试程序:
    H:\>for %x in (1,10,100,1000,10000,100000) do @mono cstest.exe stringbuilder %x
    StringBuilder外层1内层1000000耗时间289微秒
    StringBuilder外层10内层100000耗时间110微秒
    StringBuilder外层100内层10000耗时间77微秒
    StringBuilder外层1000内层1000耗时间75微秒
    StringBuilder外层10000内层100耗时间78微秒
    StringBuilder外层100000内层10耗时间78微秒
    .net版本的也写了string的测试,但是不敢贴上来,执行了大约10分钟第一个结果还没出来 -_-!  寒~~ 
      

  11.   

    C#版本测试代码:using System;
    using System.Text;
    using System.Runtime.InteropServices;
    namespace CS_Test
    {
    public class CS_Test
    {
    public static void Usage()
    {
    Console.WriteLine("cstest stringbuilder|string times");
    }
    [DllImport("winmm.dll")]
    extern static int timeGetTime();
    public static void Main()
    {
    string[] args=Environment.GetCommandLineArgs();
    if(args.Length!=3)
    {
    Usage();
    return;
    }
    int times=int.Parse(args[2]);
    if("stringbuilder"==args[1])
    test_stringBuilder(times);
    else
    if("string"==args[1])
    test_string(times);
    else
    Usage();
    }

    public static void test_stringBuilder(int times)
    {
    StringBuilder sb=new StringBuilder(40960);
    int b=1000000/times;
    int t1=timeGetTime();
    for(int j=0;j<times;j++)
    {
    sb.Length=0;
    for(int i=0;i<b;i++)
    {
    sb.Append("aabbzzz");
    }
    }
    int t2=timeGetTime();
    Console.WriteLine("StringBuilder外层{0}内层{1}耗时间{2}微秒",times,b,t2-t1);
    }
    public static void test_string(int times)
    {
    string s;
    int b=1000000/times;
    int t1=timeGetTime();
    for(int j=0;j<times;j++)
    {
    s="";
    for(int i=0;i<b;i++)
    {
    s+="aabbzzz";
    }
    }
    int t2=timeGetTime();
    Console.WriteLine("String外层{0}内层{1}耗时间{2}微秒",times,b,t2-t1);

    }
    }
    }
    ________________________________________________________________________Delphi版本测试代码:
    program DStrTest;{$APPTYPE CONSOLE}uses
      SysUtils,lxcStringBuilder,mmsystem;
      procedure Usage;
      begin
        Writeln('dstrtest stringbuilder|string times');
        halt;
      end;
      
      procedure test_stringbuilder(times:Integer);
      var s:TStringBuilder;
        b,j,i:integer;
        t1,t2:integer;
      begin
        b:=1000000 div times;
        s:=TStringBuilder.Create(40960);
        t1:=timeGetTime;   
        for j:=1 to times do
        begin
          s.Length :=0;
          for i:=1 to b do
            s.Append('aabbzzz');
        end;
        t2:=timeGetTime;
        Writeln(Format('StringBuilder外层%d内层%d耗时间%d微秒',[times,b,t2-t1]));
    //    s.Free ;
      end;
      procedure test_string(times:integer);
      var s:AnsiString;
        b,j,i:integer;
        t1,t2:integer;
      begin
        b:=1000000 div times;
        Writeln('staring...');
        t1:=timeGetTime;
        for j:=1 to times do
        begin
          s:='';
          for i:=1 to b do
            s:=s+'aabbzzz';
        end;
        t2:=timeGetTime;
        Writeln(Format('String外层%d内层%d耗时间%d微秒',[times,b,t2-t1]));
      end;
    var times:integer;
    begin
      if ParamCount<>2 then
        Usage;
      times:=StrToInt(ParamStr(2));
      if(ParamStr(1)='stringbuilder')then
        test_stringbuilder(times)
      else
      if(ParamStr(1)='string')then
        test_string(times)
      else
        usage;  
      { TODO -oUser -cConsole Main : Insert code here }
    end.其他修改:TStringBuilder增加一个FSetLength的私有方法,用于Length属性的write里:  procedure TStringBuilder.FSetLength(value:Integer);
      asm
        mov eax,[eax.m_Memory]
        mov [eax-4],edx
      end;
      

  12.   

    p.s.楼上lexchou是我在IE里发的帖子
      

  13.   

    龙子龙孙=恶鱼杀手:
    你也喜欢用AMD的呀,我也喜欢!
      

  14.   

    配置:Althlon 2500+, 256MB DDR 400×2, Win XP Pro
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~俺的:Althlon 2500+, KT600  512MB DDR 400×1, Win XP Pro
    综合考虑没选NForce2,因为硬盘是SATA的
      

  15.   

    JAVA-String的性能级差,但StringBuffer的性能出人意料的好 这句是实话
      

  16.   

    >>.net版本的也写了string的测试,但是不敢贴上来,执行了大约10分钟第一个结果还没出来 -_-
    寒一个
      

  17.   

    龙子龙孙=恶鱼杀手真TM强,年纪不大研究的这么深,我想足以让很多高手望而却步(俺更是连那些汇编是什么意思都不懂,丢人中……)。不过我也不是说星星们不行,因为诸位大多是工程人员,没这么多闲工夫。建议封龙子龙孙=恶鱼杀手为D版第一板斧,好和那些踢场子的人对砍:)
    再次佩服!
      

  18.   

    如果经常使用的东西,我一定用GetMem,然后来操作那个内存里面的东西.:D