当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > IronPython和C#执行速度对比

ASP.NET
FreeTextBox(版本3.1.6)在ASP.Net 2.0中使用方法
.NET 常用功能和代码小结
在 .NET Framework 2.0 中未处理的异常导致基于 ASP.NET 的应用程序意外退出
asp.net IList查询数据后格式化数据再绑定控件
asp.net sql存储过程
asp.net 简单实现禁用或启用页面中的某一类型的控件
asp.net(c#)获取内容第一张图片地址的函数
The remote procedure call failed and did not execute的解决办法
ASP.NET 在线文件管理
asp.net 读取并修改config文件实现代码
ASP.NET Cookie 操作实现
asp.net Silverlight中的模式窗体
Silverlight中动态获取Web Service地址
asp.net Silverlight应用程序中获取载体aspx页面参数
asp.net 水晶报表隔行换色实现方法
asp.net 获取Gridview隐藏列的值
手动把asp.net的类生成dll文件的方法
asp.net 使用ObjectDataSource控件在ASP.NET中实现Ajax真分页
动态指定任意类型的ObjectDataSource对象的查询参数
asp.net Md5的用法小结

ASP.NET 中的 IronPython和C#执行速度对比


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-14   浏览: 108 ::
收藏到网摘: n/a

其实我自己对执行速度这个问题本来并没有什么兴趣,因为以前的经验告诉我:除非是运算密集型的程序,否则脚本语言和编译型语言使用起来速度没有多大差别。但是我们公司有个人知道我的想法以后,天天在我耳边嚷嚷脚本运行速度太慢,那好吧,让我用实验来说服你。不过这一试,还真的出现了吓人一跳的结果。

我构思的实验覆盖到下面几个我认为是实际项目中比较有代表性的场景:

1. 访问一个稍大的数据表,遍历所有记录;

2. 生成并操作一个列表;

3. 生成并操作一个字典;

4. 通过反射动态加载并调用一个方法。

C#部分的代码,编译时使用了/debug-和/optimize+:

以下为引用的内容:

using System;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Collections.Generic;
using System.Reflection;

namespace Test
{
    
class Test
    {
        
public static void Main(string[] args)
        {
            Console.WriteLine(
"C#:");
            Measure(TestDb, 
"TestDb");
            Measure(TestList, 
"TestList");
            Measure(TestDict, 
"TestDict");
            Measure(TestReflection, 
"TestReflection");
        }
        
        
delegate void FuncDelegate();
        
        
static void Measure(FuncDelegate func, string funcName)
        {
            Stopwatch sw 
= new Stopwatch();
            sw.Start();
            func();
            sw.Stop();
            Console.WriteLine(
"    {0} used {1} ms", funcName, sw.ElapsedMilliseconds);
        }
        
        
static void TestDb()
        {
            
using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();
                
                SqlCommand cmd 
= new SqlCommand(sql, conn);
                SqlDataReader reader 
= cmd.ExecuteReader();
                
while (reader.Read())
                {
                    var id 
= reader["Id"];
                    var code 
= reader["Code"];
                    var cargoCode 
= reader["CargoCode"];
                    var length 
= reader["Length"];
                    var width 
= reader["Width"];
                    var height 
= reader["Height"];
                    var vol 
= reader["Vol"];
                    var pallet 
= reader["Pallet"];
                }
                reader.Close();
                cmd.Dispose();
                conn.Close();
            }
        }
        
        
static void TestList()
        {
            var list 
= new List<string>();
            
const int count = 100000;
            
for (int i=0; i<count; i++)
                list.Add(
string.Format("item{0}", i));
            
for (int i=count-1; i>=0; i--)
                list.RemoveAt(i);
        }
        
        
static void TestDict()
        {
            var dict 
= new Dictionary<stringstring>();
            
const int count = 100000;
            
for (int i=0; i<count; i++)
                dict[
string.Format("key{0}", i)] = string.Format("value{0}", i);
            
for (int i=0; i<count; i++)
                dict.Remove(
string.Format("key{0}", i));
        }
        
        
static void TestReflection()
        {
            Assembly assem 
= Assembly.LoadFrom("Lib.dll");
            Type type 
= assem.GetType("Lib.TestLib");
            
const int count = 100000;
            ConstructorInfo ci 
= type.GetConstructor(Type.EmptyTypes);
            MethodInfo mi 
= type.GetMethod("GetMessage");
            
for (int i=0; i<count; i++)
            {
                
object obj = ci.Invoke(null); // Activator.CreateInstance(type); 
                mi.Invoke(obj, new object[] { "name" } );
            }
        }
        
        
const string connStr = "Integrated Security=SSPI; Initial Catalog=test; Data Source=.";
        
        
const string sql = "select * from CargoPackageTypes";
    }
}

 IronPython部分的代码:

以下为引用的内容:

from __future__ import with_statement
import clr, sys
clr.AddReference(
'System.Data')
from System.Data.SqlClient import SqlCommand, SqlConnection
from System.Diagnostics import Stopwatch
from System.Reflection import Assembly

connStr 
= "Integrated Security=SSPI; Initial Catalog=test; Data Source=.";

sql 
= "select * from CargoPackageTypes";

def testDb():
    with SqlConnection(connStr) as conn:
        conn.Open()
        
        cmd 
= SqlCommand(sql, conn)
        reader 
= cmd.ExecuteReader()
        
while reader.Read():
            id 
= reader["Id"]
            code 
= reader["Code"]
            cargoCode 
= reader["CargoCode"]
            length 
= reader["Length"]
            width 
= reader["Width"]
            height 
= reader["Height"]
            vol 
= reader["Vol"]
            pallet 
= reader["Pallet"]
        reader.Close()
        cmd.Dispose()
        conn.Close()


def testList():
    lst 
= []
    count 
= 100000
    
for i in xrange(count):
        lst.append(
'item%d' % i)
    
for i in xrange(count-1-1-1):
        lst.pop(i)


def testDict():
    d 
= {}
    count 
= 100000
    
for i in xrange(count):
        d[
'key%d' % i] = 'value%d' % i
    
for i in xrange(count):
        d.pop(
'key%d' % i)
        

def testReflection():
    clr.AddReferenceToFile(
'Lib.dll')
    
from Lib import TestLib
    count 
= 100000
    
for i in xrange(count):
        obj  
= TestLib()
        obj.GetMessage(
'name')
        
        
def measure(fn):
    sw 
= Stopwatch()
    sw.Start()
    fn()
    sw.Stop()
    
print '    %s used %s ms' % (fn.__name__, sw.ElapsedMilliseconds)
    

print 'Python:'    
measure(testDb)
measure(testList)
measure(testDict)
measure(testReflection)

运行结果:

对于列表和字典的操作,IronPython比C#慢3到4倍,这是意料之中的事情。没有想到的是访问数据库的方法,IronPython竟然比C#还要略快,这是事先无论如何都没有料到的。原来我以为,数据库访问代码基本上是纯粹的调用ADO.Net,瓶颈主要是在数据库那一边,IronPython在方法调用的时候应该比C#略微慢一点吧,那么总体速度也应该稍微慢一点才对。没想到结果正好反过来!我也没有办法解释为什么这里IronPython能够做到比C#还快。不过结论应该很明显了:访问数据库的时候,你无需担心IronPython不够快。我们的项目大多数时候效率瓶颈都是出在数据库上面,至于程序语言快一点还是慢一点通常无关紧要,更何况这里的结果表明脚本语言有时候反而可能更快呢。

对于反射的测试,IronPython则是压倒性的战胜了C#。需要说明的一点是我在C#中反射生成对象使用的方法是ConstructorInfo.Invoke()。如果换成Activator.CreateInstance()的话,那么C#的时间将会缩减到230~250毫秒,不过即便这样仍然比IronPython落后一半左右。为什么使用反射时IronPython比C#快这么多呢?或许因为它运行的时候能够在内存中动态生成部分字节码,从而跳过反射环节,所以更快吧。

从这个实验的结果看,IronPython的性能可以说好到超出了我的预期。因为之前也看过其他一些相关的性能评测,比如说Ruby要比Java的运行速度慢30倍(这个比较已经有一段时间了,现在差距应该有所缩小),相比之下IronPython的性能简直可以用十分优异来形容了。当然脚本语言也有一个不足的地方,就是加载解释器的时候会带来几秒钟的固定开销,频繁修改程序的时候,这几秒钟还是有点让人难受的。好在以嵌入方式使用IronPython的时候,引擎只需要加载一次就够了,所以这个缺点大体上还是可以接受的。