2014-12-05 5 views
3

Я вижу сообщения, подобные постижению в [1], и это действительно заставляет меня задаться вопросом, какова общая импликация использования неизменяемой Map vs Mutable. Похоже, что разработчики Scala очень удобны, позволяя мутациям неизменных структур данных брать на себя расходы на новый объект, или, может быть, я просто что-то упустил. Если каждая операция мутации в неизменяемой структуре данных возвращает новый экземпляр, хотя я понимаю, что это хорошо для безопасности потоков, но что, если я знаю, как точно настроить мои изменчивые объекты, чтобы сделать эти же гарантии?Стоимость создания неизменяемого объекта Scala

[1] In Scala, how can I do the equivalent of an SQL SUM and GROUP BY?

+2

Структурный обмен означает, что совершенно новая копия часто не требуется. –

+2

«Если каждая операция мутации в неизменяемой структуре данных возвращает новый экземпляр», это не дублирует весь экземпляр, неизменяемые структуры позволяют совместное использование данных. – vptheron

+0

У вас есть конкретный пример, в котором недостаточно производительности для понимания? –

ответ

7

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

Теоретически, достаточно интеллектуальный компилятор ™ должен быть способен - возможно, с помощью системы линейного типа (предполагаемой или иной) - воспроизводить все преимущества эффективности изменяемой структуры данных. Фактически, поскольку у него есть больше информации о намерениях программиста и он менее ограничен случайными деталями, которые должен был указать программист, такой компилятор должен иметь возможность генерировать более высокопроизводительный код - и, например, GCC переписывает код в неизменяемую форму (SSA) для целей оптимизации. Для примера, который приближается к дому, многие Java-программы реального мира обладают достаточной пропускной способностью, но имеют проблемы с задержкой, вызванные сборщиком мусора Java, который останавливает мир, чтобы сжать кучу. JVM, который знал, что некоторые объекты неизменяемы, сможет перемещать их, не останавливая мир (вы можете просто скопировать объект, обновить все ссылки на него и затем удалить старую копию, поскольку не имеет значения, если некоторые потоки см. старую версию, а некоторые из них видят новую).

На практике это зависит, и снова единственный способ - проверить свой конкретный случай. По моему опыту, для уровня инвестиций времени программиста, доступного для большинства практических бизнес-задач, расходы x часов на (неизменяемую) версию Scala, как правило, дают более эффективную программу, чем расходы того же времени на изменяемую версию Scala или Java - действительно, в размере времени программиста, которое требуется для создания приемлемо исполняющейся версии Scala, вероятно, вообще невозможно завершить версию Java (особенно, если нам требуется такая же скорость дефекта).С другой стороны, если у вас есть неограниченное время для опытного программиста и вам нужно получить максимально возможную производительность, вы, вероятно, захотите использовать очень низкоуровневый изменяемый язык (вот почему LAPACK все еще написан на Fortran) - или даже реализовать свой алгоритм непосредственно на FPGA, как недавно сделал JP Morgan.

Но даже в этом случае вы, вероятно, захотите иметь прототип на языке более высокого уровня, чтобы вы могли писать тесты и сравнивать их, чтобы убедиться, что высокопроизводительная реализация работает правильно. В частности, если мы просто говорим о изменчивом и неизменяемом в Scala, преждевременная оптимизация - это корень всего зла. Напишите свою программу, а затем, если производительность неадекватна, просмотрите ее и посмотрите на горячие точки. Если вы действительно тратите слишком много времени на копирование неизменяемой структуры данных, это подходящее время для замены его изменчивой версией и тщательно проверяйте гарантии безопасности потоков вручную. Если вы пишете правильно развязанный код, тогда вам должно быть легко заменить критичные по производительности элементы как и когда вам нужно, и до тех пор вы сможете пожинать время разработки кода, которое проще и проще рассуждать (особенно в параллелизме случаев). По моему опыту проблемы производительности в хорошо написанном коде намного реже, чем люди ожидают; большинство проблем с производительностью программного обеспечения вызваны плохим выбором алгоритма или структуры данных, а не такими небольшими накладными расходами.

+0

lmm, я благодарю вас за то, что нашли время, чтобы сломать это. Все спрашивают конкретные примеры и контрольные показатели производительности - ни те, над которыми я работаю, ни стремлюсь производить. Я интересуюсь инженером, у меня много вопросов о языке, о котором я быстро учусь и не знаю, как близко, как мне хотелось. Я немного больше, чем на полпути через книгу «Программирование в Скале» Мартина Ордерского, и у меня есть много вопросов, которые не слишком много точек для получения ответа. Еще раз за то, что нашли время, чтобы объяснить некоторые из этих понятий. –

+0

Честно говоря, переполнение стека не может быть лучшим местом для такого общего вопроса - оно очень ориентировано на конкретные конкретные вопросы, которые имеют один объективный ответ. Но я действительно не хочу отправлять вам reddit или IRC: /. Scala привлекает много повторяющейся критики, и некоторые люди scala могут получить оборонительную позицию, когда новичок говорит что-то вроде атаки на язык; это несчастливо со всех сторон. – lmm

+0

Я начинаю видеть, что мои вопросы могут не подойти для переполнения стека. Я долгое время был парнем IRC. В эти дни я нахожусь на freenode, и я бы не прочь перескочить в чате Scala, если бы у людей было время ответить на мои вопросы «что, если» и «как это работает», более подробно. Я сам с открытым исходным кодом, и я не уверен, понимаю ли я, почему любое сообщество разработчиков будет защищаться от конструктивных проблем и критики - похоже, это может быть знаком ... особенно когда меня интересует только обучение , –

1

Ваш вопрос начинается с неправильного предположения, основанные на непонимании стоимости подвергаясь использования неизменяемых объектов.

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

Так в чем же разница с тонко отрегулированными, измененными вручную предметами?

  • неизменные объекты лучше подходят для Парадигма FP
  • компиляции оптимизации времени и проверки
  • снижает вероятность исключения времени выполнения
1

Вопрос очень общий, поэтому трудно дать определенный ответ. Кажется, что вам просто неудобно с распределением объектов в идиоматическом коде Scala, используемом для понимания и т. П.

Компилятор scala не выполняет никаких специальных магов для операций плавких предохранителей или для исключения выделения объектов. Это зависит от человека, который пишет структуру данных, чтобы убедиться, что функциональные структуры данных используют как можно больше из предыдущих версий (структурный обмен). Многие из структур данных, используемых в коллекциях scala, делают это достаточно хорошо. См. Например, этот разговор о Functional Data Structures in Scala, чтобы дать вам общее представление.

Если вы заинтересованы в деталях, книга, чтобы получить это Purely Functional Data Structures по Крис Окасаки. Материал в этой книге относится также к другим функциональным языкам, таким как Haskell и OCaml и Clojure.

JVM чрезвычайно хорош в распределении и сборе короткоживущих объектов. Так много вещей, которые кажутся возмутительно неэффективными для кого-то, привыкшего к программированию на низком уровне, на самом деле удивительно эффективны. Но есть определенные ситуации, когда изменяемое состояние имеет производительность или другие преимущества. Вот почему scala не запрещает изменчивое состояние, но только предпочитает неизменность. Если вы обнаружите, что вам действительно нужно изменить состояние по соображениям производительности, обычно рекомендуется использовать wrap your mutable state in an akka actor вместо того, чтобы пытаться правильно синхронизировать потоки нисходящего потока.

+0

Я предполагаю, что когда я сформулирую вопрос таким образом, чтобы правильно передать результат, который я ищу, я стараюсь получать более точные ответы. Спасибо! Я собираюсь купить эту книгу и дать уверенное чтение после того, как я закончил книгу «Программирование в Скала». –