C#和C++的速度大比拼(续)

来源:岁月联盟 编辑:zhu 时间:2003-07-12
转者注:

C#数据库速度较快不能说明C#本身性能好,因为他们通过外部调用实现,时间集中在外部调用上,就如同
for(int i=0;i<100;i++)
{
//外部调用1秒钟
}
C#用125秒,C++用100秒,怎么能用慢了25%来衡量?C#速度的测试结果和Java相当,实际上Java和C#都比C++慢了5~20倍(要考虑处理不同的数据性能不同,比如整型、浮点型、字符串,要考虑在堆中分配内存造成的速度降低,要考虑后台释放内存的开销,还要考虑其他因素,比如Java/C#中字符串相加和C++中strcpy的巨大效率差异)。

另外,开发效率也是首先需要考虑的,这方面,我认为c#比c++好。
至于,你选择哪种开发工具并不是本文要讨论的,具体应用不同,平台不同,开发工具自然不同。




数据库存取测试

在这一部分,我们将用C++和C#代码来测试两者对数据库的存取和处理。方法是对同一个数据库表进行操作。表结构如下: CREATE TABLE testtable
(
  col1 INTEGER,
  col2 VARCHAR(50),

  PRIMARY KEY (col1)
)      

测试将分三个部分,第一部分和第三部分集中对数据处理,第二部分集中对数据存取。数据处理和数据存取的测试结果是分开呈现的。 下面是数据存取和处理的C++代码: 代码五:db.cpp
#import "msado15.dll" no_namespace rename("EOF", "EndOfFile")
#include <iostream>
#include <string>
#include <sstream>

int main(int argc, char* argv[])
{
  if (argc != 2)
  {
    std::cerr << "Usage:/tdb [rows]/n";
    return 1;
  };

  ::CoInitialize(NULL);
  int NUM = atoi(argv[1]);
  DWORD dw = ::GetTickCount();
  _ConnectionPtr conptr(__uuidof(Connection));
  conptr->Open(L"Provider=Microsoft.Jet.OLEDB.4.0;"
    "Data Source=c://db.mdb;",
    L"",
    L"",
    adOpenUnspecified);
  for (int i=0;i<NUM;i++)
  {
    VARIANT RecordsEffected;
    RecordsEffected.vt = VT_INT;
    std::wstringstream ss;
    ss << L"INSERT INTO testtable (col1, col2) "
      << "VALUES ("
      << i+1 << L", ''" << i+1 << L"'')";
    _bstr_t sql = ss.str().c_str();
    conptr->Execute(sql, &RecordsEffected, adCmdText);
  };

  DWORD dw2 = ::GetTickCount();
  std::cout << "Milliseconds = " << dw2-dw
    << std::endl;  
  dw = ::GetTickCount();
  for (int j=0;j<100;j++)
  {
    _RecordsetPtr rsptr(__uuidof(Recordset));
    rsptr->Open(L"SELECT col1, col2 FROM testtable",
    conptr.GetInterfacePtr(),  
    adOpenForwardOnly, adLockOptimistic, adCmdText);
    while (rsptr->EndOfFile)
    {
      _variant_t v1 = rsptr->GetCollect("col1");
      _variant_t v2 = rsptr->GetCollect("col2");
      rsptr->MoveNext();
    };
    rsptr->Close();
  };

  dw2 = ::GetTickCount();
  std::cout << "Milliseconds = " << dw2-dw
    << std::endl;  
  dw = ::GetTickCount();
  for (int i=0;i<NUM;i++)
  {
    std::wstringstream ss;
    VARIANT RecordsEffected;
    RecordsEffected.vt = VT_INT;
    ss << L"DELETE FROM testtable WHERE col1 = "
      << i+1;
    _bstr_t sql = ss.str().c_str();
    conptr->Execute(sql, &RecordsEffected, adCmdText);
  };
  conptr->Close();
  dw2 = ::GetTickCount();
  std::cout << "Milliseconds = " << dw2-dw
    << std::endl;  
  ::CoUninitialize();
  return 0;
}
下面是数据存取和处理的C#代码: 代码六:db2.cs
using System;
using System.Data;
using System.Data.OleDb;
using System.Text;

namespace Db
{
  class Class1
  {
    static void Main(string[] args)
    {
      if (args.Length != 1)
      {
        Console.WriteLine("Usage:/tdb2 [rows]");
        return;
      }

      int NUM = int.Parse(args[0]);
      long dt = DateTime.Now.Ticks;      
      OleDbConnection connection;
      connection = new OleDbConnection(
        "Provider=Microsoft.Jet.OLEDB.4.0;"
        "Data Source=c://db.mdb;");
      connection.Open();
      for (int i=0;i<NUM;i++)
      {
        StringBuilder ss = new StringBuilder();
        ss.Append("INSERT INTO testtable (col1, col2)"
          " VALUES (");
        ss.Append(i+1);
        ss.Append(", ''");
        ss.Append(i+1);
        ss.Append("'')");

        OleDbCommand command = new OleDbCommand(
          ss.ToString(), connection);
        command.ExecuteNonQuery();
      };

      long dt2 = DateTime.Now.Ticks;
      System.Console.WriteLine("Milliseconds = {0}",
        (dt2-dt)/10000);
      dt = DateTime.Now.Ticks;
      for (int j=0;j<100;j++)
      {
        DataSet dataset = new DataSet();
        OleDbCommand command = new OleDbCommand(
          "SELECT col1, col2 FROM testtable",
          connection);
        OleDbDataReader reader =
          command.ExecuteReader();
        while (reader.Read() == true)
        {
          int v1 = reader.GetInt32(0);
          string v2 = reader.GetString(1);
        };
        reader.Close();
      };

      dt2 = DateTime.Now.Ticks;
      System.Console.WriteLine("Milliseconds = {0}",
        (dt2-dt)/10000);
      dt = DateTime.Now.Ticks;
      for (int i=0;i<NUM;i++)
      {
        StringBuilder ss = new StringBuilder();
        ss.Append("DELETE FROM testtable "
          "WHERE col1 = ");
        ss.Append(i+1);
        OleDbCommand command = new OleDbCommand(
          ss.ToString(), connection);
        command.ExecuteNonQuery();
      };

      connection.Close();
      dt2 = DateTime.Now.Ticks;
      System.Console.WriteLine("Milliseconds = {0}",
        (dt2-dt)/10000);
    }
  }
}
下表为运行十次,每次100行记录的结果 表三:数据库测试结果
序号
C++(~毫秒)
C#(~毫秒)

1 1612/441/450  4086/630/560
2 391/410/441  490/630/520
3 370/421/440  480/510/440
4 371/420/451  470/510/450
5 370/421/461  460/500/450
6 371/420/461  470/500/460
7 370/411/471  470/500/460
8 381/410/451  460/510/470
9 370/421/450  470/510/470
10 391/410/461  460/510/470
平均值 499/419/454  832/531/475

这个结果让人十分惊讶。.NET在这里的表现是令人满意的。一般来说下降百分之二十五的性能是可以忍受的。这说明.NET在这里是赢家。

XML性能测试
XML是数据处理领域的最新技术。许多人对用C#代码和Visaul C++代码处理或解析XML文件的性能很感兴趣。
下面是一段存取和处理XML的C++代码:
代码七:xml.cpp
#import &tl;msxml3.dll≷ named_guids
#include &tl;iostream≷
int main(int argc, char* argv[])
{
  if (argc != 2)
  {
    std::cerr &tl;&tl; "Usage:/txml [filename]/n";
    return 1;
  };

  ::CoInitialize(NULL);
  DWORD dw = ::GetTickCount();
  for (int i=0;i&tl;100;i++)
  {
    MSXML2::IXMLDOMDocumentPtr DomDocument(
      MSXML2::CLSID_DOMDocument) ;
    _bstr_t filename = argv[1];
    DomDocument-≷async = false;
    DomDocument-≷load(filename);
  }

  DWORD dw2 = ::GetTickCount();
  std::cout &tl;&tl; "Milliseconds = " &tl;&tl; dw2-dw
    &tl;&tl; std::endl;
  ::CoUninitialize();
  return 0;
}
      
下面是一段存取和处理XML的C#代码: 代码七:xml.cs
using System;
using System.Xml;

namespace xml2
{
  class Class1
  {
    static void Main(string[] args)
    {  
      if (args.Length != 1)
      {
        Console.WriteLine("Usage:/txml [filename]");
        return;
      }

      long dt = DateTime.Now.Ticks;      
      for (int i=0;i&tl;100;i++)
      {
        XmlDocument doc = new XmlDocument();
        doc.Load(args[0]);
      }

      long dt2 = DateTime.Now.Ticks;
      System.Console.WriteLine("Milliseconds = {0}", (dt2-dt)/10000);
    }
  }
}      
运行十次的结果如下:
表四:XML 测试结果
序号 C++(~毫秒)  C#(~毫秒)
1 241  1111
2 170  841
3 161  841
4 170  861
5 160 861
6 171 851
7 170 841
8 160 831
9 160 841
10 170 851
平均值 203 873

这个结果又让人惊讶一次。很难相信.NET XML类的运行效率比同等的ActiveX类要慢四至五倍。为什么会发生这种情况呢?也许只有微软的兄弟才知道。也许微软想要把.NET类设计成在某一方面与众不同。如果不是这样,那么微软的那帮家伙应该好好优化一下他们的.NET XML类。
如果你是一个Web 服务和服务器应用的开发人员,当把.NET框架用于需要很高性能的应用时,尤其是XML服务时,应三思而行。

总结
需要强调的一点是.NET框架还是一种新的技术。因此,在这个框架中需要做的事情还有很多,它还需要不断优化。另外,这里对.NET的性能测试也很肤浅,以.NET所拥有的丰富内涵来说,用以上四个方面的测试以及简陋的文章来说明它的快或者慢是远远不够的。(全文完)