मैं यहां दीवार के खिलाफ अपना सिर पीट रहा हूं, इसलिए मुझे उम्मीद है कि आप में से कुछ मुझे शिक्षित करने में सक्षम हो सकते हैं। मैं बेंचमार्कडॉटनेट का उपयोग करते हुए कुछ प्रदर्शन बेंचमार्क कर रहा था और मैं इस अजीब मामले में भाग गया, जहां ऐसा लगता है कि सदस्य के const
प्रदर्शन को काफी कम घोषित कर रहा है ।
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
namespace PerfTest
{
[DisassemblyDiagnoser(printAsm: true, printSource: true)]
public class Test
{
private int[] data;
private int Threshold = 90;
private const int ConstThreshold = 90;
[GlobalSetup]
public void GlobalSetup()
{
data = new int[1000];
var random = new Random(42);
for (var i = 0; i < data.Length; i++)
{
data[i] = random.Next(100);
}
}
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<Test>();
}
[Benchmark(Baseline = true)]
public void ClampToMemberValue()
{
for (var i = 0; i < data.Length; i++)
{
if (data[i] > Threshold) data[i] = Threshold;
}
}
[Benchmark]
public void ClampToConstValue()
{
for (var i = 0; i < data.Length; i++)
{
if (data[i] > ConstThreshold) data[i] = ConstThreshold;
}
}
}
}
ध्यान दें कि दो परीक्षण विधियों के बीच एकमात्र अंतर यह है कि क्या वे एक नियमित सदस्य चर या एक सदस्य सदस्य के खिलाफ तुलना करते हैं।
बेंचमार्कडॉटनेट के अनुसार कास्ट वैल्यू का उपयोग करना काफी धीमा है और मुझे समझ नहीं आता कि क्यों।
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i7-5820K CPU 3.30GHz (Broadwell), 1 CPU, 12 logical and 6 physical cores
.NET Core SDK=3.0.100
[Host] : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
DefaultJob : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
| Method | Mean | Error | StdDev | Ratio |
|------------------- |---------:|---------:|---------:|------:|
| ClampToMemberValue | 590.4 ns | 1.980 ns | 1.852 ns | 1.00 |
| ClampToConstValue | 724.6 ns | 4.184 ns | 3.709 ns | 1.23 |
जेआईटी संकलित कोड को देखकर यह स्पष्ट नहीं करता है कि जहां तक मैं बता सकता हूं। यहाँ दो तरीकों के लिए कोड है। फर्क सिर्फ इतना है कि तुलना एक रजिस्टर या शाब्दिक के खिलाफ की जाती है।
00007ff9`7f1b8500 PerfTest.Test.ClampToMemberValue()
for (var i = 0; i < data.Length; i++)
^^^^^^^^^
00007ff9`7f1b8504 33c0 xor eax,eax
for (var i = 0; i < data.Length; i++)
^^^^^^^^^^^^^^^
00007ff9`7f1b8506 488b5108 mov rdx,qword ptr [rcx+8]
00007ff9`7f1b850a 837a0800 cmp dword ptr [rdx+8],0
00007ff9`7f1b850e 7e2e jle 00007ff9`7f1b853e
00007ff9`7f1b8510 8b4910 mov ecx,dword ptr [rcx+10h]
if (data[i] > Threshold) data[i] = Threshold;
^^^^^^^^^^^^^^^^^^^^^^^^
00007ff9`7f1b8513 4c8bc2 mov r8,rdx
00007ff9`7f1b8516 458b4808 mov r9d,dword ptr [r8+8]
00007ff9`7f1b851a 413bc1 cmp eax,r9d
00007ff9`7f1b851d 7324 jae 00007ff9`7f1b8543
00007ff9`7f1b851f 4c63c8 movsxd r9,eax
00007ff9`7f1b8522 43394c8810 cmp dword ptr [r8+r9*4+10h],ecx
00007ff9`7f1b8527 7e0e jle 00007ff9`7f1b8537
if (data[i] > Threshold) data[i] = Threshold;
^^^^^^^^^^^^^^^^^^^^
00007ff9`7f1b8529 4c8bc2 mov r8,rdx
00007ff9`7f1b852c 448bc9 mov r9d,ecx
00007ff9`7f1b852f 4c63d0 movsxd r10,eax
00007ff9`7f1b8532 47894c9010 mov dword ptr [r8+r10*4+10h],r9d
for (var i = 0; i < data.Length; i++)
^^^
00007ff9`7f1b8537 ffc0 inc eax
00007ff9`7f1b8539 394208 cmp dword ptr [rdx+8],eax
00007ff9`7f1b853c 7fd5 jg 00007ff9`7f1b8513
}
^
00007ff9`7f1b853e 4883c428 add rsp,28h
तथा
00007ff9`7f1a8500 PerfTest.Test.ClampToConstValue()
for (var i = 0; i < data.Length; i++)
^^^^^^^^^
00007ff9`7f1a8504 33c0 xor eax,eax
for (var i = 0; i < data.Length; i++)
^^^^^^^^^^^^^^^
00007ff9`7f1a8506 488b5108 mov rdx,qword ptr [rcx+8]
00007ff9`7f1a850a 837a0800 cmp dword ptr [rdx+8],0
00007ff9`7f1a850e 7e2d jle 00007ff9`7f1a853d
if (data[i] > ConstThreshold) data[i] = ConstThreshold;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
00007ff9`7f1a8510 488bca mov rcx,rdx
00007ff9`7f1a8513 448b4108 mov r8d,dword ptr [rcx+8]
00007ff9`7f1a8517 413bc0 cmp eax,r8d
00007ff9`7f1a851a 7326 jae 00007ff9`7f1a8542
00007ff9`7f1a851c 4c63c0 movsxd r8,eax
00007ff9`7f1a851f 42837c81105a cmp dword ptr [rcx+r8*4+10h],5Ah
00007ff9`7f1a8525 7e0f jle 00007ff9`7f1a8536
if (data[i] > ConstThreshold) data[i] = ConstThreshold;
^^^^^^^^^^^^^^^^^^^^^^^^^
00007ff9`7f1a8527 488bca mov rcx,rdx
00007ff9`7f1a852a 4c63c0 movsxd r8,eax
00007ff9`7f1a852d 42c74481105a000000 mov dword ptr [rcx+r8*4+10h],5Ah
for (var i = 0; i < data.Length; i++)
^^^
00007ff9`7f1a8536 ffc0 inc eax
00007ff9`7f1a8538 394208 cmp dword ptr [rdx+8],eax
00007ff9`7f1a853b 7fd3 jg 00007ff9`7f1a8510
}
^
00007ff9`7f1a853d 4883c428 add rsp,28h
मुझे यकीन है कि वहाँ कुछ है जिसे मैंने अनदेखा किया है, लेकिन मैं इसे इस बिंदु पर नहीं कर सकता, इसलिए मैं इस बारे में इनपुट की तलाश कर रहा हूं कि यह क्या समझा सकता है।
cmp
और mov
निर्देश जो स्थिरांक पथ के लिए उपयोग किया जाता है एक रजिस्टर आधारित निर्देश की तुलना में अधिक स्मृति पर कब्जा क्योंकि एक नंबर एन्कोडिंग अतिरिक्त बाइट्स और कुल ले में और अधिक CPU चक्र निष्पादित करने के लिए (9 बाइट्स बनाम के लिए 5 बाइट्स की आवश्यकता है mov
और 6 बाइट्स बनाम सीएमपी के लिए 5 बाइट्स) । और फिर भी mov ecx,dword ptr [rcx+10h]
गैर-कास्ट संस्करण के लिए अतिरिक्त निर्देश है, यह JIT कंपाइलर द्वारा रिलीज़ संस्करण में लूप के बाहर होने की संभावना है।