Наверху реализации интерфейса

С TkAgg в качестве бэкэнда это единственная комбинация, которая максимизирует окно без полноэкранного режима:

win_manager = plt.get_current_fig_manager()
win_manager.window.state('zoomed')
win_manager.full_screen_toggle()
12
задан Sildoreth 3 April 2015 в 20:33
поделиться

11 ответов

couldn't resist and tested it and it looks like almost no overhead.

Participants are:

Interface IFoo    defining a method
class Foo: IFoo   implements IFoo
class Bar         implements the same method as Foo, but no interface involved

so i defined

Foo realfoo = new Foo();
IFoo ifoo = new Foo();
Bar bar =  new Bar();

and called the method, which does 20 string concatenations, 10,000,000 times on each variable.

realfoo:   723 Milliseconds
ifoo:      732 Milliseconds
bar:       728 Milliseconds

If the method does nothing, the actual calls stand out a bit more.

  realfoo: 48 Milliseconds
  ifoo: 62 Milliseconds
  bar: 49 Milliseconds
17
ответ дан 2 December 2019 в 02:55
поделиться

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

Сказав это недавно, я реорганизовал несколько классов, представив интерфейсы и выполнив все вызовы через интерфейс. Я был настолько уверен (или ленив), что это никак не повлияет, что мы выпустили его без проверки производительности. Оказалось, что это 10% сказалось на производительности всего приложения (а не только вызовов). Мы внесли ряд изменений, и это было последнее, о чем мы подозревали. В конце концов, когда мы вернулись к конкретным занятиям, первоначальная производительность была восстановлена.

1
ответ дан 2 December 2019 в 02:55
поделиться

Unfortunately for Java there is yet some optimization which can be done to improve interface performance. Yes there is "almost no overhead" to the invokevirtual and invokeinterface instructions compared to invokespecial but there is a Da Vinci project which targets a performance shortcoming in the very very common trivial use of interfaces: an object which implements only a single interface and is never overloaded.

See this Java bugparade request for enchancement for all the technical details you could wish for.

As always (and it seems you understand this), consult Amdahl's Law when quibbling about micro-optimizations like this. If you are making that many method calls and need the speed consider refactoring combined with thorough benchmarking.

3
ответ дан 2 December 2019 в 02:55
поделиться

Накладные расходы по сравнению с чем?

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

Тем не менее, в большинстве случаев производительность не соответствует действительности.

3
ответ дан 2 December 2019 в 02:55
поделиться

Да, интерфейсы несут накладные расходы. Фактически, каждый слой, который вы добавляете между логикой и процессором, увеличивает накладные расходы. Очевидно, вам следует писать все на ассемблере, потому что это единственное, что не требует накладных расходов. Графический интерфейс также требует накладных расходов, поэтому не используйте их.

Я шучу, но дело в том, что вы должны найти свой собственный баланс между ясным, понятным, поддерживаемым кодом и производительностью. Для 99,999% (повторяющихся, конечно) приложений, если вы будете внимательны, чтобы избежать ненужного повторения выполнения любого из ваших более дорогих методов, вы никогда не дойдете до точки, когда вам нужно будет усложнить обслуживание просто ради того, чтобы он работал быстрее.

4
ответ дан 2 December 2019 в 02:55
поделиться

Хотя интерфейс НЕ должен вызывать накладные расходы, каким-то образом они возникают. Я не знаю этого напрямую, но мы работаем с кабельными коробками, и они настолько слабые, что мы тестируем различные сценарии производительности. (Количество экземпляров классов имеет ОГРОМНУЮ разницу.)

Этого не должно быть, потому что интерфейс имеет очень небольшое влияние во время выполнения, это не похоже на то, как вызов проходит «через» интерфейс, интерфейс - это просто способ, которым компилятор связывает две части кода - во время выполнения это не должно быть больше, чем таблица диспетчеризации указателя.

И все же это влияет на производительность. Я предполагаю, что это связано с метаданными / отражением, потому что, если вам не нужны метаданные, ЕДИНСТВЕННЫЙ раз, когда интерфейс будет использоваться, - это при приведении из менее конкретного интерфейса к этому интерфейсу, и тогда это будет только тег, чтобы проверить и посмотреть, возможно ли это.

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

2
ответ дан 2 December 2019 в 02:55
поделиться

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

Есть накладные расходы, но это накладные расходы на уровне микрооптимизации. Например, интерфейс может выполнять много вызовов в режиме IL, переключаясь с вызова на callvirt, но это невероятно незначительно.

6
ответ дан 2 December 2019 в 02:55
поделиться

Интерфейсы несут накладные расходы из-за дополнительной косвенности, выполняемой при вызове методов или доступе к свойствам. Многие системы для реализации полиморфизма, включая реализацию интерфейсов, обычно используют таблицу виртуальных методов, которая отображает вызовы функций на основе типа времени выполнения.

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

В подавляющем большинстве случаев преимущества использования вызовов виртуальных функций значительно перевешивают недостатки.

9
ответ дан 2 December 2019 в 02:55
поделиться

Если у вас нет особых требований (например, «мы делаем игру, и она должна работать со скоростью 60 кадров в секунду, макет данных, согласованность кеша и преобразование указанных данных невероятно важны»), я даже не стал бы думать о дополнительных затратах на производительность вызова интерфейса при написании программного обеспечения. Это будет заметно только при определенных обстоятельствах.

Например: выполнение огромного количества вызовов через интерфейс в тесном цикле (и даже в этом случае стоимость выполнения тела метода может значительно превзойти накладные расходы на вызов интерфейса) или «погоня за указателем» при обработке данных.

Кроме того, ничто не мешает вам изменить контракт интерфейса, чтобы сделать вызов более грубым, например IMyInterface.Process (Car [] cars) вместо IMyInterface. Процесс (Автомобиль)

В Code Complete Стив МакКоннелл советует избегать постоянной микрооптимизации. Он говорит, что лучше всего написать программу, используя передовой опыт (т. Е. Сконцентрироваться на удобстве сопровождения, удобочитаемости и т. Д.), А затем, когда вы закончите, если производительность недостаточна, профилируйте ее и предпримите шаги для устранения основных узких мест.

Нет смысла спекулятивно оптимизировать весь код только потому, что он может быть быстрее. Если 80% вашего времени выполнения тратится на выполнение 20% кода, очевидно, глупо жертвовать слабой связью повсюду «просто потому, что» это может сэкономить 10 микросекунд здесь или там. Таким образом, вы экономите 10 микросекунд, но ваша программа не станет быстрее, если какая-то другая функция пожирает процессор.

Если вы работаете над программным обеспечением, не критичным для производительности, Я бы назвал отказ от интерфейсов микрооптимизацией. Это также то, что впоследствии можно легко удалить, если это необходимо (при условии, что вы не будете поставлять программное обеспечение в ближайшее время). Большинству программного обеспечения не нужна молниеносная скорость. Есть исключения (игры, симуляторы, торговля акциями в реальном времени и т. Д.), Но даже в этом случае не всегда интерфейсы являются виновниками.

4
ответ дан 2 December 2019 в 02:55
поделиться

Говоря с точки зрения Java , по крайней мере, в последних версиях Hotspot, ответ обычно небольшой или никакой накладных расходов, когда это имеет значение .

Например, предположим, что у вас есть такой метод, как следующий:

public void doSomethingWith(CharSequence cs) {
  char ch = cs.charAt(0);
  ...
}

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

Но на самом деле виртуальная машина может быть намного умнее этого. Если это сработает на практике, вы всегда передаете объекты определенного типа, то не только можно пропустить проверку типа объекта, но он может даже встроить метод. Например, если вы вызываете метод, подобный приведенному выше, в цикле для серии строк, Hotspot может фактически встроить вызов charAt (), так что получение символа буквально становится парой инструкций MOV - другими словами, вызов метода на интерфейсе может превратиться даже в отсутствие вызова метода . (PS Эта информация основана на выходных данных сборки отладочной версии 1.6, обновление 12.)

12
ответ дан 2 December 2019 в 02:55
поделиться

Virtual Stub dispatch is different than Interface Dispatch. Vance Morrison, The CLR JIT lead describes that in details in this blog post. http://blogs.msdn.com/vancem/archive/2006/03/13/550529.aspx

1
ответ дан 2 December 2019 в 02:55
поделиться