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&gl; named_guids
#include &tl;iostream&gl;
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-&gl;async = false;
        DomDocument-&gl;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所拥有的丰富内涵来说,用以上四个方面的测

解决方案 »

  1.   

    我怎么觉得XML是虚火上升啊。
      

  2.   

    楼主,建议用System.XML表空间中的类重测XML测试!
    因为在.NET中用COM来处理需要经过一次转换!
      

  3.   

    无意义,功能强大与性能是成反比的拿C#与Java比还有点意义
      

  4.   

    如果VC.NET用托管方式的话,效率可就没有C#高了。
    这里只是比较用.NET Framework和不用.NET Framework的差别。
    就好比拿直接调用WinAPI的程序和运行在虚拟机上的Java比一样。
    后者比前者慢是显然的,如果后者比前者还快的话,那VC早就该回家吃饭去了。
      

  5.   

    对于数据库部分的操作, 估计时间的消耗主要消耗到了ADO中,而不是c++或C#中,因此差距很小. 建议对于数据库的测试应多试几种数据库.