Производительность TypeCasting

существует ли какая-либо заметная разница в производительности между

((TypeA) obj).method1(); ((TypeA) obj).method2(); ((TypeA) obj).method3(); 

а также

 var A = (TypeA) obj; A.method1(); A.method2(); A.method3(); 

когда используется много раз?

Я часто вижу что-то вроде

 if (((TextBox)sender).Text.Contains('.') || ((TextBox)sender).Text.Contains(',')) 

и задаться вопросом, является ли это пустой тратой производительности.

Это может быть измеримым, если это делается миллиарды раз с очень небольшой работой. Я не знаю, будет ли CLR эффективно кэшировать тот факт, что отбор работал, поэтому ему не нужно делать это снова – если это не так сейчас, оно может сделать это в более поздней версии. Он может сделать это в 64-битной JIT, но не в 32-битной версии, или наоборот – вы получите эту идею. Я сомневаюсь, что это существенно повлияет на нормальный код.

Лично мне больше нравится читаемость второй формы, и это гораздо важнее.

@dkson: Я тестировал оба метода. Вот что я нашел на своем компьютере:

Они примерно одинаковы по производительности. Фактически, второй метод, который я обнаружил, немного медленнее. Причина (я считаю) – это стоимость дополнительной переменной и начального броска. Конечно, если вы используете достаточное количество бросков, вы можете вернуть эту стоимость. Похоже, вы теряете даже с точки зрения производительности только после сохранения 20-30 бросков.

Вот результаты двух последних тестовых прогонов:

 TestMuliCast\_3x: 00:00:00.5970000 TestSingleCast\_3x: 00:00:00.6020000 TestMuliCast\_30x: 00:00:06.0930000 TestSingleCast\_30x: 00:00:06.0480000 TestMuliCast\_3x: 00:00:00.6120000 TestSingleCast\_3x: 00:00:00.6250000 TestMuliCast\_30x: 00:00:06.5490000 TestSingleCast\_30x: 00:00:06.4440000 

Я также проверил разницу между castclass и isinst . Основываясь на том, что я читал:

http://m3mia.blogspot.com/2007/11/comparing-isinst-to-castclass.html
http://www.codeproject.com/KB/cs/csharpcasts.aspx
http://discuss.joelonsoftware.com/default.asp?dotnet.12.635066.13

Я думал, что isinst будет быстрее, чем castclass, даже если исключений не было. Однако, после создания моих собственных тестов, я обнаружил, что он немного медленнее, чем castclass. Очень интересно. Вот мои результаты:

 TestEmptyLoop: 00:00:00.0870000 TestDCast\_castclass: 00:00:00.2640000 TestDCast\_isinst: 00:00:00.3780000 TestEmptyLoop: 00:00:00.0870000 TestDCast\_castclass: 00:00:00.2600000 TestDCast\_isinst: 00:00:00.3750000 

Итак, мистер Скит, я исправляюсь.

Окружающая среда:

Виндоус виста
Максимальная частота ядра 3,2 ГГц
.NET Framework v2.0.50727

Вот полный исходный код для тестов, которые я создал и запускал: (здесь используется платформа для работы с Microbenchmarking от Jon Skeets)

 using System; using System.Collections; public class CastingBenchmark { static Int64 Iterations=100000000; static Int64 TestWork = 0; public static void Init(string[] args) { if (args.Length>0) Iterations = Int64.Parse(args[0]); } public static void Reset() { TestWork = 0; } internal class BaseType { public void TestBaseMethod() { TestWork++; } } internal class DerivedType : BaseType { public void TestDerivedMethod() { TestWork++; } public void TestDerivedMethod2() { TestWork++; } public void TestDerivedMethod3() { TestWork++; } } [Benchmark] public static void TestMuliCast_3x() { BaseType TestBaseType = new DerivedType(); for (int x = 0; x < Iterations; x++) { ((DerivedType)TestBaseType).TestDerivedMethod(); ((DerivedType)TestBaseType).TestDerivedMethod2(); ((DerivedType)TestBaseType).TestDerivedMethod3(); } } [Benchmark] public static void TestSingleCast_3x() { BaseType TestBaseType = new DerivedType(); for (int x = 0; x < Iterations; x++) { DerivedType TestDerivedType = (DerivedType)TestBaseType; TestDerivedType.TestDerivedMethod(); TestDerivedType.TestDerivedMethod2(); TestDerivedType.TestDerivedMethod3(); } } [Benchmark] public static void TestMuliCast_30x() { BaseType TestBaseType = new DerivedType(); for (int x = 0; x < Iterations; x++) { //Simulate 3 x 10 method calls while casting for (int y = 0; y < 10; y++) { ((DerivedType)TestBaseType).TestDerivedMethod(); ((DerivedType)TestBaseType).TestDerivedMethod2(); ((DerivedType)TestBaseType).TestDerivedMethod3(); } } } [Benchmark] public static void TestSingleCast_30x() { BaseType TestBaseType = new DerivedType(); for (int x = 0; x < Iterations; x++) { DerivedType TestDerivedType = (DerivedType)TestBaseType; //Simulate 3 x 10 method calls on already-cast object for (int y = 0; y < 10; y++) { TestDerivedType.TestDerivedMethod(); TestDerivedType.TestDerivedMethod2(); TestDerivedType.TestDerivedMethod3(); } } } [Benchmark] public static void TestEmptyLoop() { for (int x = 0; x < Iterations; x++) { } } [Benchmark] public static void TestDCast_castclass() { BaseType TestDerivedType = new DerivedType(); for (int x = 0; x < Iterations; x++) { ((DerivedType)TestDerivedType).TestDerivedMethod(); } } [Benchmark] public static void TestDCast_isinst() { BaseType TestDerivedType = new DerivedType(); for (int x = 0; x < Iterations; x++) { (TestDerivedType as DerivedType).TestDerivedMethod(); } } } 

И полученный IL для isinst и castclass :

 method public hidebysig static void TestDCast_isinst() cil managed { .custom instance void BenchmarkAttribute::.ctor() .maxstack 2 .locals init ( [0] class CastingBenchmark/BaseType TestDerivedType, [1] int32 x) L_0000: newobj instance void CastingBenchmark/DerivedType::.ctor() L_0005: stloc.0 L_0006: ldc.i4.0 L_0007: stloc.1 L_0008: br.s L_0019 L_000a: ldloc.0 L_000b: isinst CastingBenchmark/DerivedType L_0010: callvirt instance void CastingBenchmark/DerivedType::TestDerivedMethod() L_0015: ldloc.1 L_0016: ldc.i4.1 L_0017: add L_0018: stloc.1 L_0019: ldloc.1 L_001a: conv.i8 L_001b: ldsfld int64 CastingBenchmark::Iterations L_0020: blt.s L_000a L_0022: ret } .method public hidebysig static void TestDCast_castclass() cil managed { .custom instance void BenchmarkAttribute::.ctor() .maxstack 2 .locals init ( [0] class CastingBenchmark/BaseType TestDerivedType, [1] int32 x) L_0000: newobj instance void CastingBenchmark/DerivedType::.ctor() L_0005: stloc.0 L_0006: ldc.i4.0 L_0007: stloc.1 L_0008: br.s L_0019 L_000a: ldloc.0 L_000b: castclass CastingBenchmark/DerivedType L_0010: callvirt instance void CastingBenchmark/DerivedType::TestDerivedMethod() L_0015: ldloc.1 L_0016: ldc.i4.1 L_0017: add L_0018: stloc.1 L_0019: ldloc.1 L_001a: conv.i8 L_001b: ldsfld int64 CastingBenchmark::Iterations L_0020: blt.s L_000a L_0022: ret } 
  • «Неполный тип» в classе, который имеет один и тот же тип самого classа
  • Почему я могу вводить функции псевдонима и использовать их без кастинга?
  • Как получить тип ввода с помощью jquery?
  • .NET: Как вы получаете Тип нулевого объекта?
  • Как написать функцию для общих чисел?
  • Преобразование streamа int в char в java
  • почему byte + = 1 компилировать, но byte = byte + 1 нет?
  • Когда следует использовать std :: size_t?
  • Какова цель вопросительного знака после типа (например: int? MyVariable)?
  • Ограничение типа множественного типа (ИЛИ)
  • Как определить тип MIME загруженного файла в ASP.NET?
  • Давайте будем гением компьютера.