我构思的实验覆盖到下面几个我认为是实际项目中比较有代表性的场景
访问一个稍大的数据表遍历所有记录
生成并操作一个列表
生成并操作一个字典
通过反射动态加载并调用一个方法
C#部分的代码编译时使用了/debug和/optimize+
usingSystem;
usingSystemDataSqlClient;
usingSystemDiagnostics;
usingSystemCollectionsGeneric;
usingSystemReflection;
namespaceTest
{
classTest
{
publicstaticvoidMain(string[]args)
{
ConsoleWriteLine(C#:);
Measure(TestDbTestDb);
Measure(TestListTestList);
Measure(TestDictTestDict);
Measure(TestReflectionTestReflection);
}
delegatevoidFuncDelegate();
staticvoidMeasure(FuncDelegatefuncstringfuncName)
{
Stopwatchsw=newStopwatch();
swStart();
func();
swStop();
ConsoleWriteLine({}used{}msfuncNameswElapsedMilliseconds);
}
staticvoidTestDb()
{
using(SqlConnectionconn=newSqlConnection(connStr))
{
connOpen();
SqlCommandcmd=newSqlCommand(sqlconn);
SqlDataReaderreader=cmdExecuteReader();
while(readerRead())
{
varid=reader[Id];
varcode=reader[Code];
varcargoCode=reader[CargoCode];
varlength=reader[Length];
varwidth=reader[Width];
varheight=reader[Height];
varvol=reader[Vol];
varpallet=reader[Pallet];
}
readerClose();
cmdDispose();
connClose();
}
}
staticvoidTestList()
{
varlist=newList();
constintcount=;
for(inti=;ilistAdd(stringFormat(item{}i));
for(inti=count;i>=;i)
listRemoveAt(i);
}
staticvoidTestDict()
{
vardict=newDictionary();
constintcount=;
for(inti=;idict[stringFormat(key{}i)]=stringFormat(value{}i);
for(inti=;idictRemove(stringFormat(key{}i));
}
staticvoidTestReflection()
{
AssemblyAssemblyassem=AssemblyLoadFrom(Libdll);
Typetype=assemGetType(LibTestLib);
constintcount=;
ConstructorInfoci=typeGetConstructor(TypeEmptyTypes);
MethodInfomi=typeGetMethod(GetMessage);
for(inti=;i{
objectobj=ciInvoke(null);//ActivatorCreateInstance(type);
miInvoke(objnewobject[]{name});
}
}
conststringconnStr=IntegratedSecurity=SSPI;InitialCatalog=test;DataSource=;
conststringsql=select*fromCargoPackageTypes;
}
}
IronPython部分的代码:
from__future__importwith_statement
importclrsys
clrAddReference(SystemData)
fromSystemDataSqlClientimportSqlCommandSqlConnection
fromSystemDiagnosticsimportStopwatch
fromSystemReflectionimportAssembly
connStr=IntegratedSecurity=SSPI;InitialCatalog=test;DataSource=;
sql=select*fromCargoPackageTypes;
deftestDb():
withSqlConnection(connStr)asconn:
connOpen()
cmd=SqlCommand(sqlconn)
reader=cmdExecuteReader()
whilereaderRead():
id=reader[Id]
code=reader[Code]
cargoCode=reader[CargoCode]
length=reader[Length]
width=reader[Width]
height=reader[Height]
vol=reader[Vol]
pallet=reader[Pallet]
readerClose()
cmdDispose()
connClose()
deftestList():
lst=[]
count=
foriinxrange(count):
lstappend(item%d%i)
foriinxrange(count):
lstpop(i)
deftestDict():
d={}
count=
foriinxrange(count):
d[key%d%i]=value%d%i
foriinxrange(count):
dpop(key%d%i)
deftestReflection():
clrAddReferenceToFile(Libdll)
fromLibimportTestLib
count=
foriinxrange(count):
obj=TestLib()
objGetMessage(name)
defmeasure(fn):
sw=Stopwatch()
swStart()
fn()
swStop()
print%sused%sms%(fn__name__swElapsedMilliseconds)
printPython:
measure(testDb)
measure(testList)
measure(testDict)
measure(testReflection)
运行结果
)thisstylewidth=; border=>
对于列表和字典的操作IronPython比C#慢到倍这是意料之中的事情没有想到的是访问数据库的方法IronPython竟然比C#还要略快这是事先无论如何都没有料到的原来我以为数据库访问代码基本上是纯粹的调用ADONet瓶颈主要是在数据库那一边IronPython在方法调用的时候应该比C#略微慢一点吧那么总体速度也应该稍微慢一点才对没想到结果正好反过来!我也没有办法解释为什么这里IronPython能够做到比C#还快不过结论应该很明显了访问数据库的时候你无需担心IronPython不够快我们的项目大多数时候效率瓶颈都是出在数据库上面至于程序语言快一点还是慢一点通常无关紧要更何况这里的结果表明脚本语言有时候反而可能更快呢
对于反射的测试IronPython则是压倒性的战胜了C#需要说明的一点是我在C#中反射生成对象使用的方法是ConstructorInfoInvoke()如果换成ActivatorCreateInstance()的话
那么C#的时间将会缩减到~毫秒不过即便这样仍然比IronPython落后一半左右为什么使用反射时IronPython比C#快这么多呢?或许因为它运行的时候能够在内存中动态生成部分字节码从而跳过反射环节所以更快吧
从这个实验的结果看IronPython的性能可以说好到超出了我的预期因为之前也看过其他一些相关的性能评测比如说Ruby要比Java的运行速度慢倍(这个比较已经有一段时间了现在差距应该有所缩小)相比之下IronPython的性能简直可以用十分优异来形容了当然脚本语言也有一个不足的地方就是加载解释器的时候会带来几秒钟的固定开销频繁修改程序的时候这几秒钟还是有点让人难受的好在以嵌入方式使用IronPython的时候引擎只需要加载一次就够了所以这个缺点大体上还是可以接受的