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

ASP.NET
使用函数传递参数来执行相应的数据库操作
如何实现在窗体和窗体之间进行传递数据
ASP.NET中文显示之两种解决方法
ASP.NET、JSP及PHP之间的抉择
ASP.NET 2.0发送电子邮件中存在的问题
谈谈HtmlControl与WebControl的区别与用途
从ASP.NET 1.1升级到ASP.NET 2.0要考虑的Cookie问题
通过系统配置来提高ASP.NET应用程序的稳定性
妙用ASP2.0中的URL映射改变网址
AJAX实现web页面中级联菜单的设计
ASP.NET跨页面传值技巧总结
再议ASP.NET DataGrid控件中的“添加新行”功能
Geometry 对象浅析
重构CollapsibleSplitter
如何利用.NET Framework使用RSS feed
ASP.NET获取IP与MAC地址的方法
在ASP.NET 2.0中使用样式、主题和皮肤
ASP.NET中为GridView添加删除提示框
ASP.NET 2.0,无刷新页面新境界
看看一个.net版对话框控件

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-14   浏览: 117 ::
收藏到网摘: 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的时候,引擎只需要加载一次就够了,所以这个缺点大体上还是可以接受的。