ãœãããŠã§ã¢ããããã¡ã€ãªã³ã°ããçµæããããã¡ãŒæ¯èŒæ©èœãæé©åããå¿
èŠããããšçµè«ä»ããŸããã
ãªããªã CLRã¯ã¡ã¢ãªã®2ã€ã®éšåãæ¯èŒããæšæºçãªæ¹æ³ãæäŸããªããããé¢æ°ã¯ç¬ç«ããŠæ©èœããŸããïŒæ©èœããå Žåã®ã¿ïŒã
ã.Netã®ãã€ãé
åãæ¯èŒããæè¯ã®æ¹æ³ããšãããã¬ãŒãºãã°ãŒã°ã«ã§æ¢ããŸããããã»ãšãã©ã®å Žåã人ã
ã¯LINQãŸãã¯Enumerable.SequenceEqualïŒïŒã䜿çšããããšãææ¡ããŸããã StackOverflowã§ãããããæãäžè¬çãªåçã§ããã ã€ãŸã å£æ»
çã«äººæ°ã®ãããã©ãŒã ã®åŠæ³ïŒ
ãã³ã³ãã€ã©ãšã©ã³ã¿ã€ã ç°å¢ã¯ã«ãŒããæé©åããã®ã§ãããã©ãŒãã³ã¹ãå¿é
ããå¿
èŠã¯ãããŸãããã
æåã«ãã®æçš¿ãæžãããšãèããããããã®ã¯ããã§ããã
CïŒããå©çšå¯èœãªãããã¡ãŒãæ¯èŒãã5ã€ã®æ¹æ³ã®æ¯èŒãã¹ããå®æœãããã¹ãçµæã«åºã¥ããŠãã¡ãœããã®éžæã«é¢ããæšå¥šäºé
ã瀺ããŸããã
ããã«ãããã€ãã®é¢æ°ãéã³ã³ãã€ã«ããx86æ§æçšã«JITã³ã³ãã€ã©ãŒã«ãã£ãŠçæãããã³ãŒããåæããåæ§ã®ç®çã§JITã³ã³ãã€ã©ãŒã«ãã£ãŠçæããããã·ã³ã³ãŒããšCRTé¢æ°ã®ãã·ã³ã³ãŒããæ¯èŒããŸããã
èæ¯
å¥ã®ãŠãŒãã£ãªãã£ãäœæããŠæ©èœãããåŸããããã¡ã€ã©ãèµ·åãããã€ãé
åã®æ¯èŒã«éåžžã«æéãããã£ãŠããããšã確èªããŸããã
CompareByteArraysïŒïŒé¢æ°ã¯ã¯ãªãã£ã«ã«ãã¹äžã«ãããããã¹ãããšããããŸããã
ããã©ãŒãã³ã¹ã®åé¡ã«å¯Ÿããã¢ã«ãŽãªãºã ã®è§£æ±ºçã¯èŠåœãããŸããã§ãããã¢ã«ãŽãªãºã ã¯äºåã«éžæãããŠãããçµæãšããŠçããè€éãã軜æžããæ¹æ³ã«ã€ããŠã®ã¢ã€ãã¢ã¯ãããŸããã§ããã
World Wide Webã§ã®æ€çŽ¢çµæã¯ããŸãæåŸ
ã§ããŸããã§ãããã¡ãœããã®é床ã®æ¯èŒã¯ãããŸãããããããã®æ°å€ã¯ã©ã®ããŒã¿ã§ãã©ã®æ¡ä»¶ã§èª°ãæžãããšãæ°ã«ããã«åŸãããŸããã
ç§ã¯ã誰ãã©ã®ãããªæ¡ä»¶äžã§ããéããªããã«ã€ããŠãç¬èªã®ä»®å®ãæã£ãŠããŸããã 確èªããããšã«ããŸããã
çµæã¯é¢çœãã£ãã®ã§ãããã§ã®æé£ã®èãã¯ã€ãã«æçããŸããã
äœããã¹ãããŸããã
äž»ãªãã®
ã³ãŒãã¯ã³ã³ãã€ã«ãããWindows 7 x64ãã·ã³äžã§å®è¡ãããŸããã Microsoft Visual Studion 2010ã®ããã©ã«ãèšå®ã§ãx86æ§æã®ã¿ãã€ãŸã ããã¯32ãããã³ãŒãã§ãã ãŸããåºäŒã£ãã³ãŒãã®ã»ãšãã©ã32ãããã·ã¹ãã çšã«æžãããŠããããã§ãã 次ã«ããã®æ§æã§ã¯.NetãéèŠã§ãããšèããŠããŸãã ç¹ã«ã倧éã®æ¢åã®ã³ã³ããŒãã³ãã32ãããçšã«èšè¿°ãããŠããã誰ãããããæžãæããªããããããããšå¯Ÿè©±ããå¿
èŠããããŸãã æçµçãªã¢ããªã±ãŒã·ã§ã³ã®æ§æã決å®ããŸãã 次ã«ã64ããããå¿
èŠãšããã¢ããªã±ãŒã·ã§ã³ã®æ°ãéåžžã«å°ãªããããå¿
èŠãªããã深床ã¯äž»ã«ã¡ã¢ãªèŠä»¶ãšã¿ãŒã²ãããã©ãããã©ãŒã ã«ãã£ãŠæ±ºãŸããŸãã ææ°ã®64ãããx86äºæããã»ããµã¯ãããŒããŠã§ã¢ã§32ãããã¿ã¹ã¯ããµããŒãããŸã[1] [2]ã Windows x64ã32ãããã³ãŒããçŽæ¥å®è¡ããããšã§ãã®æ©èœã䜿çšããã®ã¯è«ççã§ã[3]ã æåã«32ãããã¢ããªã±ãŒã·ã§ã³ã64ãããã§ã³ã³ãã€ã«ãããšãã³ã³ãã€ã©ãŒãªãã·ã§ã³ã«ãã£ãŠããã»ããµãŒTLBãµã€ãºã1次ãã£ãã·ã¥ãå€æŽãããããã€ã³ã¿ãŒãµã€ãºã2åã«ãªããå¿
èŠãªããŒã¿ã¢ã©ã€ã¡ã³ãå¢çããããããå¿
èŠãªã¡ã¢ãªãå¢å ããããã©ãŒãã³ã¹ãäœäžããŸãå€æŽ[4]ã
ããŒã¿ãµã€ãº
å
ã®ã¿ã¹ã¯ã§ã¯ããµã€ãºã16ãã€ãã§ãµã€ãºã1ã4 * 1024ãã€ãã®ãã€ãé
åãæ¯èŒããå¿
èŠããããŸããã 16ãã€ãã¯MD5ã®ãµã€ãºã4 Kbã¯Windowsã®æšæºã¡ã¢ãªããŒãžã®ãµã€ãºã§ãããããI / Oãããã¡çšã«éžæãããŸããã
ãã ããããã·ã¥ã®ãµã€ãºã16ãã€ãã ãã§ãªãã4ãã€ããããã«ã¯2ãã€ãïŒCRC16ãCRC32ïŒãããã³ã¡ã¢ãªããŒãžã4ã§ãããšããåçŽãªçç±ã«ããã1ãã€ããã1/2ã¡ã¬ãã€ãã®ãããã¯ã§æ¯èŒããã¹ãããŸããããããã€ãã ãã§ãªãã2 MB [2]ãããã«ã¯4 MBããããŸãã 1/2 MBãããã¯ã§ç€ºãããçµæã¯ã倧ããªãããã¯ã§ã®äœæ¥ã«ã€ããŠçµè«ãåºãã®ã«ååã§ãããããã«ãç§ã®æéã¯ç¡å¶éã§ã¯ãããŸããïŒãã¹ãäžã«ã³ã³ãã¥ãŒã¿ãŒã«è§Šããªãããã«ããŠã説æãããããã»ã¹ããæéãããããªãããã«ããŸãïŒã
æåã®å®è¡ã®çµæã«åºã¥ããŠã25çš®é¡ã®ãµã€ãºã®ãã¹ãããŒã¿ã§ã¡ãœãããæ¯èŒããã ãã§ååã§ããããšãããããŸããã ãããè¡ãã«ã¯ãæåã®ãã¹ãã»ããã1ãã€ãé
åã§æ§æããã次ã®åã¹ãããã§ãã¹ãé
åã®ãµã€ãºã«åãä¿æ°ãä¹ç®ãããããã«ããã¹ããµã€ã¯ã«ãæ§ç¯ããŸããã
ãã©ã¡ãŒã¿ãŒã¯ãã³ãŒãå
ã®å®æ°ã«ãã£ãŠèšå®ãããŸããã
private const int CountArrays = 128;
ã¡ã€ã³ã®ãã¹ããµã€ã¯ã«ã¯æ¬¡ã®ããã«ãªããŸãã
double sizeMultiplier = 1; DoInvestigationStep(sizeMultiplier); const int MaxMultiplier = MaxArraySize / StartArraySize; var stepMmltiplier = Math.Pow( MaxMultiplier, 1 / (double)StepsCount ); for (var step = 1; step <= StepsCount; step++) { sizeMultiplier = Math.Pow(stepMmltiplier, (double) step); DoInvestigationStep(sizeMultiplier); }
åã¹ãããã§ã®é
åã®ãµã€ãºã¯ã次ã®ããã«èšç®ãããŸããã
var arraySize = (int) (StartArraySize * p_SizeMultiplier);
ãã¹ãæžã¿ã®ã¡ãœãã
System.Collections.IStructuralEquatableã€ã³ã¿ãŒãã§ã€ã¹ã®äœ¿çš
ããã¯CïŒã®æ¯èŒçæ°ããæ¹æ³ã§ããã.NET 4ã§ã®ã¿ç»å Žãããããç¹ã«èå³æ·±ããã®ã§ããã
private static bool ByteArrayCompareWithIStructuralEquatable(byte[] p_BytesLeft, byte[] p_BytesRight) { IStructuralEquatable eqa1 = p_BytesLeft; return eqa1.Equals(p_BytesRight, StructuralComparisons.StructuralEqualityComparer); }
LINQããŸãã¯ãããEnumerable.SequenceEqualïŒïŒ
ããã¯æãç°¡åãªæ¹æ³ã®1ã€ã§ãå®è£
ãæãç°¡åã§ãã ãŸããããã¯æãäžè¬çãªæ¹æ³ã§ãã
private static bool ByteArrayCompareWithSequenceEqual(byte[] p_BytesLeft, byte[] p_BytesRight) { return p_BytesLeft.SequenceEqual(p_BytesRight); }
PInvokeãCRT memcmpïŒïŒé¢æ°çš
çè«çã«ã¯ããããæéã®æ¹æ³ã§ããã¯ãã§ãããåžžã«ããã§ãããšã¯éããªãããšãå€æããŸããããã©ãããã©ãŒã ãšã®ããåãã®ãªãŒããŒãããã¯éåžžã«å€ãã®æéãæ¶è²»ããå Žåã«ãã£ãŠã¯ãã®æ¹æ³ã¯ãã®é
åã倱ããŸãã
ããã§ç§ã¯ãããSOã§èŠã€ãã圢ã§æã£ãŠããŸãã ãã®åœ¢åŒã§ãã¹ãããŸããã
PInvoke.netã§ã¯ãå°ãç°ãªããŸãã
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] private static extern int memcmp(byte[] p_BytesLeft, byte[] p_BytesRight, long p_Count); private static bool ByteArrayCompareWithPInvoke(byte[] p_BytesLeft, byte[] p_BytesRight) {
é¡ã«ã ã€ãŸã forïŒ;;ïŒã«ãŒãå
ã®ãã€ãã®çŽæ¥æ¯èŒ
ããã¯ã2ã€ã®é
åãæ¯èŒããæãæçœãªæ¹æ³ã§ãããèå³æ·±ãã®ã¯ãã®ããã§ãã
åœåããã®æ¹æ³ã¯éããããšã¯æãããŸããã§ããããå€ãã®ç¶æ³ã§ã¯ããªã蚱容ã§ããããšãå€æããŸããã
ã¡ãªã¿ã«ããã®æ¯èŒæ¹æ³ã®ããªãšãŒã·ã§ã³ã®1ã€ã¯ãCLR補é æ¥è
èªèº«ã®
èšäºã§ ãããã«å¿
èŠãªããã¹ãã§äœ¿çšãããŠããŸããã
ã©ãããããŠãŒã¶ãŒã¯ãã®ãããªè³ªåã§ããããçµããŸããã
private static bool ByteArrayCompareWithSimplest(byte[] p_BytesLeft, byte[] p_BytesRight) { if (p_BytesLeft.Length != p_BytesRight.Length) return false; var length = p_BytesLeft.Length; for (int i = 0; i < length; i++) { if (p_BytesLeft[i] != p_BytesRight[i]) return false; } return true; }
Hafor Stefansonã®æé©åãããå®å
šã§ãªãæ¹æ³
ã¡ãœããã®äœæè
ã¯ããã®æé©åãããã¡ãœããã¯ãé
åã®å
é ãQWORDå¢çã«æããããŠãããšä»®å®ããŠãé
åã®å¯èœãªæ倧éšåã«ã€ããŠ64ãããã®ãããã¯ã§æ¯èŒãè¡ããšäž»åŒµããŠããŸãã QWORDã¢ã©ã€ã¡ã³ãããªãå Žåã§ãåäœããŸãããé床ã¯é
ããªããŸãã
ãã ãã32ãããç°å¢ã§ã¯ã64ããããããã¯ã§ã®æ¯èŒã¯ã¢ã»ã³ãã©ãŒã䜿çšããŠã®ã¿å®çŸã§ããŸããæ±çšã¬ãžã¹ã¿ãŒã¯32ãããã§ãããã³ã³ãã€ã©ãŒã¯ãããã䜿çšããŠãã·ã³ã³ãŒããçæããŸãã
ãããã£ãŠããã®ã¡ãœãããå®éã«ã©ã®ããã«æ©èœãããã¯ãã³ã³ãã€ã«æ¹æ³ã«ãã£ãŠç°ãªããŸãã ç§ã®å Žåãããã¯ééããªã64ãããã§ã¯ãããŸããã
ãã¹ãæ¹æ³
ãã¹ãã»ãã
ãã¹ãæ¡ä»¶ãæŠéæ¡ä»¶ã«ã§ããã ãè¿ã¥ããããã»ããµãã£ãã·ã¥å
ã®ãã¹ãããŒã¿ã®ã劚害ããæé€ããããïŒå¯èœãªéãã¡ã¢ãªã䜿çšïŒãå€ãã®ãã¹ãé
åãçæããããããçžäºã«æ¯èŒããããšã決å®ãããŸããã ããããã®åé
åã
ãã¹ãã»ãããšããŠãããžã£ã°ãã¢ã¬ã€ãéžæãããŸããïŒå
ã®ããã¥ã¡ã³ãã§ã¯ããžã£ã°ã¢ã¬ã€ãïŒã ããããã€ãã®éžæè¢ã¯ãäŸãã°ãã ã£ãã
List<byte[]>
ãš
LinkedList<byte[]>
ãã.NETã®é
åãããã«èŒããŠããªããŠã代æ¿æ¡ã¯ãã¢ã€ãã ã®ã¹ãŒãã®æéã¢ã¯ã»ã¹ããªãã£ãïŒãã©ã®ãããªå Žåã«ã¯CLRãåºåé
åå¢çã®ã€ã³ããã¯ã¹ããã§ãã¯ããŸããããããŒãããŒã¹ã®é
åã§ãã£ãŠãã
ãã¹ãããŒã¿ã¯ããã¹ãŠã®é
åãç°ãªããé
åã®ç°ãªãèŠçŽ ãã¡ããã©äžå€®ã«ãããããªæ¹æ³ã§çæãããŸããã
ãã¹ãããŒã¿çæ private static void PrepareTestData(int p_ArraySize) { for (int i = 0; i < CountArrays; i++) { var byteArray = new byte[p_ArraySize]; byteArray[p_ArraySize / 2] = (byte) (i & 0x000000ff); s_arrays[i] = byteArray; } }
æ¯èŒãã
ãã¹ãŠã®é
åã¯ãã¹ãŠãšæ¯èŒãããããšã«ãªã£ãŠãããããå®è¡æéã枬å®ããã¡ãœããã®äžè¬çãªãã¥ãŒã¯ãã»ããã®ãã¹ãŠã®é
åã«å¯Ÿãã2ã€ã®ãã¹ããããã«ãŒãã§ããããã¹ãã¡ãœããã¯ãã®å
éšã§åŒã³åºãããŸãã äœãèµ·ãã£ãŠãããã®æ¬è³ªã¯ãã³ãŒãã§è¡šçŸããããšãã§ããŸãã
for (int i = 0; i < CountArrays; i++) for (int j = 0; j < CountArrays; j++) Compare( s_arrays[i], s_arrays[j] );
ãã ãããèšç®ãã®çµæã䜿çšããªãå ŽåãCLRã«ã¯ãèšç®ãèªäœãå®è¡ããªããã¹ãŠã®æš©å©ããããŸãã C ++ãè©ŠããŠãããšãã«ãããã«åºããããŸããã ã-O3ãæé©åããªã³ã«ãããšãäœã枬å®ããããšãéåžžã«å°é£ã«ãªããŸããã äœåºŠããŒãã§ããããšãå€æããŸããã ãããã£ãŠãæ¯èŒæ©èœã®çµæããèç©ããããŠè¿ãããæé«ã¬ãã«ã§åæãããããã«ããã®ãããªã·ããªãªãæåããé€å€ããããšã決å®ãããŸããã
çµæãç¡èŠããªãæ¯èŒ var result = true; for (int i = 0; i < CountArrays; i++) for (int j = 0; j < CountArrays; j++) { var tmp = Compare( s_arrays[i], s_arrays[j] ); result = result && tmp; } return result;
æ¯èŒçµæã®åæ var stubLocalVar = p_omparisonMethod(); if (stubLocalVar) throw new InvalidOperationException();
5ã€ã®æ¯èŒæ¹æ³ããããäžèšã®ãã³ãã¬ãŒãã¯äžè¬çã§ãããããäžè¬çãªããã³ãã¬ãŒããæ¹æ³ã決å®ããããã«æ¯èŒæ¹æ³ãæž¡ãããšã¯è«ççã«æããŸãã ãã®ããã«ïŒ
äžæ£ãªé¢æ°åŒã³åºãã¡ãœãã private static bool CompareArraysWithExternalMethod(Func<byte[], byte[], bool> p_Method) { var result = true; for (int i = 0; i < CountArrays; i++) for (int j = 0; j < CountArrays; j++) { var tmp = p_Method( s_arrays[i], s_arrays[j] ); result = result && tmp; } return result; }
ãã®ãããªããã»ã¹ã¯ãåœç¶ã®ããšãªãããé€å€ã³ããŒ/貌ãä»ãããšã©ãŒã®ç¢ºçãæžå°ããããããšåæã«ãç¹ã«å€ãã®ãã®åŒã³åºããèæ
®ãã枬å®ã®ç²ŸåºŠã®æ倱ãžã®äžèŠãªéæ¥ã³ãŒã«ãšé€å€ã®åã蟌ã¿æ¹æ³ïŒã€ã³ã©ã€ã³åïŒãé çªã«ãªãŒããäœæããŸãã ãã®ãããã»ãŒåã5ã€ã®ã¡ãœãããäœæããå¿
èŠããããŸããã
private static bool CompareArraysWithUnsafeMethod(); private static bool CompareArraysWithSimplestMethod(); private static bool CompareArraysWithSequenceEqualMethod(); private static bool CompareArraysWithPInvokeMethod(); private static bool CompareArraysWithIStructuralEquatableMethod();
ãã ããã¬ãã«ãé«ãå Žåã¯ããã³ãã¬ãŒãã¡ãœãããæ¢ã«é©çšã§ããŸãã
以äžã®ã³ãŒãã¯ãæ¯èŒã¡ãœããã®å®è¡æéã枬å®ããMeasureComparisonTimeïŒïŒé¢æ°ãããã©ã¡ãŒã¿ãŒãšããŠFuncåã®ããªã²ãŒããåãããšã瀺ããŠããŸãã 枬å®ãããã®ã¯åœŒã®ã©ã³ã¿ã€ã ã§ãã
ã¡ãœãã枬å®æ©èœ private static long GetMinimalMesuredValue(int p_MeasurementNumber, long p_PreviousValue, long p_MeasuredValue) { var result = p_MeasurementNumber == 0 ? p_MeasuredValue : Math.Min(p_PreviousValue, p_MeasuredValue); return result; } private static long MeasureComparisonTime(Func<bool> p_Method, long p_PreviousTime, int p_MeasurementNumber) { GC.Collect(); GC.Collect(); s_stopwatch.Start(); var stubLocalVar = p_Method(); s_stopwatch.Stop(); if (stubLocalVar) throw new InvalidOperationException(); var result = GetMinimalMesuredValue(p_MeasurementNumber, p_PreviousTime, s_stopwatch.ElapsedTicks); s_stopwatch.Reset(); return result; }
枬å®æé
æéã¯ã
QueryPerformanceCounterïŒïŒã«åºã¥ãæšæºã®ã¹ããããŠã©ããïŒ
ã¯ã©ã¹System.Diagnostics.Stopwatch ïŒã䜿çšããŠæž¬å®ãããŸããã åœç¶ã圌ãã¯ããªç§ã§ã¯ãªãããã¯ã«èå³ããããŸãããå°ããªã¢ã¬ã€ã®å Žåãããªç§åäœã®æž¬å®å€ã¯ãã¹ãŠãŒãã«ãªããŸãã ãŸããRDTSCã®åºç€[6]ã®ãèªè»¢è»ãã䜿çšããããã®ã¢ã€ãã¢ãæã£ãŠããããæåã«ãã¹ãŠã®ãæåã®ããã€ãã®å®è¡ã¯ããããæç¶ãã®é»æµç²ŸåºŠã®ããã«ååã§ããããšã瀺ãããŠããã第äºã«ã䜿çšã®èŠå
ProcessThread.ProcessorAffinityã«ç»å Žããããã¥ã¡ã³ãã®æè¿ã®ããŒãžã§ã³ã§ã¯ããã®ã¯ã©ã¹ã®åºç€ã¯åè¿°ã®ããã»ããµã¯ããã¯ã«ãŠã³ã¿ã§ããããšã瀺åãããŠããŸãã ãã¹ãŠã®æž¬å®ã¯10åç¹°ãè¿ãããæé©ãªæéãåãããŸããã æå°ã®æéã§ããªãæ£ç¢ºãªçµæãåŸããããããæ°å€10ã¯å®éšçã«éžæãããŸããã
ãã¹ãŠã®æž¬å®ãè¡ãæ©èœ private static MeasurementsResults DoMeasurements() { MeasurementsResults result; result.SimplestTime = 0; result.SequenceEqualTime = 0; result.PInvokeTime = 0; result.IStructuralEquatableTime = 0; result.UnsafeTime = 0; for (int measurementNumber = 0; measurementNumber < MeasurementsCount; measurementNumber++) { Console.WriteLine(" {0}", measurementNumber); result.SimplestTime = MeasureComparisonTime(CompareArraysWithSimplestMethod, result.SimplestTime, measurementNumber); result.SequenceEqualTime = MeasureComparisonTime(CompareArraysWithSequenceEqualMethod, result.SequenceEqualTime, measurementNumber); result.PInvokeTime = MeasureComparisonTime(CompareArraysWithPInvokeMethod, result.PInvokeTime, measurementNumber); result.IStructuralEquatableTime = MeasureComparisonTime(CompareArraysWithIStructuralEquatableMethod, result.IStructuralEquatableTime, measurementNumber); result.UnsafeTime = MeasureComparisonTime(CompareArraysWithUnsafeMethod, result.UnsafeTime, measurementNumber); } return result; }
枬å®çµæãšæåã®çµè«
å®éšãéå§ããåã«ãã©ã®æ¹æ³ãåè
ã§ãããã©ã®æ¹æ³ãéšå€è
ã§ããããããã£ãŠããŸããããããã§ãçµæã¯é©ããŸããã ç§ã®äºæž¬ã¯å®å
šã«æ£ãããããŸããã§ããã
ãã¹ãã¿ã€ã ïŒããã¯ïŒ | é
åãµã€ãºïŒãã€ãïŒ | å®å
šã§ãªã | é¡ | ãã³ããŒã¯ | ã·ãŒã±ã³ã¹ | IStructuralEquatable |
---|
276
| 1
| 1.7
| 1
| 6
| 10.5
| 55
|
276
| 1
| 1.7
| 1
| 6.3
| 10.1
| 55.7
|
325
| 2
| 1.3
| 1
| 5.3
| 11
| 95.2
|
374
| 4
| 1,1
| 1
| 4.8
| 11,4
| 121.3
|
413
| 8
| 1
| 1.3
| 5
| 14.1
| 181.2
|
412
| 13
| 1
| 1.7
| 4.7
| 17.5
| 252.5
|
490
| 23
| 1
| 2,3
| 3,7
| 22.1
| 364.8
|
554
| 39
| 1
| 3.4
| 3,5
| 30.1
| 535.9
|
691
| 67
| 1
| 4.3
| 2.9
| 39.1
| 727.5
|
887
| 114
| 1
| 5,6
| 2,4
| 50.3
| 964.1
|
1212
| 194
| 1
| 4.6
| 2.1
| 61.5
| 1190.9
|
1875
| 328
| 1
| 4.8
| 1.8
| 65.8
| 1295.8
|
2897
| 556
| 1
| 5
| 1,6
| 71.5
| 1416.9
|
4565
| 942
| 1
| 5.3
| 1.4
| 76.3
| 1521.1
|
7711
| 1595
| 1
| 5.2
| 1.3
| 76,2
| 1521.2
|
12482
| 2702
| 1
| 5,4
| 1.3
| 79,4
| 1593.6
|
20692
| 4576
| 1
| 5.5
| 1,2
| 81.2
| 1626.2
|
34369
| 7750
| 1
| 5,6
| 1,2
| 82.8
| 1657.1
|
58048
| 13124
| 1
| 5,6
| 1,2
| 82.9
| 1661.9
|
97511
| 22226
| 1
| 5,6
| 1,2
| 83.6
| 1677.3
|
173805
| 37640
| 1
| 5,4
| 1,1
| 79.5
| 1585.7
|
295989
| 63743
| 1
| 5.3
| 1,1
| 79.3
| 1574.9
|
588797
| 107949
| 1
| 4.6
| 1,1
| 67.5
| 1340.9
|
1010768
| 182811
| 1
| 4.6
| 1,1
| 67
| 1340.4
|
1705668
| 309590
| 1
| 4.6
| 1,1
| 67.3
| 1334.1
|
2885452
| 524287
| 1
| 4.6
| 1,1
| 67.3
| 1329.1
|
çµæã¯æ¬¡ã®ãšããã§ãã
æåã«ïŒCRTé¢æ°ã¯åçŽã«æé©åããå¿
èŠããããç¹å®ã®æ®µéïŒãã¹ãé
åã®ãµã€ãºïŒã§ãã®é床ããã©ãããã©ãŒã åŒã³åºãã®ãªãŒããŒãããããããã¯ãããšèšç®ããŸããããããã¯èµ·ãããŸããã§ããã åŸã§ãã¯ããã«å€§ããªã¢ã¬ã€ã§ãã¹ããç¹°ãè¿ããŸãããã1.5ã¡ã¬ãã€ãã§ãå®å
šã§ãªãã³ãŒãã®æ¹ãé«éã§ããããšãããããŸããã
2çªç®ïŒIStructuralEquatableã¯é
ããªããšæããŸããããæ°åã¯åã«ç§ãé©ãããŸããïŒç§ã¯ééããªããããæåŸ
ããŠããŸããã§ããã
åã
ã®æ©èœã®èšºæãšåæ
çããæ·±å»å€§ããã¢ã¬ã€äžå±éºãªæãåçŽãªå·®ãããïŒç§ã¯ãã以äžã®2ã€ã®3æéãå©ç¹ãããäºæ³ïŒããããµããŒã¿ãŒã¯ãè«æ±é
ã®ããã«.NETã®é
åã®èŠçŽ ãæé©åããæ§èšŽã®ãµã€ã¯ã«ã¯ããã»ã©æ»ããã§ã¯ãªãããšã瀺åããŠããŸãã ãããã£ãŠãç§ã¯JIT'erã®ä»äºã®çµæãèŠãããšã®åã³ãåŠå®ããŸããã§ããã çŽæ¥çæããããã·ã³ã³ãŒãã
CompareArraysWithSimplestMethodïŒïŒé¢æ°ã®åæ
ãããè¡ãããã«ãã¡ãœããã®æåã«Thread.SleepïŒ60 * 1000ïŒãæ¿å
¥ãããŸããã ãªãªãŒã¹ãã«ããèµ·åããåŸãOllyDebugããã»ã¹ãéžæããŸããã ãã®ãããªããªãããŒãªåãã¯ãCLRã®æé©åãæãªãããšããªãããã«ããããã«å¿
èŠã§ããã
ntdll.NtDelayExecutionïŒïŒãšSleepExïŒïŒããã³ãŒã«ã¹ã¿ãã¯ãäžã£ãŠè¡ããšãç§ã¯èªåã®é¢æ°ãèŠã€ããæ
éã«ç 究ããåŸãåã³äžå¿«ã«é©ããŸããã ããã§æ¬åœã«å¥œãã§ã¯ãªãã£ããã®ïŒ
- åäžã®RngChkFailãã§ãã¯ïŒã«ãŒãå
šäœã«å¯ŸããŠïŒã®ä»£ããã«ãCLRã¯ã€ã³ããã¯ã¹ããšã«ãã®ãã§ãã¯ãè¡ããŸã!!!
- ãµã€ã¯ã«ã¯ãç§ãæžãã圢ã®ãŸãŸã§ãããã³ã³ãã€ã©ã¯ãããããããã€ãããŸããã§ããã
- ãããã£ãŠãCLRã¯4ãã€ãïŒã¬ãžã¹ã¿ãµã€ãºïŒã®æ¯èŒãè¡ããªã©ãCLRãæé©åããããšã¯ã§ããŸããããæ¯èŒã¯ãã€ãåäœã®ãŸãŸã§ããã
- åäžã®ãšãããŒã°ã§åäžã®æ»ãå€ãè¿ããŠã¹ã¿ãã¯ãã¯ãªã¢ãã代ããã«ãCLRã¯ãããã3åã³ããŒããã³ãŒãããèšåŒµããããŸããã å®éããã·ã³ã³ãŒãã¯CïŒã³ãŒããã»ãŒ1察1ã§ç¹°ãè¿ããŸãã ããã«é¢ããŠãçåãçããŸãã圌ã¯ã³ãŒãããŸã£ããæé©åããŸãããïŒïŒ 圌ã¯ãããè¡ãæ¹æ³ãç¥ã£ãŠããŸããïŒ
- ããããåã®æ®µèœïŒã³ãŒãã®èšåŒµïŒã®ãããã§ãé¢æ°ã¯ã€ã³ã©ã€ã³åãããŸããã§ããã
UnsafeCompareïŒïŒé¢æ°åæ
ãã®é¢æ°ãéã³ã³ãã€ã«ããçµæãç§ã®å¥œå¥å¿ãçãäžãããä»ã®é¢æ°ã«ã€ããŠèããããã«ãªããŸããã CRTæ©èœãšå®å
šã§ãªããªãã·ã§ã³ãæ¯èŒããããšã«ããŸããã ãŸããå®å
šã§ãªããªãã·ã§ã³ãæ€èšããããšã«ããŸããã ãããè¡ãã«ã¯ãæåã®é¢æ°ãšåãæäœãè¡ããŸããããThread.SleepïŒïŒã¯é¢æ°èªäœã§ã¯ãªããåŒã³åºãããåã«æ¿å
¥ãããŸããã ããã¯ãäœãèµ·ãã£ãŠãããã®æ¬è³ªã«ã»ãšãã©åœ±é¿ãäžããããšã¯ã§ããŸããã§ããããéã³ã³ãã€ã«ã幟ååçŽåããŸãããå®å
šã§ãªãé¢æ°ã¯æããã«æåã®ãã®ããè€éã§ãã
æ¿å
¥ã¹ã¬ãããã¹ãªãŒãïŒïŒ private static bool CompareArraysWithUnsafeMethod() { var result = true; for (int i = 0; i < CountArrays; i++) for (int j = 0; j < CountArrays; j++) { Thread.Sleep( 60 * 1000 ); var tmp = UnsafeCompare(s_arrays[i], s_arrays[j]);
ãã®é¢æ°ã®ååãéèŠã§ãã UnsafeCompareïŒïŒãåŒã³åºããããŸã§ã æåã®äŸãšåæ§ã«ãé
åã®èŠçŽ ã«ã¢ã¯ã»ã¹ãããšãé
åã®å¢çå
ã§ã€ã³ããã¯ã¹ããã§ãã¯ãããŸãã ç§ã¯ããªã¹ãã«ãã®ããšã匷調ããŸããã
CPU Disasm CompareArraysWithUnsafeMethod ;Address Hex dump Command Comments 001B0B88 55 push ebp ; 001B0B89 8BEC mov ebp, esp 001B0B8B 57 push edi 001B0B8C 56 push esi 001B0B8D 53 push ebx 001B0B8E BF 01000000 mov edi, 1 ; result = true; 001B0B93 33DB xor ebx, ebx ; for (int i = 0; 001B0B95 33F6 xor esi, esi ; for (int j = 0; 001B0B97 B9 60EA0000 mov ecx, 0EA60 ; Thread.Sleep( 60 * 1000 ); 001B0B9C E8 0CFBC161 call clr.ThreadNative::Sleep 001B0BA1 8B15 A8337A03 mov edx, [s_arrays] ; EDX <-- s_arrays 001B0BA7 3B5A 04 cmp ebx, [edx+4] ; Compare(s_arrays.Length, ) (1) !!! 001B0BAA 73 31 jae short stub_CLR.JIT_RngChkFail 001B0BAC 8B4C9A 0C mov ecx, [ebx*4+edx+0C] ; ECX <-- s_arrays[i] 001B0BB0 3B72 04 cmp esi, [edx+4] ; Compare(s_arrays.Length, ) (2) !!! 001B0BB3 73 28 jae short stub_CLR.JIT_RngChkFail 001B0BB5 8B54B2 0C mov edx, [esi*4+edx+0C] ; EDX <-- s_arrays[j] 001B0BB9 FF15 F0381400 call near UnsafeCompare
é¢æ°ã®éã³ã³ãã€ã«ã®çµæã¯éåžžã«å€§ããã1ã€ã®ç»é¢ã«åãŸããªãããããããã¬ãŠã£ã³ããŠã®ã¹ã¯ãªãŒã³ã·ã§ããã¯æäŸããŸããã§ããã 倧èŠæš¡ãªçµ±åããããªã¹ãã¯èªãã®ãéå±ã§éçç£çã§ãããããããã§ã¯è«ççã«é¢é£ããæçã§èª¬æããåæçã«çãã³ã¡ã³ããä»ããŸãã
UnsafeCompareïŒïŒã ;a1 ========> ECX ;a2 ========> EDX ;Address Hex dump Command Comments 001B0BF8 55 push ebp ; 001B0BF9 8BEC mov ebp, esp 001B0BFB 57 push edi ; , , , 001B0BFC 56 push esi ; 001B0BFD 53 push ebx ; 001B0BFE 83EC 0C sub esp, 0C ; 3*sizeof(DWORD), .. 3 001B0C01 33C0 xor eax, eax ; (!) 001B0C03 8945 F0 mov [ebp-10], eax ; var1 <-- 0 (!) 001B0C06 8945 EC mov [ebp-14], eax ; var2 <-- 0 (!) 001B0C09 85C9 test ecx, ecx ; Compare(a1, null) 001B0C0B 74 0C je short return1 001B0C0D 85D2 test edx, edx ; Compare(a2, null) 001B0C0F 74 08 je short return1 001B0C11 8B41 04 mov eax, [ecx+4] ; eax <-- a1.Length 001B0C14 3B42 04 cmp eax, [edx+4] ; Compare(eax, a2.Length) 001B0C17 74 0A je short argsIsValid return1: 001B0C19 33C0 xor eax, eax ; result <-- 0 001B0C1B 8D65 F4 lea esp, [ebp-0C] 001B0C1E 5B pop ebx 001B0C1F 5E pop esi 001B0C20 5F pop edi 001B0C21 5D pop ebp 001B0C22 C3 ret argsIsValid: ;
.NET Framework [7] [8]ã«ç¶ãfastcallåŒã³åºãèŠçŽã«ãããšãæåãš2çªç®ã®ãã©ã¡ãŒã¿ãŒã¯ãå·Šããå³ã®é ã«ecxããã³edxã¬ãžã¹ã¿ãŒã«ãããŸãã äžèšã®ãªã¹ãã§ã¯ãå
¥åãã©ã¡ãŒã¿ãŒã®é 次ãã§ãã¯ãæ確ã«è¡šç€ºãããŠãããCïŒã®ã³ãŒãã«ã»ãŒæ確ã«å¯Ÿå¿ããŠããŸãã
if (a1 == null || a2 == null || a1.Length != a2.Length) return false;
ãã ãã匷調衚瀺ãããŠããè¡ã«ã¯ç¹å¥ãªæ³šæãå¿
èŠã§ãããã®ç®çã¯äžæã§ãããæ··ä¹±ãæããŸãã ãããäœã§ããå¿
èŠãããã®ãââãç解ããããã«ãå¥ã®å®éšãè¡ãå¿
èŠããããŸããããã®éã«ãCïŒã§æãåçŽãªå®å
šã§ãªãé¢æ°ãäœæããŸããããã®é¢æ°ã¯åºå®å¥ãšãã€ã³ã¿ãŒåŠçã䜿çšããåæ§ã®ã¢ã¯ã·ã§ã³ãå®è¡ããŸããã
private static unsafe int func1(byte[] param1) { fixed (byte* p = param1) { return *p; } }
æãåçŽãªå®å
šã§ãªãæ©èœã®æ²æšã ;param1 ========> ECX Address Hex dump Command Comments $ ==> 55 push ebp ; $+1 8BEC mov ebp, esp $+3 50 push eax ; (!) $+4 33C0 xor eax, eax ; (!) $+6 8945 FC mov [ebp-4], eax ; var1 <-- 0 (!) $+9 85C9 test ecx, ecx ; Compare(param1, null) $+B 74 06 je short param_is_null $+D 8379 04 00 cmp dword ptr [ecx+4], 0 ; Compare(param1.Length, 0) $+11 75 07 jne short not_zero_len param_is_null: $+13 33D2 xor edx, edx $+15 8955 FC mov [ebp-4], edx ; var1 <-- 0 $+18 EB 0C jmp short ret_1 not_zero_len: $+1A 8379 04 00 cmp dword ptr [ecx+4], 0 $+1E 76 10 jbe short call.JIT_RngChkFail $+20 8D49 08 lea ecx, [ecx+8] ; ecx <-- param1.BufferPointer $+23 894D FC mov [ebp-4], ecx ; var1 <-- ecx ret_1: $+26 8B45 FC mov eax, [ebp-4] ; eax <-- var1 $+29 0FB600 movzx eax, byte ptr [eax] ; eax <-- *eax $+2C 8BE5 mov esp, ebp ; $+2E 5D pop ebp $+2F C3 ret call.JIT_RngChkFail: $+30 E8 B3BDC861 call clr.JIT_RngChkFail $+35 CC int3
ããããªã¹ãäžããã«ããããããæ±çšã¬ãžã¹ã¿ã®å¯çšæ§ã®ãã¹ã¿ãã¯äžã«çœ®ãããã«ããŠãã ããåºå®ææ¡ã«ãããJITã³ã³ãã€ã«å€æ°ã®çµæãšããŠãã®æ確ã«ãªããŸãã ããã¯ãeaxã¬ãžã¹ã¿ãŒãã¹ã¿ãã¯ã«ä¿åãããå°æ¥äœ¿çšãããããããã£ãŠæäœã®ããã«ç¡æã§ã¢ã¯ã»ã¹å¯èœã§ããïŒé¢æ°ã®éå§ãããªãã»ãã0x26ãŸã§ïŒãããªãã»ããå€æ°ã¹ã¿ãã¯å€æ°ãäžæããŒã¿ãæ ŒçŽããããã«äœ¿çšããããšããäºå®ããæããã§ãebp-4]ïŒvar1ãšåŒã³ãŸãããïŒã å€æ°ã¯ãããã䜿çšãããŠããŸããããåçŽã«äžæžããããŠããã«ãããããããããã«å¿
ããããŒãã«åæåãããŸãã äŸãã°ãVAR1ãŒãã§0x15ã®ãªãã»ããã¯æ¢ã«ãŒãæ ŒçŽããããã®æç¹ã§ååšãããšããäºå®ã«ãããããããåã³å
¥åãããŸãã
ãããã£ãŠãããã¯ãªã¹ãUnsafeCompare.CPU Disasm.ParametersCheckingã§éžæãããè¡ã«ç¹å¥ãªæå³ã¯ãªãã¯ããååšããªãããšãæããã«ãªããããã¯ã³ã³ãã€ã«ã®ã¡ããã©å¯äœçšã§ãã ãŸããäžèšã®ãªã¹ããããé
åã3ã€ã®æ®µéã§åºå®åŒã§ãã§ãã¯ãããããšãæããã«ãªããŸãïŒæåã«ãé
åã®nullããã§ãã¯ããã次ã«ãã®é·ãããŒããšçãããïŒjneã³ãã³ããZFã®ã¿ãåæããïŒããŒããšè² ã®å€ãçãããããã§ãã¯ãããŸãïŒ jbeã¯ZFãšCFã®äž¡æ¹ããã§ãã¯ããŸãïŒã ç§ã®èŠç¹ããã¯ãæ¡ä»¶åå²ããã©ã°ããªã»ããããªããããCMPåœä»€ã¯ã2åå®è¡ãããŠããããšãããã¹ãŠã®ããå€ãã®å¥åŠãªæåŸã®2ã€ã®æé ãäžã€ã«çµåãããããšã¯ãªããå¥åŠã§ããããšã ããã¯ç§ãç¡é§ã«ããããšããŠããªãããšãæå³ããããã³ã¢ã»ã³ããªãªã¹ãã®ç§ã®çºæ調æ»ã¯ç¡é§ã§ã¯ãªãã£ãã®ã§ãä»ã®ãã®ã®äžã§ãç§ã¯ããã®è¡ãèªãã§ããªãã®äººã
ã«å¿ããæè¬ããŠããŸãã
ãã®å®éšã¯ãããã«ã³ãŒãåæã倧å¹
ã«ç°¡çŽ åããŸãã
CompareArraysWithUnsafeMethodïŒïŒé¢æ°ã®åºå®å¥ argsIsValid: 001B0C23 8379 04 00 cmp dword ptr [ecx+4], 0 ; Compare(a1.Length, 0) 001B0C27 75 07 jne short a1Len_NonZero ; 001B0C29 33C0 xor eax, eax 001B0C2B 8945 F0 mov [ebp-10], eax ; var1 <-- 0 001B0C2E EB 10 jmp short a1Len_Zero a1Len_NonZero: 001B0C30 8379 04 00 cmp dword ptr [ecx+4], 0 ; Compare(a1.Length, 0) () 001B0C34 0F86 B5000000 jbe call.JIT_RngChkFail ; 001B0C3A 8D41 08 lea eax, [ecx+8] ; eax <-- a1.BufferPointer 001B0C3D 8945 F0 mov [ebp-10], eax ; var1 <-- eax a1Len_Zero: 001B0C40 837A 04 00 cmp dword ptr [edx+4], 0 ; Compare(a2.Length, 0) 001B0C44 75 07 jne short a2Len_NonZero ; 001B0C46 33D2 xor edx, edx 001B0C48 8955 EC mov [ebp-14], edx ; var2 <-- 0 001B0C4B EB 10 jmp short part3 a2Len_NonZero: 001B0C4D 837A 04 00 cmp dword ptr [edx+4], 0 ; Compare(a2.Length, 0) () 001B0C51 0F86 98000000 jbe call.JIT_RngChkFail ; 001B0C57 8D52 08 lea edx, [edx+8] ; edx <-- a2.BufferPointer 001B0C5A 8955 EC mov [ebp-14], edx ; var2 <-- edx
ã³ã³ãã€ã©ã¯ããã§é©ãã瀺ããŸããã§ããã ã³ã³ãã€ã«ã¢ã«ãŽãªãºã ã«ãããç°¡åã«äºæž¬å¯èœãªçµæãåŸãããŸãã ããšãã°ãåºå®å¥ã§åæåãããå€æ°ã¯ããšã«ããã¹ã¿ãã¯ã«ããã·ã¥ãããŸãã
åºå®ãããã¯å
ã®å€æ°ã®åæåïŒ
part3: ; ECX <======= a1 ; EDX <======= a2.BufferPointer ; var1 <======= a1.BufferPointer ; var2 <======= a2.BufferPointer 001B0C5D 8B45 F0 mov eax, [ebp-10] ; eax <-- var1 001B0C60 8BF0 mov esi, eax ; esi <-- eax 001B0C62 8B45 EC mov eax, [ebp-14] ; eax <-- var2 001B0C65 8BF8 mov edi, eax ; edi <-- eax 001B0C67 8B41 04 mov eax, [ecx+4] ; eax <-- a1.Length 001B0C6A 8945 E8 mov [ebp-18], eax ; var3 <-- eax
åºå®ãããã¯å
ã®å€æ°ã®åæåã¯ãJITã³ã³ãã€ã©ãŒãã³ãŒããçæããåçããã瀺ããŠãããšããç¹ã§èå³æ·±ããã®ã§ããããã§ã¯ãã¹ã¿ãã¯å€æ°ããã€ã³ããã¯ã¹ã¬ãžã¹ã¿ã«å€ãçŽæ¥éä¿¡ãã代ããã«ãå€ãæåã«ã¢ãã¥ã ã¬ãŒã¿ã¬ãžã¹ã¿ã«é
眮ãããããšãæ確ã«ç€ºãããŠããŸãããã¶ããããã¯ããçš®ã®ç§å¯ã®éæ³ã®æå³ã§ãããããã¯äœåãªã¢ã¯ã·ã§ã³ã®ããã«èŠããŸãïŒeaxã«éä¿¡ïŒã8ãã€ãã®ã«ãŒã 001B0C6D 33C9 xor ecx, ecx ; <-- 0 001B0C6F 8BD8 mov ebx, eax ; ebx <-- a1.Length 001B0C71 85DB test ebx, ebx 001B0C73 79 03 jns short ebx_greaterZero 001B0C75 83C3 07 add ebx, 7 ; , 7 ebx_greaterZero: 001B0C78 C1FB 03 sar ebx, 3 ; ebx <-- a1.Length / 8 001B0C7B 85DB test ebx, ebx 001B0C7D 7E 1D jle short fourBytesComparing for8_body: 001B0C7F 8B06 mov eax, [esi] 001B0C81 8B56 04 mov edx, [esi+4] 001B0C84 3B57 04 cmp edx, [edi+4] 001B0C87 75 04 jne short setResult_jumpReturn 001B0C89 3B07 cmp eax, [edi] 001B0C8B 74 04 je short for8_increment setResult_jumpReturn: 001B0C8D 33C0 xor eax, eax ; result <-- 0 001B0C8F EB 56 jmp short return2 ; goto return for8_increment: 001B0C91 41 inc ecx 001B0C92 83C6 08 add esi, 8 001B0C95 83C7 08 add edi, 8 for8_expression: 001B0C98 3BD9 cmp ebx, ecx 001B0C9A ^ 7F E3 jg short for8_body
ãµã€ã¯ã«ã®æ§é ã¯éåžžã«ç°¡åã§ããããšãã°ããµã€ã¯ã«ã«ãŠã³ã¿ãŒã¯äŒçµ±çã«ecxã«é
眮ãããã«ãŠã³ã¿ãŒã®å¢çå€ã¯ebxã«é
眮ãããŸããããããäŒçµ±çã§ããããã§æ³šç®ãã¹ãã¯ãã«ãŒãæ¡ä»¶ã®æåã®ãã§ãã¯ãåæåçŽåŸã«ãããã¡ã€ã³ã«ãŒãæ¡ä»¶ã®ããã«èŠããªãããšã§ããå¥è·¡ãèµ·ãããªãããšãæããã§ãããREXãã¬ãã£ãã¯ã¹ã¯ä¿è·ã¢ãŒããŸãã¯äºæã¢ãŒãã®ãããã§ã䜿çšã§ããŸããã QWORDãããã¯ãšã®æ¯èŒã¯äžå¯èœã§ãããããDWORDãµã€ãºã®ãããã¯ãæ¯èŒãããŸãããã ããã³ãŒãã¯ãæ¯èŒãå®è¡ããåã«ãæåã®é
åã®å¯Ÿå¿ããéšåãeaxãedxã¬ãžã¹ã¿ã«ããŒããããããšã瀺ããŠããŸãã JITã³ã³ãã€ã©ã¯ããœãŒã¹ã³ãŒãã«å¯èœãªéãè¿ããã·ã³ã³ãŒããçæããããšããŸãããã³ã³ãã€ã©ãããã§CMPSDæåååœä»€ãã€ãŸããesiãšediã¢ãã¬ã¹ã«é
眮ãããDWORDãããã¯ãæ¯èŒããé©åãªãã©ã°ãèšå®ãããçãã圢åŒã䜿çšããªãã£ãããšã¯é©ãã¹ãããšã§ãããã®å Žåããã·ã³ã³ãŒãã®ãµã€ãºã¯æ°åå°ãããªããŸãïŒmovã³ãã³ãã®ãµã€ãºã¯2ãã€ããš3ãã€ããcmpã³ãã³ãã®ãµã€ãºã¯2ãã€ããš3ãã€ããåCMPSDã³ãã³ãã®ãµã€ãºïŒçã圢åŒïŒã¯1ãã€ãã®ã¿ã§ãã ã 2ããŒã ã®å Žåã¯2ãã€ãã®ã¿ãããã¯ãJITã³ã³ãã€ã©ãŒãã³ãŒãã®æé©åãæãŸãªãããšã瀺åããŠããŸããäžèšã®ãªã¹ããããæåã®ã³ãã³ããeaxãžã®è»¢éã§ããããã€ãã®ã³ãã³ãããã³ã³ãã€ã©ãŒãå³å¯ã«åŸããã¿ãŒã³ã§ããããšã¯æããã§ãããã®ãããªããªã¥ãŒã ãæ®ã£ãŠããå ŽåãDWORDãµã€ãºã®ãããã¯ãæ¯èŒããããšããŸãã fourBytesComparing: 001B0C9C F745 E8 0400000 test dword ptr [ebp-18], 00000004 ; ZF <-- (var3 & 4) == 0 001B0CA3 74 10 je short length_lowerThenFour 001B0CA5 8B06 mov eax, [esi] 001B0CA7 3B07 cmp eax, [edi] 001B0CA9 74 04 je short dwords_equals ; , 001B0CAB 33C0 xor eax, eax 001B0CAD EB 38 jmp short return2 dwords_equals: 001B0CAF 83C6 04 add esi, 4 001B0CB2 83C7 04 add edi, 4
WORD, , :
length_lowerThenFour: 001B0CB5 F745 E8 0200000 test dword ptr [ebp-18], 00000002 ; ZF <-- (var3 & 2) == 0 001B0CBC 74 10 je short length_lowerThenTwo 001B0CBE 0FBF06 movsx eax, word ptr [esi] 001B0CC1 66:3B07 cmp ax, [edi] 001B0CC4 74 04 je short words_equals ; , 001B0CC6 33C0 xor eax, eax 001B0CC8 EB 1D jmp short return2 words_equals: 001B0CCA 46 inc esi 001B0CCB 46 inc esi 001B0CCC 47 inc edi 001B0CCD 47 inc edi
BYTE, , :
length_lowerThenTwo: 001B0CCE F745 E8 0100000 test dword ptr [ebp-18], 00000001 ; ZF <-- (var3 & 1) == 0 001B0CD5 74 0B je short 001B0CE2 001B0CD7 0FB606 movzx eax, byte ptr [esi] 001B0CDA 3A07 cmp al, [edi] 001B0CDC 74 04 je short 001B0CE2 ; , 001B0CDE 33C0 xor eax, eax 001B0CE0 EB 05 jmp short return2 001B0CE2 B8 01000000 mov eax, 1
:
return2: 001B0CE7 8D65 F4 lea esp, [ebp-0C] 001B0CEA 5B pop ebx 001B0CEB 5E pop esi 001B0CEC 5F pop edi 001B0CED 5D pop ebp 001B0CEE C3 ret JIT_RngChkFail: 001B0CEF E8 C4B1DB61 call clr.JIT_RngChkFail 001B0CF4 CC int3
CRT memcmp()
, , , , , , .
, 0x76C20000 C:\Windows\SysWOW64\msvcrt.dll 7.0.7601.17744.
, , .. , , .
: -, , , , -, . «» , switch 32 case' .
:
76C37975 . 8BFF mov edi, edi ; <--(!) INT msvcrt.memcmp(buf1,buf2,count) 76C37977 . 55 push ebp 76C37978 . 8BEC mov ebp, esp
, , .. , nop, 2 . , , . . nop.
It's a hot-patch point.
The MOV EDI, EDI instruction is a two-byte NOP, which is just enough space to patch in a jump instruction so that the function can be updated on the fly. The intention is that the MOV EDI, EDI instruction will be replaced with a two-byte JMP $-5 instruction to redirect control to five bytes of patch space that comes immediately before the start of the function. Five bytes is enough for a full jump instruction, which can send control to the replacement function installed somewhere else in the address space.
blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214405.aspx
switch Address Hex dump Command Comments 75A9797C . 8B7D 10 mov edi, [ebp+10] ; edi <-- length 75A9797F . 8BC7 mov eax, edi 75A97981 . 83E8 00 sub eax, 0 ; 75A97984 . 0F84 E7070100 je msvcrt.zeroResult_GoReturn ; (length == 0)=> {result <-- 0, goto return;} (!) ; ; 75A979BC . 83FF 1F cmp edi, 1F ; Switch (cases 1..1F, 32. exits) 75A979BF . 77 5B ja short msvcrt.75A97A1C 75A979C1 . FF24BD 1F8AA975 jmp near [edi*4+msvcrt.75A98A1F] ; (!) (!) ; ; 75A98A1F . 1C7AA975 dd msvcrt.75A97A1C ; (00) , jump 75A98A23 . E88AA975 dd msvcrt.75A98AE8 ; (01) 75A98A27 . CA8AA975 dd msvcrt.75A98ACA ; (02) 75A98A2B . 8C8BA975 dd msvcrt.75A98B8C ; (03) 75A98A2F . 0A7AA975 dd msvcrt.75A97A0A ; (04) 75A98A33 . 088FA975 dd msvcrt.75A98F08 ; (05) 75A98A37 . B88AA975 dd msvcrt.75A98AB8 ; (06) 75A98A3B . 758BA975 dd msvcrt.75A98B75 ; (07) 75A98A3F . F479A975 dd msvcrt.75A979F4 ; (08) 75A98A43 . 238FA975 dd msvcrt.75A98F23 ; (09) 75A98A47 . 9F8AA975 dd msvcrt.75A98A9F ; (0A) 75A98A4B . A18BA975 dd msvcrt.75A98BA1 ; (0B) 75A98A4F . DE79A975 dd msvcrt.75A979DE ; (0C) 75A98A53 . 3A8FA975 dd msvcrt.75A98F3A ; (0D) 75A98A57 . FD8AA975 dd msvcrt.75A98AFD ; (0E) 75A98A5B . ED8EA975 dd msvcrt.75A98EED ; (0F) 75A98A5F . C879A975 dd msvcrt.75A979C8 ; (10) 75A98A63 . 518FA975 dd msvcrt.75A98F51 ; (11) 75A98A67 . BA8EA975 dd msvcrt.75A98EBA ; (12) 75A98A6B . 6A98A975 dd msvcrt.75A9986A ; (13) 75A98A6F . 8990A975 dd msvcrt.75A99089 ; (14) 75A98A73 . CD98A975 dd msvcrt.75A998CD ; (15) 75A98A77 . D58EA975 dd msvcrt.75A98ED5 ; (16) 75A98A7B . 8598A975 dd msvcrt.75A99885 ; (17) 75A98A7F . 1899A975 dd msvcrt.75A99918 ; (18) 75A98A83 . E898A975 dd msvcrt.75A998E8 ; (19) 75A98A87 . 698FA975 dd msvcrt.75A98F69 ; (1A) 75A98A8B . 9D98A975 dd msvcrt.75A9989D ; (1B) 75A98A8F . 3399A975 dd msvcrt.75A99933 ; (1C) 75A98A93 . 0099A975 dd msvcrt.75A99900 ; (1D) 75A98A97 . 848FA975 dd msvcrt.75A98F84 ; (1E) 75A98A9B . B598A975 dd msvcrt.75A998B5 ; (1F)
, :
- (overhead) «» (PInvoke)
- .
é¢æ°ãåŒã³åºããªãŒããŒããããæšå®ããããã«ããããŒãžã³ãŒãããé¢æ°èªäœã®éå§ãŸã§ã³ãŒãããã¬ãŒã¹ããããšã«ããŸããããããè¡ãããã«ãé¢æ°ã®å
é ã«ãã¬ãŒã¯ãã€ã³ããèšå®ãããThread.SleepïŒïŒããæ»ã£ãåŸããã¬ãŒã¹ãéå§ãããŸããããã ããæåã®ãã¬ãŒã¹è©Šè¡ã®çµæã¯å€±æããŸããããã¬ãŒã¹ãã°ã倧ããããŠïŒçŽ10äžè¡ïŒãDllMainïŒïŒãå®è¡ãããããšã瀺ããŠããå¯èœæ§ããããäžéšã®CLRã³ãŒãããã£ããã£ãããå¯èœæ§ããããŸãã JITã³ã³ãã€ã©ã³ãŒããããã§äœãæ£ç¢ºã«è¡ãããã®ããç§ã¯çºèŠãå§ããŸããã§ããããã®ãããªéå§ã³ãŒãã¯1åã ãå®è¡ãããå
šäœåã«ã¯ã»ãšãã©åœ±é¿ããŸããããã®ã³ãŒããé€å€ããããã«ãThread.SleepïŒïŒãåŒã³åºããŠå床ãã¬ãŒã¹ããåã«ãmemcmpïŒïŒãžã®å¥ã®åŒã³åºããæ¿å
¥ããŸããããã®çµæã100è¡ãå°ãè¶
ããŸããããã¬ãŒã¹ãã°ã®äžéšïŒ main 00480AEA call 0031C19C ESP=0016F368 ; main clr.628C3B5F call near [eax+14] ESP=0016F248 ; (1) ; main 00480B87 mov eax, [ebp-1C] EAX=00313880 main 00480B8A mov eax, [eax+14] EAX=0031391C main 00480B8D mov ecx, [eax] ECX=75A97975 ; (2) main 00480B8F push dword ptr [ebp+0C] ESP=0016F328 main 00480B92 push dword ptr [ebp+8] ESP=0016F324 main 00480B95 push edi ESP=0016F320 main 00480B96 push dword ptr [ebp-10] ESP=0016F31C main 00480B99 mov dword ptr [ebp-2C], 0 main 00480BA0 mov [ebp-28], esp main 00480BA3 mov dword ptr [ebp-24], 480BB0 main 00480BAA mov byte ptr [ebx+8], 0 main 00480BAE call ecx ESP=0016F318 ; (3) main msvcrt.memcmp mov edi, edi
äžèšã®ãã°ããããŸããé¢æ°ãžã®éäžã§å°ãªããšã1ã€ã®éæ¥åŒã³åºããçºçãã次ã«ãCLRãäœããã®ããŒã¿æ§é ããæçµé¢æ°ã®ã¢ãã¬ã¹ãæœåºããããšãããããŸãã課é¡ã«ã¯ããªãã®éæ¥æ§ãããã移è¡äºæž¬ãŠãããã«ãã®äœ¿åœãæããåžæãæ®ããŸãããããã«ãããäžåºŠã«å€§éã®ããŒã¿ãåŠçãããå€ãã®èšç®æéãå¿
èŠãšããªãå ŽåããããŒãžã³ãŒãã®ç¯å²å€ã§ãã®ãããªé¢æ°ã䜿çšããã®ã¯ç¡æå³ã«ãªããŸããã¡ã€ã³æ©èœã³ãŒãã®è©äŸ¡
, , . . . , .
, , . , -, , , , -, , , , .
å€æŽãããé
åæ¯èŒé¢æ° private static bool CompareArraysWithPInvokeMethod() { var result = true; for (int i = CountArrays - 1; i >= 0; i--)
æåã®ãã¬ãŒã¹ïŒãã¹ãã±ãŒã¹ïŒ main msvcrt.memcmp mov edi, edi main msvcrt.75A97977 push ebp ESP=0041EC74 main msvcrt.75A97978 mov ebp, esp EBP=0041EC74 main msvcrt.75A9797A push esi ESP=0041EC70 main msvcrt.75A9797B push edi ESP=0041EC6C main msvcrt.75A9797C mov edi, [ebp+10] EDI=00080000 ; edi <-- count main msvcrt.75A9797F mov eax, edi EAX=00080000 ; eax <-- edi main msvcrt.75A97981 sub eax, 0 ; if (eax == 0) {result <-- 0; return;} main msvcrt.75A97984 je msvcrt.zeroResult_GoReturn main msvcrt.75A9798A dec eax EAX=0007FFFF main msvcrt.75A9798B je msvcrt.75A98C10 main msvcrt.75A97991 dec eax EAX=0007FFFE main msvcrt.75A97992 je msvcrt.75A9E610 main msvcrt.75A97998 dec eax EAX=0007FFFD main msvcrt.75A97999 je msvcrt.75A9E5DF main msvcrt.75A9799F dec eax EAX=0007FFFC main msvcrt.75A979A0 je msvcrt.75A98BD2 main msvcrt.75A979A6 mov ecx, [ebp+0C] ECX=034C53B8 ; ecx <-- buf1 main msvcrt.75A979A9 mov eax, [ebp+8] EAX=05C41038 ; eax <-- buf2 main msvcrt.75A979AC push ebx ESP=0041EC68 main msvcrt.75A979AD push 20 ESP=0041EC64 ; main msvcrt.75A979AF pop edx EDX=00000020, ESP=0041EC68 ;-------------------------------- main msvcrt.75A979B0 cmp edi, edx main msvcrt.75A979B2 jae msvcrt.75A993A7 main msvcrt.75A993A7 mov esi, [eax] ESI=4241403F main msvcrt.75A993A9 cmp esi, [ecx] main msvcrt.75A993AB jne msvcrt.75AA80E7 ; main msvcrt.75AA80E7 movzx esi, byte ptr [eax] ESI=0000003F main msvcrt.75AA80EA movzx ebx, byte ptr [ecx] EBX=00000001 main msvcrt.75AA80ED sub esi, ebx ESI=0000003E ; DWORD' main msvcrt.75AA80EF jne msvcrt.75AA8178 main msvcrt.75AA8178 xor ebx, ebx EBX=00000000 ; ebx main msvcrt.75AA817A test esi, esi main msvcrt.75AA817C setg bl EBX=00000001 main msvcrt.75AA817F lea ebx, [ebx+ebx-1] main msvcrt.75AA8183 mov esi, ebx ESI=00000001 main msvcrt.75AA8185 test esi, esi main msvcrt.75AA8187 jne msvcrt.75A98AB1 main msvcrt.75A98AB1 mov eax, esi EAX=00000001 main msvcrt.75A98AB3 jmp msvcrt.75A97A1E main msvcrt.75A97A1E pop ebx EBX=00852AE0, ESP=0041EC6C main msvcrt.return1 pop edi ESP=0041EC70, EDI=034C53B8 main msvcrt.75A97A20 pop esi ESP=0041EC74, ESI=034C53B0 main msvcrt.75A97A21 pop ebp ESP=0041EC78, EBP=0041ECC4 main msvcrt.75A97A22 ret ESP=0041EC7C
ããã§æåã«ç®ãåŒãã®ã¯ãç¹æ®ãªã±ãŒã¹ã®åŠçã§ãããã©ã¡ãŒã¿ã«ãŠã³ãã[0..4]å
ã«ããå Žåãéåžžã«ãŸãã«ãªããŸãããããswitchå¥ã®ã³ã³ãã€ã«ã®çµæãªã®ããããŒã«ã«å€æ°ãå®éã«ã»ããã¢ãããããã®ããæšæž¬ããããšããã§ããŸãããããŒã«ã«å€æ°ã¯ãã§ãã¯ã®åã¹ãããã§æžå°ããŸããããã ãããããã°æ
å ±ã¯ãããããŸã ã¹ã€ããã§ãããšäž»åŒµããŠããŸããæé©åã®èŠ³ç¹ãããããã¯éåžžã«åççãªã¢ã¯ã·ã§ã³ã§ããã«ãŒãã®åæåã¯å®è¡ãããŸãããããã«ç§ã®ç®ãåŒãã2çªç®ã®ããšã¯ãïŒã¹ã¿ãã¯ãä»ããŠïŒçªå·0x20ãedxã¬ãžã¹ã¿ã«å
¥åããéåžžã«çããæ¹æ³ã§ãããããã¯ãããçš®ã®ã³ã³ãã€ã«ã¢ãŒãã£ãã¡ã¯ããšéåžžã«ãã䌌ãŠãããé¢æ°ãã¢ã»ã³ãã©ãŒã§èšè¿°ãããŠããªãããšãæ確ã«ç€ºããŠããŸãã人ã¯ãããæžããªãã§ãããããªããªãããã¯ç¡æå³ã§ããã¹ã¿ãã¯ã¯ã¡ã¢ãªå
ã«ãããã¹ã¿ãã¯ãžã®ã¢ã¯ã»ã¹ã¯åžžã«ã¬ãžã¹ã¿ãããé
ããªããŸãããããã€ã³ã©ã€ã³ã¢ãŒãã£ãã¡ã¯ãã§ããããšãææ¡ããããšæããŸãã0x75AA8178, esi ebx , . , , , , . , , . , DWORD' , .
;Address Hex dump Command Comments 75AA80E7 > 0FB630 movzx esi, byte ptr [eax] 75AA80EA . 0FB619 movzx ebx, byte ptr [ecx] 75AA80ED . 2BF3 sub esi, ebx ; DWORD' 75AA80EF .- 0F85 83000000 jne msvcrt.75AA8178 ; ebx 75AA80F5 > 0FB670 01 movzx esi, byte ptr [eax+1] 75AA80F9 . 0FB659 01 movzx ebx, byte ptr [ecx+1] 75AA80FD . 2BF3 sub esi, ebx 75AA80FF .- 0F84 1EF9FEFF je msvcrt.75A97A23 ; 75A97A23 > 0FB670 02 movzx esi, byte ptr [eax+2] 75A97A27 . 0FB659 02 movzx ebx, byte ptr [ecx+2] 75A97A2B . 2BF3 sub esi, ebx 75A97A2D .- 74 15 je short msvcrt.75A97A44 ; 75A97A44 > 0FB670 03 movzx esi, byte ptr [eax+3] 75A97A48 . 0FB659 03 movzx ebx, byte ptr [ecx+3] 75A97A4C . 2BF3 sub esi, ebx 75A97A4E .- 0F84 5F190000 je msvcrt.75A993B3 ; - 75A97A54 . 33DB xor ebx, ebx ; ebx 75A97A56 . 85F6 test esi, esi 75A97A58 . 0F9FC3 setg bl 75A97A5B . 8D5C1B FF lea ebx, [ebx+ebx-1] 75A97A5F . 8BF3 mov esi, ebx 75A97A61 .- E9 4D190000 jmp msvcrt.75A993B3 ; 75A993B1 . |33F6 xor esi, esi 75A993B3 > |85F6 test esi, esi 75A993B5 .-|0F85 F6F6FFFF jne msvcrt.75A98AB1
ã³ãŒãã®è€è£œã¯è¯ããããŸããããæãããããšã§ã¯ãããŸããããç¹ã«ãã€ãæ°ãçµæã«åœ±é¿ããªããããããã«ãã€ããæ¯èŒããããã®é£ç¶ãããã€ãæ¯èŒã¯æè¯ã®æ¹æ³ã§ã¯ãããŸããããããã£ãŠããããããœãŒã¹ã³ãŒããããã«å¥åŠã§ããããã«ããã®ã³ãŒããå€å°å¥åŠã§ããããšã¯ãã§ã«æããã§ããæåã«2çªç®ã®ãã¬ãŒã¹ã®ãã°ãèŠãŠãã ããïŒã«ãŒãã®1åã®ç¹°ãè¿ãã§8åã®ããã«ã¯ãŒããæ¯èŒãããŸãããããã¯è¯ãããšã§ãïŒã«ãŒããå±éãããããšã¯æããã§ããç§ã¯ããããªãè¡ãããã®ãã«ã€ããŠã®ä»®å®ã¯ãããŸãããããããã©ã®ããã«èµ·ãããã«ã€ããŠã®ä»®å®ããããŸãïŒãŸããã¢ã»ã³ãã©ãŒã³ãŒãã圢æããããã€ãã®ãã¯ãã®çµæã«éåžžã«äŒŒãŠããŸãããããŠã Microsoft Cã³ã³ãã€ã©ã¯ã以åèããŠããã»ã©è¯ããªããšããããšã§ãã2çªç®ã®ãã¬ãŒã¹ïŒã«ãŒãã®ã¿ïŒ ;-------------------------------- main msvcrt.75A979B0 cmp edi, edx main msvcrt.75A979B2 jae msvcrt.75A993A7 main msvcrt.75A993A7 mov esi, [eax] ESI=00000000 main msvcrt.75A993A9 cmp esi, [ecx] main msvcrt.75A993AB jne msvcrt.75AA80E7 main msvcrt.75A993B1 xor esi, esi main msvcrt.75A993B3 test esi, esi main msvcrt.75A993B5 jne msvcrt.75A98AB1 main msvcrt.75A993BB mov esi, [eax+4] main msvcrt.75A993BE cmp esi, [ecx+4] main msvcrt.75A993C1 jne msvcrt.75AA811F main msvcrt.75A993C7 xor esi, esi main msvcrt.75A993C9 test esi, esi main msvcrt.75A?993CB jne msvcrt.75A98AB1 main msvcrt.75A993D1 mov esi, [eax+8] main msvcrt.75A993D4 cmp esi, [ecx+8] main msvcrt.75A993D7 jne msvcrt.75A97A9A main msvcrt.75A993DD xor esi, esi main msvcrt.75A993DF test esi, esi main msvcrt.75A993E1 jne msvcrt.75A98AB1 main msvcrt.75A993E7 mov esi, [eax+0C] main msvcrt.75A993EA cmp esi, [ecx+0C] main msvcrt.75A993ED jne msvcrt.75A97B1F main msvcrt.75A993F3 xor esi, esi main msvcrt.75A993F5 test esi, esi main msvcrt.75A993F7 jne msvcrt.75A98AB1 main msvcrt.75A993FD mov esi, [eax+10] main msvcrt.75A99400 cmp esi, [ecx+10] main msvcrt.75A99403 jne msvcrt.75A97BA4 main msvcrt.75A99409 xor esi, esi main msvcrt.75A9940B test esi, esi main msvcrt.75A9940D jne msvcrt.75A98AB1 main msvcrt.75A99413 mov esi, [eax+14] main msvcrt.75A99416 cmp esi, [ecx+14] main msvcrt.75A99419 jne msvcrt.75A97C29 main msvcrt.75A9941F xor esi, esi main msvcrt.75A99421 test esi, esi main msvcrt.75A99423 jne msvcrt.75A98AB1 main msvcrt.75A99429 mov esi, [eax+18] main msvcrt.75A9942C cmp esi, [ecx+18] main msvcrt.75A9942F jne msvcrt.75AA1172 main msvcrt.75A99435 xor esi, esi main msvcrt.75A99437 test esi, esi main msvcrt.75A99439 jne msvcrt.75A98AB1 main msvcrt.75A9943F mov esi, [eax+1C] main msvcrt.75A99442 cmp esi, [ecx+1C] main msvcrt.75A99445 jne msvcrt.75A97CFC main msvcrt.75A9944B xor esi, esi main msvcrt.75A9944D test esi, esi main msvcrt.75A9944F jne msvcrt.75A98AB1 main msvcrt.75A99455 add eax, edx EAX=031353B8 main msvcrt.75A99457 add ecx, edx ECX=031353B8 main msvcrt.75A99459 sub edi, edx EDI=0007FFE0 main msvcrt.75A9945B jmp msvcrt.75A979B0
倧éã®ãã¹ãããŒã¿ã§ããã®ã³ãŒãã¯ãå®å
šã§ãªãã³ãŒãã䜿çšããå Žåããã10ïŒ
ã»ã©æªãçµæã瀺ããããšã¯æ³šç®ã«å€ããŸããããŒã¿é
åãæ¯èŒãããšãã®ã»ãšãã©ã®æéã¯ãã¡ã¢ãªããã®èªã¿åãæäœãå¿
èŠãšããããšã¯æããã§ããããã¯ãããã»ããµãã£ãã·ã¥ãç¹ã«ã¬ãžã¹ã¿ãããã¯ããã«é
ãã§ããããããããã»ããµã¬ãžã¹ã¿ã䜿çšããæäœã«ãã£ãŠã®ã¿äžãããããã®ãããªé倧ãªéãã¯ãã³ã³ãã€ã©ã®æé©åãéåžžã«éèŠã§ããããšã瀺åããŠããŸããããšãã°ãã¯ããã¯é床ãé
ãããã»ããµãªã©ããã匱ãããã»ããµã§ãã¹ããè¡ããšãã¯ããã«å€§ããªéããçããããšãææ¡ããããšæããŸããçµè«
- å°ããïŒ7ãã€ã以äžïŒé
åããã°ããæ¯èŒããå¿
èŠãããå Žåã¯ãæãæçœãªæ¹æ³ïŒã«ãŒãå
ã®ãã€ãæ¯èŒïŒã䜿çšããŸãã倧ããé
åã¯å®å
šã§ã¯ãªããä»ã®ãã¹ãŠã¯å·§åŠã§ãã
- .Net CLR . , JIT- , , CLR «» . . JIT- , . â C++- Intel, , (AMD Intel) .
- C-RunTime , , C- â MS VC. « » (http://rsdn.ru/article/optimization/optimization.xml): « , , ».
- Intel® 64 and IA-32 Architectures Software Developer Manuals .CHAPTER 2. Intel ® 64 Architecture
- AMD64 Architecture Programmer's Manual Volume 1 : Application Programming CHAPTER 1 Long Mode
- Intel® 64 and IA-32 Architectures Optimization Reference Manual . CHAPTER 3. Alignment
- Windows Internals, Sixth Edition, Part 1, CHAPTER 5 Processes, Threads, and Jobs
- Windows Internals, Sixth Edition, Part 2, CHAPTER 10. Memory Management
- Intel® 64 and IA-32 Architectures Software Developer Manuals. CHAPTER 17. TIME-STAMP COUNTER
- MSDN Magazine 2005, May: Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects
- Joe Duffy, Professional .NET Framework 2.0 (Programmer to Programmer). Chapter 3: Inside the CLR, Just-In-Time (JIT) Compilation
21.03.2014 4:37
ååãã³ã¡ã³ãã«ééã£ããœãŒã¹ãæçš¿ããŸãããäºå®ãç§ã¯ç¥ããªãã£ãããŸãã¯éšåçã«æžããå®éšã®éçšã§ããœãŒã¹ã³ãŒãã¯èšäºããçµæãåŸãã®ã«é©ããŠããªããšããããšã§ããäŸïŒ
- ã¡ãœãããžã®ããã€ãã®åŒã³åºãã¯ã³ã¡ã³ãåãããŸãã
DoMeasurements()
ã result.SequenceEqualTime = result.IStructuralEquatableTime = result.PInvokeTime;
- ãã®ã¡ãœãã
PrepareTestData(int p_ArraySize)
ã¯ãæåã®ãã€ããšã¯ç°ãªãé
åãçæããŸããã - å®æ°ã¯ãé
åã®éå§ãµã€ãºã512 * 1024ã§ãé
åã64ã®ã¿ã«ãªãããã«èšå®ãããŸããã
- ãã®ã¡ãœããã¯
CompareArraysWithPInvokeMethod()
ãç°ãªãé
åãæåã«æ¯èŒãããããã«å€æŽãããŠããŸããçè«çã«ã¯ãããã¯æçµããŒã¿ã«ããŸã圱é¿ããªãã¯ãã§ãã
, , , .
,
Saladin GitHub , , .
25.03.2014 6:37
RtlCompareMemory()
.
, ,
SuppressUnmanagedCodeSecurity memcmp()
RtlCompareMemory()
, ,
user-mode kernel-mode, CRT.
ã¡ã¢ãªã®äž¡æ¹ã®ãããã¯ãåžžé§ããŠããå ŽåãRtlCompareMemoryã®åŒã³åºãå
ã¯ä»»æã®IRQLã§å®è¡ã§ããŸãã
ç«ã®äžã§ã®çµæ Unsafe MemCMP RtlCompareMemory 1 279 1 : 001,7 1 : 003,2 1 : 008,8 1 : 001,0 1 278 1 : 001,8 1 : 003,2 1 : 008,9 1 : 001,0 2 325 1 : 001,3 1 : 002,9 1 : 006,1 1 : 001,0 4 374 1 : 001,1 1 : 002,6 1 : 009,0 1 : 001,0 7 422 1 : 001,0 1 : 002,5 1 : 007,0 1 : 001,1 12 426 1 : 001,0 1 : 002,5 1 : 006,9 1 : 001,7 19 490 1 : 001,0 1 : 002,2 1 : 006,0 1 : 001,9 32 560 1 : 001,0 1 : 002,0 1 : 005,3 1 : 002,7 54 622 1 : 001,0 1 : 002,0 1 : 005,4 1 : 003,8 89 802 1 : 001,0 1 : 001,7 1 : 004,3 1 : 004,7 147 1092 1 : 001,0 1 : 001,5 1 : 003,7 1 : 004,0 242 1571 1 : 001,0 1 : 001,4 1 : 003,0 1 : 004,2 398 2328 1 : 001,0 1 : 001,4 1 : 002,7 1 : 004,5 657 3664 1 : 001,0 1 : 001,2 1 : 002,2 1 : 004,6 1082 5519 1 : 001,0 1 : 001,2 1 : 002,1 1 : 005,0 1782 8554 1 : 001,0 1 : 001,2 1 : 002,1 1 : 005,3 2936 13520 1 : 001,0 1 : 001,2 1 : 002,0 1 : 005,5 4837 21771 1 : 001,0 1 : 001,2 1 : 002,0 1 : 005,6 7967 35464 1 : 001,0 1 : 001,2 1 : 001,9 1 : 005,7 13124 58073 1 : 001,0 1 : 001,2 1 : 001,9 1 : 005,7 21618 96457 1 : 001,0 1 : 001,2 1 : 001,9 1 : 005,7 35610 167952 1 : 001,0 1 : 001,1 1 : 001,8 1 : 005,4 58656 285282 1 : 001,0 1 : 001,1 1 : 001,8 1 : 005,3 96617 534712 1 : 001,0 1 : 001,1 1 : 001,6 1 : 004,7 159146 924569 1 : 001,0 1 : 001,1 1 : 001,6 1 : 004,5 262143 1520968 1 : 001,0 1 : 001,1 1 : 001,6 1 : 004,5
ãããã¬ãŒãŠã£ã³ããŠã®ã¹ã¯ãªãŒã³ã·ã§ããã§ã¯ãã©ã€ãã©ãªããŒãžã§ã³ æ©èœã¯é©ãã»ã©å°ããããšãå€æããŸããããã¹ãŠãããã«ãããŸãããã®é¢æ°ã¯ãç¹°ãè¿ããã¬ãã£ãã¯ã¹ïŒcmps*
ïŒã䜿çšããŠæååæ¯èŒæŒç®ãç©æ¥µçã«äœ¿çšããŸããã¡ã¢ãªã®æ¯èŒã¯çŽæ¥ã®é åºã§è¡ãããŸããããã¯ãã³ãã³ãã«ãã£ãŠãªã»ãããããDFãã©ã°ã«ãã£ãŠæ±ºå®ããcld
ãŸãããã®é¢æ°ã®ãµã€ãºãšåçŽãã¯ããããã¢ã»ã³ããªèšèªã§æžãããŠããããšã瀺åããŠããŸãããããã«ã€ããŠã¯ããããŸãããæååæ¯èŒæäœã®ã¢ã«ãŽãªãºã ã¯éåžžã«ç°¡åã§ããããšãã°ã次ã®ã³ãã³ãã§æå®ãããDWORDãé æ¹åã«æ¯èŒããŸãã repe cmpsd ; ecx DWORD';
Javaã§ã¯ã次ã®ããã«è¡šãããšãã§ããŸãã while ( ( 0 != ecx ) & ( 0 == Compare( (DWORD) RAM[esi], (DWORD) RAM[edi] ) ) ) { --ecx; edi += 4; esi += 4; }
åèªãšãã€ãã®é
眮ãæ³åã§ããã»ãŒåãæ¹æ³ãã«ããã®äžã§ã®ã³ã¡ã³ããšæ²æš push esi ; push edi cld ; DF <-- 0 mov esi, [esp+0C] ; esi <-- Source1 mov edi, [esp+10] ; edi <-- Source2 mov ecx, [esp+14] ; ecx <-- SIZE_T shr ecx, 2 ; ecx <-- (ecx >> 2) ( 4) jz short smaller_4 ; repe cmpsd ; ecx DWORD'; jne short not_zero ; if ( !ZF ) goto not_zero; smaller_4: mov ecx, [esp+14] ; ecx <-- SIZE_T and ecx, 00000003 ; ecx &= 3 jz short return_SIZE_T ; if ( ZF ) goto return_SIZE_T; repe cmpsb ; jne short found_difference return_SIZE_T: mov eax, [esp+14] ; eax <-- SIZE_T pop edi ; pop esi ret 0C ; return eax not_zero: sub esi, 4 ; esi -= 4 sub edi, 4 ; edi -= 4 mov ecx, 4 ; ecx -= 4 repe cmpsb ; found_difference: dec esi ; --esi sub esi, [esp+0C] ; esi <-- (esi - Source1) mov eax, esi ; eax <-- esi pop edi ; pop esi ret 0C ; return eax