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

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

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

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

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

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

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

Code
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<string, string>();
            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部分的代码:

Code
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)
        
//www.elivn.com
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的时候,引擎只需要加载一次就够了,所以这个缺点大体上还是可以接受的。

补充: 经网友提醒,数据库缓存实际上对测试结果有一定影响,执行相同的sql语句两次(虽然是在两个进程),后一次总是比前一次稍微快一点,不论使用何种语言。通过改变C#和IronPython测试顺序以后的结果来看,可以认为数据库访问,C#和IronPython的性能基本上是没有什么差别的。

转载于:https://www.cnblogs.com/seoxs/archive/2011/04/21/2023492.html

IronPython和C#执行速度对比相关推荐

  1. php和asp.net下SQLite3的执行速度对比

    当看到这样的结果时,我很诧异.我以为php会更快一点儿,但事实是asp.net更胜一筹.不解! php 页面:0.5秒 asp.net 页面 :0.4秒 php页面源码 <html> &l ...

  2. IronPython 与C#交互

    一.介绍 Python是一种面向对象.直译式计算机程序设计语言,也是一种功能强大而完善的通用型语言,已经具有十多年的发展历史,成熟且稳定.这种语言具有非常简捷而清晰的语法特点,适合完成各种高层任务,几 ...

  3. Python.net 和IronPython 是什么关系

    Python.NET和IronPython都是将Python语言集成到.NET平台上的工具库.但是,它们之间存在一些区别. Python.NET更像是一个桥接器(bridge),它提供了一种使用Pyt ...

  4. 2021年大数据Flink(三十):Flink ​​​​​​​Table API  SQL 介绍

    目录 ​​​​​​​Table API & SQL 介绍 为什么需要Table API & SQL ​​​​​​​Table API& SQL发展历程 架构升级 查询处理器的选 ...

  5. 【日记】一次程序调优发现的同步IO写的问题,切记

    众所周知,我们在写程序的时候,好习惯是在重要的代码打上日志.以便监控程序运行的性能和记录可能发生的错误. 但是,如果日志是基于同步IO文件操作,那么就必须考虑到访问总次数或并发数目. 如果总次数或并发 ...

  6. Spring Boot 2.3.x 分层构建 Docker 镜像实战

    目录 一.什么是镜像分层 二.SpringBoot 2.3.x 新增对分层的支持 三.创建测试的 SpringBoot 应用 1.Maven 中引入相关依赖和插件 2.创建测试的 Controller ...

  7. SpringBoot 2.3.x 分层构建 Docker 镜像实践

    目录[-] . 一.什么是镜像分层 . 二.SpringBoot 2.3.x 新增对分层的支持 . 三.创建测试的 SpringBoot 应用 . 1.Maven 中引入相关依赖和插件 . 2.创建测 ...

  8. 【超全教程】SpringBoot 2.3.x 分层构建 Docker 镜像实践

    作者:超级小豆丁 http://www.mydlq.club/article/98/ 目录 什么是镜像分层 SpringBoot 2.3.x 新增对分层的支持 创建测试的 SpringBoot 应用 ...

  9. 万字夜里爆肝,熬夜倾情奉献 Hive最最基础应用

    Hive流程 文章目录 Hive流程 Hive与传统数据库对比 Hadoop简介 1.为什么使用Hive 2.Hive是什么 3.Hive具体内容 4.Hive的存储格式 5.Hive的重要特性 6. ...

最新文章

  1. 为什么说Netty是性能之王,因为它用了 Reactor 模型啊
  2. 使用SAP iRPA Studio创建的本地项目,如何部署到SAP云平台上?
  3. How is default text type determined for Account view
  4. ASP.NET vs MVC vs WebForms
  5. 想做一个程序员 这600个单词是你必须掌握的!
  6. vue中,format与value-format比较
  7. websocket协议中获取 http 请求字符串
  8. php外壳函数,php 方法笔记
  9. Vue中路由管理器Vue Router使用介绍(三)
  10. flink 异步io mysql 缓存_Flink用于外部数据访问的异步I/O
  11. eNSP模拟器拓扑图:浮动路由的实际作用和分析,默认路由的配置,抓包分析
  12. 打开cmd 的方式和常用的cmd快捷键
  13. windows11错误代码0x0000011b怎么解决? 0x0000011b问题的相应解决办法
  14. OPC UA SDK案例:虹科OPC UA SDK助力立功科技ZWS云平台
  15. springboot点餐微信小程序系统毕业设计源码221144
  16. VUE发送POST请求自动附带本地地址
  17. 【数据分析实战】杭州2019年链家在售房源数据分析
  18. dsp6657的helloworld例程测试-第二篇-CFG文件
  19. 用计算机打字英语单词,计算机基本英语词汇
  20. 快速批量创建文件夹、文件的快捷键

热门文章

  1. node --- koa、Mongoose、vue联系知识梳理
  2. Python 杨辉三角形的简单实现
  3. 监控工具之zabbix server3.4 部署配置
  4. iOS- 关于AVAudioSession的使用——后台播放音乐
  5. eclipse搭建SSH框架详解
  6. php安装soap扩展
  7. ubuntu 目录及文件权限 000 444 666 777(转)
  8. 开发短信发送程序的几则技巧
  9. bootargs中的环境变量说明和一些常用的uboot命令
  10. 将Linux系统下交叉编译的依赖库推到ARM平台下无法建立以来关系解决