рд╕рдВрдХрд▓рд┐рдд Linq рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдкреЗрдбрд╝ рдХреА рдЧрддрд┐

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ, рд╡рд╣рд╛рдБ рдХреБрдЫ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдерд╛, рд▓реЗрдХрд┐рди рдХреБрдЫ "рдЧреИрд░-рдЕрднрд┐рд╕рд░рдг" рдЖрдИрдПрд▓ рдПрдорд┐рдЯ рдФрд░ рд╕рдВрдХрд▓рд┐рдд рд▓рд╛рдЗрдирдХ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдЯреНрд░реА рдХреА рдЧрддрд┐ рдХреА рддреБрд▓рдирд╛ рдореЗрдВред

рдпрд╣ рдорд┐рдиреА рд▓реЗрдЦ рдЧрддрд┐ рдкрд░реАрдХреНрд╖рдг + рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдЪрд▓рд╛рдиреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХрд╛ рдХреЛрдб рд╣реИред

рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдХреЛрдб рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдЬреЛ рдореВрд▓ рд▓реЗрдЦ рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде рдЕрдВрддрд░ рдХрд░рддрд╛ рд╣реИ - рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рд▓рдВрдмрд╛рдИ рдХреА рдзрд╛рд░рд╛ рдореЗрдВ рдХреНрд░рдорд╛рдВрдХрди рдФрд░ рдлрд┐рд░ UTF-16 рдореЗрдВ рдПрдиреНрдХреЛрдб рдХрд┐рдП рдЧрдП рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕рднреА рдмрд╛рдЗрдЯреНрд╕ (рдПрдирдХреЛрдбрд┐рдВрдЧред рдпреВрдирд┐рдХреЛрдб)ред

рдХреНрд░рдордмрджреНрдзрддрд╛ рдХреЛрдб рд╣реА рд╕рдмрд╕реЗ рдЗрд╖реНрдЯрддрдо рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рдирд┐рд░реНрдорд╛рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕рдХреЗ рдХрд░реАрдм рд╣реИред

рджреЛрдиреЛрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдХреЛрдб рд╕рдорд╛рди рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рд▓реИрдореНрдмреНрдбрд╛ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреА рдЬрд╛рдВрдЪ рдХрд░рдХреЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдореИрдВрдиреЗ рдПрдорд┐рдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдИрдПрд▓ рдкреАрдврд╝реА рдХреЗ рд╕рд╛рде рдкрд░реЗрд╢рд╛рди рдирд╣реАрдВ рдХрд┐рдпрд╛ - рд╡рд╣ рдХреЛрдб рдЬреЛ "рдЗрд╖реНрдЯрддрдо" рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдореИрдВрдиреЗ рд╕рд┐рд░реНрдл рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдореЗрдВ рд╕реА # рдореЗрдВ рд▓рд┐рдЦрд╛ рдерд╛ (рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рд╕рднреА рддрд░реАрдХреЗ рд╕реНрдерд┐рд░ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХ рдмрд╣реБрдд рд╣реА рд╕рд░рд▓ рдХрдВрд╕реЛрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реИ) - рдпрд╣ рд╡рд┐рдзрд┐ рдХреЛ рдореВрд▓ рдирд┐рд╡рд╛рд╕реА рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред

рддреБрд▓рдирд╛ рдХреЗ рд▓рд┐рдП рджреВрд╕рд░реА рд╡рд┐рдзрд┐ рд▓реИрдореНрдмреНрдбрд╛-рдЬрдирд░реЗрдЯреЗрдб рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рд╣реИ, рдЬрд┐рд╕реЗ рдХрдВрдкрд╛рдЗрд▓ рдореЗрдердб рдХрд╣рдХрд░ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (рд╢рд╛рдпрдж рдХреЙрдореНрдкрд╛рдЗрд▓рдЯреЗрдореЛрдереЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЧрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдЯреАрдХ рдирд╣реАрдВ рд╣реИ) - рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдЖрдЧреЗ рдПрдХреНрд╕рдкреЗрд╕реАрд╕рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред

рдмреЛрдирд╕! рдХрд┐рд╕реА рдХрд╛рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдкрд░реАрдХреНрд╖рдг рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛ - рдореВрд▓ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рдХреЙрд▓ - рдПрдХ рд╕реНрдерд┐рд░ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдХреНрд╖реЗрддреНрд░ рдХреЛ рд╡рд┐рдзрд┐ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдХреЗ - рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдореВрд▓ рдирд┐рд╡рд╛рд╕реА рдбреАрдПрд▓рдЬреАрдЯреА рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред

рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ, рджреЛрдиреЛрдВ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ рдЖрдЙрдЯрдкреБрдЯ рд╣реЛрддрд╛ рд╣реИ, рддрд╛рдХрд┐ рдЖрдк рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░ рд╕рдХреЗрдВ рдХрд┐ рдХреЛрдб рдмрд┐рд▓реНрдХреБрд▓ рдПрдХ рд╣реА рдбреЗрдЯрд╛ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред

рддреЛ, рдпрд╣рд╛рдБ рдЖрд╡реЗрджрди рдХреЛрдб рд╣реИ (рд╕рднреА рдХреЛ рдПрдХ рдмрд╛рд░):

рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ
using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; namespace ExpressionSpeedTest { class Program { static void Main(string[] args) { InitExpression(); InitDelegateNative(); var inst = new TestClass { StringProp = "abcdefabcdef" }; byte[] buff1, buff2; using (var ms1 = new MemoryStream()) { SaveString(ms1, inst); buff1 = ms1.ToArray(); } using (var ms2 = new MemoryStream()) { DynamicMethod(ms2, inst); buff2 = ms2.ToArray(); } Console.WriteLine($"Native string: {string.Join("", buff1.Select(b => Encoding.Default.GetString(new[] { b })))}"); Console.WriteLine($"Expressions string: {string.Join("", buff2.Select(b => Encoding.Default.GetString(new[] { b })))}"); GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); GC.Collect(GC.MaxGeneration); TestNative(); GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); GC.Collect(GC.MaxGeneration); TestDelegateNative(); GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); GC.Collect(GC.MaxGeneration); TestExpressions(); GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); GC.Collect(GC.MaxGeneration); Console.ReadLine(); } private static void TestDelegateNative() { var inst = new TestClass { StringProp = "abcdefabcdef" }; using (var ms = new MemoryStream()) { var sw = new Stopwatch(); sw.Start(); for (var idx = 0; idx < loopLength; idx++) { SaveString(ms, inst); } sw.Stop(); Console.WriteLine($"Native Dlgt test: {sw.Elapsed}, {sw.ElapsedTicks} ticks"); } } private static void InitDelegateNative() { NativeDelegate = SaveString; } private static void InitExpression() { var intGetBytes = typeof(BitConverter).GetMethods(BindingFlags.Static | BindingFlags.Public) .Single(x => x.Name == nameof(BitConverter.GetBytes) && x.GetParameters()[0].ParameterType == typeof(int)); var stringGetBytes = typeof(Encoding).GetMethods(BindingFlags.Instance | BindingFlags.Public) .Single(x => x.Name == nameof(Encoding.GetBytes) && x.GetParameters().Length == 1 && x.GetParameters()[0].ParameterType == typeof(string)); var unicodeProp = typeof(Encoding).GetProperty(nameof(Encoding.Unicode), BindingFlags.Static | BindingFlags.Public); var streamWrite = typeof(Stream).GetMethod(nameof(Stream.Write)); var streamPar = Expression.Parameter(typeof(Stream), "stream"); var instPar = Expression.Parameter(typeof(TestClass), "inst"); var intBuffVar = Expression.Variable(typeof(byte[]), "intBuff"); var strBuffVar = Expression.Variable(typeof(byte[]), "strBuff"); var expressionBody = Expression.Block( new[] { intBuffVar, strBuffVar }, Expression.Assign(intBuffVar, Expression.Call(null, intGetBytes, Expression.Property( Expression.Property( instPar, nameof(TestClass.StringProp)), nameof(string.Length)))), Expression.Assign(strBuffVar, Expression.Call(Expression.Property(null, unicodeProp), stringGetBytes, Expression.Property( instPar, nameof(TestClass.StringProp) ))), Expression.Call(streamPar, streamWrite, intBuffVar, Expression.Constant(0), Expression.Property(intBuffVar, nameof(Array.Length))), Expression.Call(streamPar, streamWrite, strBuffVar, Expression.Constant(0), Expression.Property(strBuffVar, nameof(Array.Length))) ); DynamicMethod = Expression.Lambda<Action<Stream, TestClass>>(expressionBody, streamPar, instPar).Compile(); } private const int loopLength = 10000000; private static Action<Stream, TestClass> DynamicMethod; private static Action<Stream, TestClass> NativeDelegate; private static void TestExpressions() { var inst = new TestClass { StringProp = "abcdefabcdef" }; using (var ms = new MemoryStream()) { var sw = new Stopwatch(); sw.Start(); for (var idx = 0; idx < loopLength; idx++) { DynamicMethod(ms, inst); } sw.Stop(); Console.WriteLine($"Expressions test: {sw.Elapsed}, {sw.ElapsedTicks} ticks"); } } private static void TestNative() { var inst = new TestClass { StringProp = "abcdefabcdef" }; using (var ms = new MemoryStream()) { var sw = new Stopwatch(); sw.Start(); for (var idx = 0; idx < loopLength; idx++) { SaveString(ms, inst); } sw.Stop(); Console.WriteLine($"Native test: {sw.Elapsed}, {sw.ElapsedTicks} ticks"); } } public static void SaveString(Stream stream, TestClass instance) { var intBuff = BitConverter.GetBytes(instance.StringProp.Length); var strBuff = Encoding.Unicode.GetBytes(instance.StringProp); stream.Write(intBuff, 0, intBuff.Length); stream.Write(strBuff, 0, strBuff.Length); } } class TestClass { public string StringProp { get; set; } } } 


рдФрд░ рдпрд╣рд╛рдБ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рдиреНрдпрд╛рд╕ рдкрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдкрд░рд┐рдгрд╛рдо рд╣реИрдВ:

рд╕реАрдкреАрдпреВ
	 рдЗрдВрдЯреЗрд▓ (R) рдХреЛрд░ (TM) i7-3770 CPU @ 3.40GHz

	 рдмреЗрд╕ рд╕реНрдкреАрдб: 3.90 рдЧреАрдЧрд╛рд╣рд░реНрдЯреНрдЬрд╝
	 рдХреБрд░реНрд╕рд┐рдпрд╛рдВ: 1
	 рдХреЛрд╕: рек
	 рддрд╛рд░реНрдХрд┐рдХ рдкреНрд░реЛрд╕реЗрд╕рд░: 8
	 рд╡рд░реНрдЪреБрдЕрд▓рд╛рдЗрдЬреЗрд╢рди: рд╕рдХреНрд╖рдо
	 L1 рдХреИрд╢: 256 KB
	 L2 рдХреИрд╢: 1.0 рдПрдордмреА
	 L3 рдХреИрд╢: 8.0 рдПрдордмреА

	 рдЙрдкрдпреЛрдЧ 8%
	 рд╕реНрдкреАрдб 4.05 рдЧреАрдЧрд╛рд╣рд░реНрдЯреНрдЬрд╝
	 рд╕рдордп 5: 00: 43: 01
	 рдкреНрд░рдХреНрд░рд┐рдпрд╛ 239
	 рдереНрд░реЗрдбреНрд╕ 4092
	 168774 рдХреЛ рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИ


рд╕реНрдореГрддрд┐
	 32.0 рдЬреАрдмреА рдбреАрдбреАрдЖрд░ 3

	 рд╕реНрдкреАрдб: 1600 рдореЗрдЧрд╛рд╣рд░реНрдЯреНрдЬ
	 рд╕реНрд▓реЙрдЯ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛: 4 рдХреЗ 4
	 рдлрд╛рд░реНрдо рдлреИрдХреНрдЯрд░: DIMM
	 рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рдЖрд░рдХреНрд╖рд┐рдд: 42.5 рдПрдордмреА

	 рдЙрдкрд▓рдмреНрдз 20.7 рдЬреАрдмреА
	 рдХреИрд╢реНрдб 20.1 рдЬреАрдмреА
	 13.4 / 36.7 рдЬреАрдмреА рдкреНрд░рддрд┐рдмрджреНрдз рд╣реИ
	 рдкреЗрдб рдкреВрд▓ 855 рдПрдордмреА
	 рдЧреИрд░-рдкреГрд╖реНрдард╛рдВрдХрд┐рдд рдкреВрд▓ 442 рдПрдордмреА
	 рдЙрдкрдпреЛрдЧ рдореЗрдВ (рд╕рдВрдкреАрдбрд╝рд┐рдд) 11.2 рдЬреАрдмреА (48.6 рдПрдордмреА)

рд▓рдХреНрд╖реНрдп .Net рдлреНрд░реЗрдорд╡рд░реНрдХ 4.7
рдУрдПрд╕ рд╡рд┐рдВрдбреЛрдЬ 10 рдкреНрд░реЛ x 64 1803 17134.48 рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддрд╛ рд╣реИ

рддреЛ, рд╡рд╛рджрд╛ рдХрд┐рдП рдЧрдП рдкрд░рд┐рдгрд╛рдо:

рдбрд┐рдмрдЧ рдореЗрдВ рд╕рдВрдХрд▓рди, рдЕрдиреБрдХреВрд▓рди рдХреЗ рдмрд┐рдирд╛, рдбрд┐рдмрдЧрд░ рдХреЗ рдмрд┐рдирд╛ рд▓реЙрдиреНрдЪ рдХрд░рдирд╛ (Ctrl + F5):
рдХрд╕реМрдЯреАрд╕рдордп (рдЯрд╛рдЗрдордкреЗрди)рд╕рдордп (рдЯрд┐рдХ)% рд╕рдордп
рджреЗрд╢реА00: 00: 01.576065115760651101,935%
рдореВрд▓ рдирд┐рд╡рд╛рд╕реА dlgt00: 00: 01.546147815461478100%
рднрд╛рд╡00: 00: 01.583545415835454102.4188%

рдЕрдиреБрдХреВрд▓рди рдХреЗ рд╕рд╛рде рд░рд┐рд▓реАрдЬрд╝ рдореЗрдВ рд╕рдВрдХрд▓рди, рдбрд┐рдмрдЧрд░ рдХреЗ рдмрд┐рдирд╛ рдкреНрд░рд╛рд░рдВрдн (Ctrl + F5):
рдХрд╕реМрдЯреАрд╕рдордп (рдЯрд╛рдЗрдордкреЗрди)рд╕рдордп (рдЯрд┐рдХ)% рд╕рдордп
рджреЗрд╢реА00: 00: 01.3182291
13182291
100%
рдореВрд▓ рдирд┐рд╡рд╛рд╕реА dlgt00: 00: 01.3300925
13300925
100.8999%
рднрд╛рд╡00: 00: 01.4871786
14871786
112.8164%

рдХреБрдЫ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

  • рд╕рдВрдХрд▓рд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╡реГрдХреНрд╖ рдбрд┐рдмрдЧ рдореЗрдВ 1-2% рдзреАрдореА рдЧрддрд┐ рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ 10-12 рд░рд┐рд▓реАрдЬрд╝ рдореЗрдВ, рдЬреЛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИ, рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рд░рдирд┐рдВрдЧ рдореЗрдВ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдкреЗрдбрд╝ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИред
  • рдбрд┐рдмрдЧ рдореЛрдб рдореЗрдВ, рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ, рдПрдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд┐рдзрд┐ рдХреЙрд▓ рдкреНрд░рддреНрдпрдХреНрд╖ рдХреЙрд▓ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рддреЗрдЬ рд╣реИред

рд╕реНрдкреЙрдЗрд▓рд░ рдХреЗ рддрд╣рдд рдмреЛрдирд╕ рдирдВрдмрд░ 2 - рд╕рдВрдХрд▓рди рд╕реЗ рдкрд╣рд▓реЗ рд▓реИрдВрдмрдбрд╛ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдбрд┐рдмрдЧ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡:

рд▓реИрдореНрдмреНрдбрд╛
 .Lambda # рд▓реЗрдореНрдмрдбрд╛ 1 <System.Action`2 [System.IO.Stream, ExpressionSpeedTest.TestClass]> (
     System.IO.Stream $ рд╕реНрдЯреНрд░реАрдо,
     ExpressionSpeedTest.TestClass $ inst) {
     .Block (
         System.Byte [] $ intBuff,
         System.Byte [] $ strBuff) {
         $ intBuff = .Call System.BitConverter.GetBytes (($ inst.StPProp) .Length);
         $ strBuff = .Call (System.Text.Encoding.Unicode) .GetBytes ($ inst.StringProp);
         ред $ $ рд╕реНрдЯреНрд░реАрдоред
             $ intBuff,
             0
             $ intBuff.Length);
         ред $ $ рд╕реНрдЯреНрд░реАрдоред
             $ strBuff,
             0
             $ strBuff.Length)
     }
 }

Source: https://habr.com/ru/post/hi413561/


All Articles