Egy példa arra, hogy azért semmiképpen nem árt, ha 1 C# programozó (is) tisztában van az asm és a C alapjaival(legalább).
Van a következő C# kód:
using System;
using System.Runtime.InteropServices;
namespace ArrTeszt
{
internal class Program
{
[DllImport("ArrTestDll.dll", SetLastError = false)]
public static extern void LengthInt(int[] arr, int index);
[DllImport("ArrTestDll.dll", SetLastError = false)]
public static extern void LengthInt2D(int[,] arr, int row, int col);
static void Main(string[] args)
{
int index = 3, row = 2, col = 1;
int[] arrtest = new int[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
int[,] arrtest2D = new int[,] { { 12, 11, 10 }, { 9, 8, 7 }, { 6, 5, 4 }, { 3, 2, 1 } };
int x = arrtest[index];
int y = arrtest2D[row, col];
Console.WriteLine("arrtest[{0}]: {1}", index, x);
LengthInt(arrtest, index);
Console.WriteLine("arrtest2D[{0}, {1}]: {2}", row, col, y);
LengthInt2D(arrtest2D, row, col);
Console.ReadKey(true);
}
}
}
és vannak a következő függvények 1 .dll-ben:
__declspec(dllexport) void __stdcall LengthInt(int arr[], int index)
{
if (index < (*(arr - 1)))
{
printf("arr[%d]: %d\n", index, arr[index]);
printf("arr.Length: %d\n", *(arr - 1));
}
}
__declspec(dllexport) void __stdcall LengthInt2D(int arr[], int row, int col)
{
if (row < (*(arr - 4)) && col < (*(arr - 3)))
{
printf("arr[%d, %d]: %d\n", row, col, *(arr + (row * (*(arr - 3))) + col));
printf("Sorok szama: %d\nOszlopok szama: %d\n", *(arr - 4), *(arr - 3));
}
}
A C# kód releváns assembly kódja:
index = ebp-40h
row = ebp-44h
col = ebp-48h
&arrtest = ebp-4Ch
&arrtest2D = ebp-50h
x = ebp-54h
y = ebp-58h
int x = arrtest[index];
02A90919 mov eax,dword ptr [ebp-40h]
02A9091C mov edx,dword ptr [ebp-4Ch]
02A9091F cmp eax,dword ptr [edx+4]
02A90922 jb ArrTeszt.Program.Main(System.String[])+0E1h (02A90929h)
02A90924 call 70A5FF80
02A90929 mov eax,dword ptr [edx+eax*4+8]
02A9092D mov dword ptr [ebp-54h],eax
int y = arrtest2D[row, col];
02A90930 push dword ptr [ebp-48h]
02A90933 mov ecx,dword ptr [ebp-50h]
02A90936 mov edx,dword ptr [ebp-44h]
02A90939 call System.Int32[,].Get(Int32, Int32) (02A90140h)
02A9093E mov dword ptr [ebp-6Ch],eax
02A90941 mov eax,dword ptr [ebp-6Ch]
02A90944 mov dword ptr [ebp-58h],eax
A C# program kimenete:
arrtest[3]: 6
arr[3]: 6
arr.Length: 9
arrtest2D[2, 1]: 5
arr[2, 1]: 5
Sorok szama: 4
Oszlopok szama: 3
Az nem nagyon meglepő, hogy a C .dll-nek átadott 1D int tömbnek átadott pointer előtti int tartalmazza a tömb hosszát.
Ami inkább meglepőbb, az a C# mátrix kezelése. A C .dll függvénynek átadott pointer előtti negyedik int a mátrix sorainak a száma, és a pointer előtti harmadik int a mátrix oszlopainak a száma. Viszont a C# mátrix a C-s .dll-nek 1D tömbként adódik át(nem mátrix-ként)!! Tehát a C#-al ellentétben itt memória címzéssel lekérdezhető a mátrix 1 eleme. A C# erre külön metódust használ:
02A90939 call System.Int32[,].[B]Get[/B](Int32, Int32) (02A90140h)
Itt látható, hogy a C#-ban a Get() metódus hívódik meg.
Na ilyen "ínyencségeket" nem tudhat meg 1 olyan C# programozó, akinek fogalma sincs az asm-ról és a C-ről!
Itt látszik, hogy a C# miért lassabb.
http://www.bferi.hu/download.php ; http://bferi.hu/egyeb.php