Znalazłem to dziwne zachowanie w .NET i nawet po zaglądaniu w CLR via C# znowu jestem wciąż zdezorientowany. Załóżmy, że mamy interfejs z jednej metody i klasy, która imlements go:C#: Dlaczego wywoływanie zaimplementowanej metody interfejsu jest szybsze dla zmiennej klasy niż dla zmiennej interfejsu?
interface IFoo
{
void Do();
}
class TheFoo : IFoo
{
public void Do()
{
//do nothing
}
}
Następnie chcemy po prostu instancję tej klasy i wywołać tej metody Do() wiele razy na dwa sposoby: za pomocą zmiennej klasy betonu i za pomocą zmiennej interfejs:
TheFoo foo1 = new TheFoo();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (long i = 0; i < 1000000000; i++)
foo1.Do();
stopwatch.Stop();
Console.Out.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds);
IFoo foo2 = foo1;
stopwatch = new Stopwatch();
stopwatch.Start();
for (long i = 0; i < 1000000000; i++)
foo2.Do();
stopwatch.Stop();
Console.Out.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds);
Zaskakująco (przynajmniej dla mnie), że minęły czasy są o 10% innego:
Elapsed time: 6005
Elapsed time: 6667
różnica nie jest tak dużo, więc nie będzie W większości przypadków bardzo się o to martwimy. Jednak nie mogę pojąć, dlaczego tak się dzieje, nawet po przejrzeniu kodu IL, więc byłbym wdzięczny, gdyby ktoś wskazał mi coś oczywistego, czego mi brakuje.
Przeprowadziłem twoje testy i faktycznie otrzymałem zupełnie inny wynik.Upływający czas: 12125 Upłynął czas: 11682. Oczywiście korzystam z wolniejszej maszyny. Pomiar wydajności w ten sposób jest trudny, ponieważ istnieją czynniki, które mogą być w grze, które nie są jasne. –
@Craig Prawdopodobnie jakiś proces przeszkadzał. Mam bardzo konsekwentne wyniki w tym mini-benchmarku 10 razy. –
@Ivan Uruchomiłem to wiele razy, zanim opublikowałem i uzyskałem spójne wyniki. Ja też po prostu poszedłem i odtworzyłem to, wprowadzając go w pętlę i uruchamiając go 10 razy z powrotem do tyłu. Mam bardzo mało innych maszyn i ciągle widzę, że pierwszy przypadek jest wolniejszy. Jest to teraz znacząca różnica, prawie 2: 1. Dodałem także inną klasę, która jawnie implementuje interfejs i przeprowadził test na tym. To działało mniej więcej tak samo, jak w drugim przypadku. Z jakiej wersji platformy korzystasz? Może to wyjaśnia różnice. –