C# 'является' производительностью оператора

Итак, я получил это, просто используя несколько интерфейсов, сопоставляя каждый интерфейс виртуальной машины с пространством имен. И затем я смог использовать исходный порт 63999 одновременно в двух одновременных сеансах

ip netns eng51 ifconfig eth1.51 Link encap: Ethernet HWaddr 52: 54: 00: bd: 68: c3 inet addr: 51.51.1.10 Bcast: 51.51.1.255 Маска: 255.255.255.0

ip netns exec eng52 ifconfig eth2.52 Код соединения: Ethernet HWaddr 52: 54: 00: bd: 68: c3 inet addr: 51.51.2.10 Bcast : 51.51.2.255 Маска: 255.255.255.0

ip netns exec eng522 ifconfig eth3.522 Link encap: Ethernet HWaddr 52: 54: 00: bd: 68: c3 inet addr: 51.51.2.10 Bcast: 51.51.2.255 Маска: 255.255.255.0

ip netns exec eng511 ifconfig eth4.511 Код соединения: Ethernet HWaddr 52: 54: 00: bd: 68: c3 inet addr: 51.51.1.10 Bcast: 51.51.1.255 Маска: 255.255. 255,0

90
задан Josh Lee 29 November 2009 в 23:39
поделиться

4 ответа

Используя is может повредить производительность, если, после того как Вы проверяете тип, Вы бросаете к тому типу. is на самом деле бросает объект к типу, который Вы проверяете, таким образом, любой последующий кастинг избыточен.

Если Вы собираетесь бросить так или иначе, вот лучший подход:

ISpecialType t = obj as ISpecialType;

if (t != null)
{
    // use t here
}
109
ответ дан Andrew Hare 24 November 2019 в 06:57
поделиться

Я с Ian, Вы, вероятно, не хотите делать это.

Однако именно так Вы знаете, существует очень мало различия между двумя, более чем 10 000 000 повторений

  • Перечислимая проверка входит в 700 миллисекундах (приблизительно)
  • Проверка, входит в 1 000 миллисекунд (приблизительно)

Я лично не решил бы эту проблему этот путь, но если бы я был вынужден выбрать один метод, то это был бы встроенный, проверка, различие в производительности не достойно рассмотрения кодирование наверху.

Моя база и производные классы

class MyBaseClass
{
    public enum ClassTypeEnum { A, B }
    public ClassTypeEnum ClassType { get; protected set; }
}

class MyClassA : MyBaseClass
{
    public MyClassA()
    {
        ClassType = MyBaseClass.ClassTypeEnum.A;
    }
}
class MyClassB : MyBaseClass
{
    public MyClassB()
    {
        ClassType = MyBaseClass.ClassTypeEnum.B;
    }
}

JubJub: Согласно просьбе больше информации о тестах.

Я запустил оба теста из консольного приложения (отладочная сборка), каждый тест похож на следующее

static void IsTest()
{
    DateTime start = DateTime.Now;
    for (int i = 0; i < 10000000; i++)
    {
        MyBaseClass a;
        if (i % 2 == 0)
            a = new MyClassA();
        else
            a = new MyClassB();
        bool b = a is MyClassB;
    }
    DateTime end = DateTime.Now;
    Console.WriteLine("Is test {0} miliseconds", (end - start).TotalMilliseconds);
}

Работая в выпуске, я получаю различие 60 - 70 мс, как Ian.

Дальнейшее обновление - 25-го октября 2012
После на расстоянии в несколько лет я заметил что-то об этом, компилятор может принять решение опустить bool b = a is MyClassB в выпуске, потому что b не используется нигде.

Этот код...

public static void IsTest()
{
    long total = 0;
    var a = new MyClassA();
    var b = new MyClassB();
    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < 10000000; i++)
    {
        MyBaseClass baseRef;
        if (i % 2 == 0)
            baseRef = a;//new MyClassA();
        else
            baseRef = b;// new MyClassB();
        //bool bo = baseRef is MyClassB;
        bool bo = baseRef.ClassType == MyBaseClass.ClassTypeEnum.B;
        if (bo) total += 1;
    }
    sw.Stop();
    Console.WriteLine("Is test {0} miliseconds {1}", sw.ElapsedMilliseconds, total);
}

... последовательно шоу is регистрируйте прибытие приблизительно в 57 миллисекунд и перечислимое сравнение, входящее в 29 миллисекундах.

NB я все еще предпочел бы is проверьте, разница является слишком небольшой для заботы о

69
ответ дан Community 24 November 2019 в 06:57
поделиться

Andrew корректен. На самом деле с анализом кода об этом сообщает Visual Studio как ненужный бросок.

Одна идея (не зная то, что Вы делаете, является определенным выстрелом в темноте), но мне всегда рекомендовали постараться не проверить как это и вместо этого иметь другой класс. Так вместо того, чтобы делать некоторые проверки и иметь различные действия в зависимости от типа, заставьте класс знать, как обработать себя...

например, Obj может быть ISpecialType или IType;

у них обоих есть DoStuff () определенный метод. Для IType это может просто возвратить или сделать пользовательский материал, тогда как ISpecialType может сделать другой материал.

Это затем полностью удаляет любой кастинг, делает инструмент для очистки кода и легче поддержать, и класс знает, как сделать свои собственные задачи.

16
ответ дан Ian 24 November 2019 в 06:57
поделиться

Хорошо, я поговорил об этом с кем-то и решил проверить это еще раз. Насколько я могу судить, производительность как и равно очень хороша по сравнению с тестированием вашего собственного члена или функции для хранения информации о типе.

Я использовал ] Секундомер , который, как я только что узнал, может быть не самым надежным подходом, поэтому я также попробовал UtcNow . Позже я также попробовал подход с использованием времени процессора, который кажется похожим на UtcNow , включая непредсказуемое время создания. Я также попытался сделать базовый класс неабстрактным без виртуальных машин, но, похоже, это не имело значительного эффекта.

Я запускал это на Quad Q6600 с 16 ГБ ОЗУ. Даже с итерациями 50 мил, числа все еще колеблются в районе +/- 50 или около того миллисекунд, так что я бы не стал Как: 561 мс
Is: 597 мс
Базовое свойство: 539 мс
Базовое поле: 555 мс
Базовое поле RO: 552 мс
Виртуальный тест GetEnumType (): 556 мс
Виртуальный тест IsB (): 588 мс
Время создания: 10416 мс

UtcNow:
Как: 499 мс
Есть: 532 мс
Базовое свойство: 479 мс
Базовое поле: 502 мс
Базовое поле RO: 491 мс
Виртуальный GetEnumType (): 502 мс
Virtual bool IsB (): 522 мс
Время создания: 285 мс (Это число кажется ненадежным с UtcNow. Я также получаю 109 мс и 806 мс.)

Режим выпуска x86:
Секундомер:
Как: 391 мс
Is: 423 мс
Базовое свойство: 369 мс
Базовое поле: 321 мс
Базовое поле RO: 339 мс
Виртуальный тест GetEnumType (): 361 мс
Виртуальный тест IsB (): 365 мс
Время создания: 14106 мс

UtcNow:
Как: 348 мс
Is: 375 мс
Базовое свойство: 329 мс
Базовое поле: 286 мс
Базовое поле RO: 309 мс
Виртуальный GetEnumType (): 321 мс
Virtual bool IsB (): 332 мс
Время создания: 544 мс (это число кажется ненадежным с UtcNow.)

Вот большая часть кода:

    static readonly int iterations = 50000000;
    void IsTest()
    {
        Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)1;
        MyBaseClass[] bases = new MyBaseClass[iterations];
        bool[] results1 = new bool[iterations];

        Stopwatch createTime = new Stopwatch();
        createTime.Start();
        DateTime createStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            if (i % 2 == 0) bases[i] = new MyClassA();
            else bases[i] = new MyClassB();
        }
        DateTime createStop = DateTime.UtcNow;
        createTime.Stop();


        Stopwatch isTimer = new Stopwatch();
        isTimer.Start();
        DateTime isStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] =  bases[i] is MyClassB;
        }
        DateTime isStop = DateTime.UtcNow; 
        isTimer.Stop();
        CheckResults(ref  results1);

        Stopwatch asTimer = new Stopwatch();
        asTimer.Start();
        DateTime asStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i] as MyClassB != null;
        }
        DateTime asStop = DateTime.UtcNow; 
        asTimer.Stop();
        CheckResults(ref  results1);

        Stopwatch baseMemberTime = new Stopwatch();
        baseMemberTime.Start();
        DateTime baseStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].ClassType == MyBaseClass.ClassTypeEnum.B;
        }
        DateTime baseStop = DateTime.UtcNow;
        baseMemberTime.Stop();
        CheckResults(ref  results1);

        Stopwatch baseFieldTime = new Stopwatch();
        baseFieldTime.Start();
        DateTime baseFieldStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].ClassTypeField == MyBaseClass.ClassTypeEnum.B;
        }
        DateTime baseFieldStop = DateTime.UtcNow;
        baseFieldTime.Stop();
        CheckResults(ref  results1);


        Stopwatch baseROFieldTime = new Stopwatch();
        baseROFieldTime.Start();
        DateTime baseROFieldStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].ClassTypeField == MyBaseClass.ClassTypeEnum.B;
        }
        DateTime baseROFieldStop = DateTime.UtcNow;
        baseROFieldTime.Stop();
        CheckResults(ref  results1);

        Stopwatch virtMethTime = new Stopwatch();
        virtMethTime.Start();
        DateTime virtStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].GetClassType() == MyBaseClass.ClassTypeEnum.B;
        }
        DateTime virtStop = DateTime.UtcNow;
        virtMethTime.Stop();
        CheckResults(ref  results1);

        Stopwatch virtMethBoolTime = new Stopwatch();
        virtMethBoolTime.Start();
        DateTime virtBoolStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].IsB();
        }
        DateTime virtBoolStop = DateTime.UtcNow;
        virtMethBoolTime.Stop();
        CheckResults(ref  results1);


        asdf.Text +=
        "Stopwatch: " + Environment.NewLine 
          +   "As:  " + asTimer.ElapsedMilliseconds + "ms" + Environment.NewLine
           +"Is:  " + isTimer.ElapsedMilliseconds + "ms" + Environment.NewLine
           + "Base property:  " + baseMemberTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base field:  " + baseFieldTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base RO field:  " + baseROFieldTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Virtual GetEnumType() test:  " + virtMethTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Virtual IsB() test:  " + virtMethBoolTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Create Time :  " + createTime.ElapsedMilliseconds + "ms" + Environment.NewLine + Environment.NewLine+"UtcNow: " + Environment.NewLine + "As:  " + (asStop - asStart).Milliseconds + "ms" + Environment.NewLine + "Is:  " + (isStop - isStart).Milliseconds + "ms" + Environment.NewLine + "Base property:  " + (baseStop - baseStart).Milliseconds + "ms" + Environment.NewLine + "Base field:  " + (baseFieldStop - baseFieldStart).Milliseconds + "ms" + Environment.NewLine + "Base RO field:  " + (baseROFieldStop - baseROFieldStart).Milliseconds + "ms" + Environment.NewLine + "Virtual GetEnumType():  " + (virtStop - virtStart).Milliseconds + "ms" + Environment.NewLine + "Virtual bool IsB():  " + (virtBoolStop - virtBoolStart).Milliseconds + "ms" + Environment.NewLine + "Create Time :  " + (createStop-createStart).Milliseconds + "ms" + Environment.NewLine;
    }
}

abstract class MyBaseClass
{
    public enum ClassTypeEnum { A, B }
    public ClassTypeEnum ClassType { get; protected set; }
    public ClassTypeEnum ClassTypeField;
    public readonly ClassTypeEnum ClassTypeReadonlyField;
    public abstract ClassTypeEnum GetClassType();
    public abstract bool IsB();
    protected MyBaseClass(ClassTypeEnum kind)
    {
        ClassTypeReadonlyField = kind;
    }
}

class MyClassA : MyBaseClass
{
    public override bool IsB() { return false; }
    public override ClassTypeEnum GetClassType() { return ClassTypeEnum.A; }
    public MyClassA() : base(MyBaseClass.ClassTypeEnum.A)
    {
        ClassType = MyBaseClass.ClassTypeEnum.A;
        ClassTypeField = MyBaseClass.ClassTypeEnum.A;            
    }
}
class MyClassB : MyBaseClass
{
    public override bool IsB() { return true; }
    public override ClassTypeEnum GetClassType() { return ClassTypeEnum.B; }
    public MyClassB() : base(MyBaseClass.ClassTypeEnum.B)
    {
        ClassType = MyBaseClass.ClassTypeEnum.B;
        ClassTypeField = MyBaseClass.ClassTypeEnum.B;
    }
}
22
ответ дан 24 November 2019 в 06:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: