2013-12-04 2 views
1

У меня есть два класса:Может ли призывать получателя суперкласса снизить эффективность?

abstract class Employee{ 
    protected int id; 

    public int getId(){ 
     return id; 
    } 
} 

class Manager extends Employee{ 
} 

В ходе выполнения остальной части моего приложения я создаю много объектов сотрудников и называю их метод GetId() много раз.

Время выполнения составляет около 8 секунд. Но если добавить следующий метод менеджер:

@Override 
    public int getId(){ 
     return super.id; 
    } 

..следующих же программа (сохраняя все остальное постоянная) в настоящее время работает в два раза меньше времени. Я тестировал обе версии несколько раз и получал те же результаты. Может ли кто-нибудь подумать о причине этого?

+0

Вы повторяли оба запуска несколько раз или только вторую версию? (Ваш текст немного неясен в отношении этого.) – Omaha

+0

Вы добавили 'getId()' в 'Employee'or' Manager'? – neutrino

+1

'super'' Employee' является 'Object', и у него нет поля' id', поэтому это не должно компилироваться. –

ответ

3

Когда вы запускаете микро-бенчмарк, вы очень восприимчивы к тому, как вы выполнили бенчмарк и какой код можно оптимизировать. Это означает, что код, который в основном такой же, может быть настолько тонким, но относительно большим различием в производительности. Однако, если вы сделали тест немного по-другому или используете другое обновление Java, вы можете найти совсем другой результат.

Когда вы переопределяете метод в подклассе, вы фактически делаете класс виртуальным. Это означает, что вы можете позвонить Employee.getId() или Manager.getId(), и ему нужно проверить тип, чтобы определить, какой метод класса вызывать. Тот факт, что методы одинаковы, не помогает. JVM может быть разумным и встроенным методом, но поскольку ваш метод тривиален, очень простая проверка типа может означать разницу в производительности. ,

Возможно также, что это изменение превращает другую оптимизацию. Например, «редкая» является только встроенной, если она имеет длину 35 байтов. Это может вызвать проблемы с блоками try/catch. Блок try/catch сам по себе не замедляет работу кода, но может сделать метод больше и означает, что он больше не встроен. В вашем случае наличие метода overriden может означать, что код вызова немного больше, когда ваш метод встроен и он не оптимизирован так агрессивно.

Наконец-то я проверил бы ваш код с последним JVM. например Обновление Java 7 40. Вы можете обнаружить, что эта версия не показывает разницу, и в этом случае я бы поставил ее на ошибку в вашей версии JVM.

+0

Я не думаю, что это будет микро-бенчмарк. В приложении также есть много другого кода. Только эту строку я изменил для сравнения производительности. – aditya

+0

@aditya Можете ли вы привести пример, который мы можем запустить? –

+0

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

1

Довольно интересно,

Чтобы просто подтвердить себя, я создал тестовый пример, чтобы воспроизвести поведение, учитывая ниже теста и результатов испытаний

Случай 1, когда не перекрывая метод

Результаты испытаний

Пробег 1 - Создание 100000000 Сотрудники Время, затраченное на выполнение операции: 501 (мс)

Run 2 - Создание 100000000 сотрудников Время, необходимое для завершения операции: 507 (мс)

Выполнить 3 - Создание 100000000 сотрудников Время, необходимое для завершения операции: 502 (мс)

Случай 2 -Если переопределения метода в подпункте класса,

@Override 
     public int getId(){ 
      return super.id; 
     } 

Test Result 

Run 1 - Создание 100000000 Employees Время, необходимое для завершения операции: 486 (мс)

Run 2 - Создание 100000000 Сотрудники Время, необходимое для завершения операции: 497 (мс)

Run 3 - Создание 100000000 сотрудников Время, необходимое для завершения операции: 478 (мс)

Случай 3 - переопределение метода, но не используя супер ключевое слово

@Override 
     public int getId(){ 
      return id; 
     } 

Результат теста

Run 1 - Создание 100000000 сотрудников Время, необходимое для завершения операции: 457 (мс)

Run 2 - Создание 100000000 сотрудников Время, необходимое для завершения операции: 471 (мс)

Run 3 - Создание 100000000 сотрудников Время, необходимое для завершения операции: 471 (мс)

Наблюдение:

Существует минимальное улучшение при переопределении метода/использования непосредственно (случай 2 и случай 3); но в качестве наилучшей практики большинство случаев, которые переменная будет объявлена ​​конфиденциальной, и метод будут защищены. Если сама переменная защищена, то вам нужно будет супер ключ

---------- Полный код теста для справки -----

public class TestEff { 

    public static void main(String[] args) { 
     System.out.println(" Creating 100000000 Employees "); 
     long st = System.currentTimeMillis(); 
     for(int i=0;i<100000000;i++){ 
      Manager mgr = new Manager(); 
      int id =mgr.getId(); 
     } 
     long et = System.currentTimeMillis(); 
     long t = (et-st); 
     System.out.println(" Time taken to complete operation :"+t); 
    } 
} 

abstract class Employee{ 
    protected int id; 

    public int getId(){ 
     return id; 
    } 
} 

класс Менеджер расширяет Employee { @Override public int getId() { return super.id; } }

Смежные вопросы