Skip to content

Instantly share code, notes, and snippets.

@akimboyko
Last active April 19, 2016 13:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akimboyko/5207102 to your computer and use it in GitHub Desktop.
Save akimboyko/5207102 to your computer and use it in GitHub Desktop.
Simple performance and readability test: RoslynScript vs. IronPython from C# Performance ratio 1:2,7-3 Readability: both scripting engines required some knowledge about underlying APIs
async void Main()
{
GetType().Assembly.FullName.Dump();
IEnumerable<Model.ProcessingModel> models =
Enumerable.Range(0, 1000000)
.Select(n => new Model.ProcessingModel { InputA = n, InputB = n * 0.5M, Factor = 0.050M });
var sw = Stopwatch.StartNew();
var pyCodeReadingTask = Task.FromResult(
File.ReadAllText(@"D:\work\Courses\CaaS\Snippets\sample.py"));
var pyEngine = Python.CreateEngine();
var pyScope = pyEngine.CreateScope();
var source = pyEngine.CreateScriptSourceFromString(await pyCodeReadingTask, SourceCodeKind.File);
source.Execute(pyScope);
dynamic businessRule = pyEngine.Operations.Invoke(pyScope.GetVariable("BusinessRule"));
IEnumerable<dynamic> results =
models
.Select(model => businessRule.calculate(model))
.ToList();
sw.Stop();
string.Format("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds).Dump();
results
.Zip(models, (result, model) => new { result, model })
.Select(@group =>
new
{
@return = @group.result,
ResultModel = @group.model
})
.Take(10)
.Dump();
}
namespace Model
{
public class ProcessingModel
{
public decimal InputA { get; set; }
public decimal InputB { get; set; }
public decimal Factor { get; set; }
public decimal? Result { get; set; }
public decimal? Delta { get; set; }
public string Description { get; set; }
public decimal? Addition { get; set; }
}
public class ReportModel
{
public decimal? Σ { get; set; }
public decimal? Δ { get; set; }
public string λ { get; set; }
}
}
void Main()
{
IEnumerable<Model.ProcessingModel> models =
Enumerable.Range(0, 100000)
.Select(n => new Model.ProcessingModel { InputA = n, InputB = n * 0.5M, Factor = 0.050M });
var sw = Stopwatch.StartNew();
var engine = new ScriptEngine();
new[]
{
typeof (Math).Assembly,
this.GetType().Assembly
}.ToList().ForEach(assembly => engine.AddReference(assembly));
new[]
{
"System", "System.Math",
typeof(Model.ProcessingModel).Namespace
} .ToList().ForEach(@namespace => engine.ImportNamespace(@namespace));
// no dynamic allowed
// no async/await allowed
var script =
@"
Result = InputA + InputB * Factor;
Delta = Math.Abs((Result ?? 0M) - InputA);
Description = ""Some description"";
new Model.ReportModel { Σ = Result, Δ = Delta, λ = Description }
";
var submissionModel = new Model.ProcessingModel();
var session = engine.CreateSession(submissionModel);
var submission = session.CompileSubmission<dynamic>(script);
IEnumerable<dynamic> results =
models
.Select(model =>
{
//submissionModel.InjectFrom(model);
submissionModel.InputA = model.InputA;
submissionModel.InputB = model.InputB;
submissionModel.Factor = model.Factor;
return submission.Execute();
})
.ToList();
sw.Stop();
string.Format("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds).Dump();
results
.Zip(models, (result, model) => new { result, model })
.Select(@group =>
new
{
@return = @group.result,
ResultModel = @group.model
})
.Take(10)
.Dump();
}
namespace Model
{
public class ProcessingModel
{
public decimal InputA { get; set; }
public decimal InputB { get; set; }
public decimal Factor { get; set; }
public decimal? Result { get; set; }
public decimal? Delta { get; set; }
public string Description { get; set; }
public decimal? Addition { get; set; }
}
public class ReportModel
{
public decimal? Σ { get; set; }
public decimal? Δ { get; set; }
public string λ { get; set; }
}
}
# -*- coding: utf8 -*-
import math
import clr
clr.AddReference("query_aicotw") # linq snippet assembly name
from Model import *
class BusinessRule:
def calculate(self, model):
result = model.InputA + model.InputB * model.Factor
delta = math.fabs(result - model.InputA)
description = 'Some description'
resultModel = ReportModel()
resultModel.Σ = result
resultModel.Δ = delta
resultModel.λ = description
return resultModel
@akimboyko
Copy link
Author

While there are some 'voodoo' with Submissions for Roslyn, it executes 3x-3.5x faster compared to IronPython from C# code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment