none
c# вопрос RRS feed

  • Вопрос

  • Подскажите какой код будет лучше по скорости, по компактности..

    public class A
    {
     int i, j;
     
     public int sum(){ return i + j; }
    }


    или


    public class A
    {
     int i, j;
     
     public static int sum(A a){ return a.i + a.j; }
    }

Ответы

  • Одинаково (ну или на грани погрешности, один из вариантов будте "быстрее", в зависимости от параметров компиляции, версии фреймворка, поведения jit).
    • Помечено в качестве ответа Abolmasov Dmitry 4 мая 2012 г. 6:42
    Модератор
  • Проверял работу классов вот такой программой:

    class Program
    {
        public class A
        {
            public int i, j;
    
            public int sum() { return i + j; }
        }
    
        public class B
        {
            public int i, j;
    
            public static int sum(B a) { return a.i + a.j; }
        }
    
        static void Main(string[] args)
        {
            int n = 10000000;
            Random rnd = new Random();
            A[] a = new A[n];
            B[] b = new B[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = new A() { i = rnd.Next(n), j = rnd.Next(n) };
                b[i] = new B() { i = a[i].i, j = a[i].j };
            }
            DateTime start, stop;
            start = DateTime.Now;
            for (int i = 0; i < n; i++)
            {
                int s = a[i].sum();
            }
            stop = DateTime.Now;
            Console.WriteLine("Первый вариант: {0} с.", stop.Subtract(start).TotalSeconds);
            start = DateTime.Now;
            for (int i = 0; i < n; i++)
            {
                int s = B.sum(b[i]);
            }
            stop = DateTime.Now;
            Console.WriteLine("Второй вариант: {0} с.", stop.Subtract(start).TotalSeconds);
            Console.ReadKey();
        }
    }

    Вот результат быстродействия на 10 млн. объектов:

    Вы чувствуете выгоду от 1 сотой секунды на 10 млн. объектов? Тогда выбирайте второй вариант. Он быстрее. Компактнее? Да тоже наверное. Но вот в большом проекте, который вы потом планируете сопровождать и поддерживать, я бы выбрал 1 варинат, т.к. он понятнее.


    Отвечающий

Все ответы

  • Одинаково (ну или на грани погрешности, один из вариантов будте "быстрее", в зависимости от параметров компиляции, версии фреймворка, поведения jit).
    • Помечено в качестве ответа Abolmasov Dmitry 4 мая 2012 г. 6:42
    Модератор
  • Из личного опыта: переназначение переменной идет медленнее, чем объявление новой переменной.

    У меня была программа по числа Фибоначчи. Считала на двух ядрах трое суток.

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

  • А любая «.» замедляет код (когда его много!!!)

  • Ни в первом, ни во втором примере нет локальных переменных.

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

    эквивалентный код типа this.i + this.j, то он вдруг станет медленее? Можете обосновать, почему? :)

    P.S. не холивара ради. классы и ооп в целом - это способы ускорить разработку, а не сократить время выполнения. пример выше всегда можно переписать в виде сложения двух целых чисел, и это будет намного быстрее чем оба варианта с классами. но конкретно в этом случае разница по скорости между вариантами будет порядка порядка 10^-9 cекунд на вызов, что никак не повлияет на скорость работы приложения. если только оно не занимается только сложением чисел в огромных количествах.

    Модератор
  • Допустим "sum()" компилируется в 10 байт машинного кода, понятно что здесь одна команда ассемблера, не в этом дело.
    Тогда если имеется A [] array = new A [2]; то он займет места в 2 раза больше, чем во втором случае
    и будет работать непринципиально быстрее?
  • Проверял работу классов вот такой программой:

    class Program
    {
        public class A
        {
            public int i, j;
    
            public int sum() { return i + j; }
        }
    
        public class B
        {
            public int i, j;
    
            public static int sum(B a) { return a.i + a.j; }
        }
    
        static void Main(string[] args)
        {
            int n = 10000000;
            Random rnd = new Random();
            A[] a = new A[n];
            B[] b = new B[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = new A() { i = rnd.Next(n), j = rnd.Next(n) };
                b[i] = new B() { i = a[i].i, j = a[i].j };
            }
            DateTime start, stop;
            start = DateTime.Now;
            for (int i = 0; i < n; i++)
            {
                int s = a[i].sum();
            }
            stop = DateTime.Now;
            Console.WriteLine("Первый вариант: {0} с.", stop.Subtract(start).TotalSeconds);
            start = DateTime.Now;
            for (int i = 0; i < n; i++)
            {
                int s = B.sum(b[i]);
            }
            stop = DateTime.Now;
            Console.WriteLine("Второй вариант: {0} с.", stop.Subtract(start).TotalSeconds);
            Console.ReadKey();
        }
    }

    Вот результат быстродействия на 10 млн. объектов:

    Вы чувствуете выгоду от 1 сотой секунды на 10 млн. объектов? Тогда выбирайте второй вариант. Он быстрее. Компактнее? Да тоже наверное. Но вот в большом проекте, который вы потом планируете сопровождать и поддерживать, я бы выбрал 1 варинат, т.к. он понятнее.


    Отвечающий
  • new A [2] в обоих случаях займет одинаково места. Метод sum не занимет место внутри объекта.
    Модератор
  • А чем тогда static отличается от dinamic?
  • Спасибо огромное, т.к. это то, в чем надеюсь убедиться. А если сделать 10 млн. потоков?.. 

  • А чем тогда static отличается от dinamic?

    Это ортогональные понятия.

    static - модификатор, означающий, что член класса будет один на все экземпляры. Если класс помечен static, значит все его члены должны быть статическими.

    dynamic - означает, что проверки типов будут производиться во время выполнения, а не во время компиляции. Это чрезвычайно медленно, и чревато ошибками. Никогда не используйте его! Я запретил!

  • А если сделать 10 млн. потоков?.. 

    То вам оборвёт уши тим-лид (ведущий программист). :)
  • Угу, а архитектор еще и с лопатой будет за вами бегать :)

    Чтобы на переключения не тратилось времени больше чем на работу, желательно количество потоков делать не большим, чем количество ядер/процессоров у вас в системе, т.к. в противном случае, среднее время на решение задачи возрастает.


    Отвечающий
  • В dynamic случае в каждом объекте класса будет присутствовать "10 байт м.кода" в отличие от static,
    где будет в каждом объекте ссылка на 10 байт кода?
  • В объекте класса не могут присутствовать "10 байт м.кода". Код (методы, функции) не занимают места внутри объектов. Внутри объекта занимают память только поля класса - данные - i и j в ваших примерах. 

    static и dynamic - это вообще никак не пересекающиеся понятия. как "красный" и "мягкий". В фразе, построенной как "в dynamic случае ..., в отличие от static" нет смысла. в коде можно написать static dynamic someField. И получить общее для всех экземляров (статическое) поле, проверки типов для которого будут производиться во время выполнения (dynamic).

    Модератор
  • Вы пытаетесь заниматься микрооптимизацией вместо решения самой задачи поставленной перед вами. У вас скорее всего найдутся более сложные места в алгоритме программы, которые будут занимать значительно больше ресурсов, вот на них и стоит смотреть и оптимизировать их.


    Для связи [mail]