Накладные расходы на "бокс" примитивных типов через имплициты в Scala - PullRequest
6 голосов
/ 20 октября 2010

Предположим, я хочу иметь класс, подобный Java Date.Его единственный элемент данных - это long, представляющий миллисекунды с 1970 года.

Будет ли это полезным для производительности, если просто создать новый тип Scala:

type PrimitiveDate = Long

Затем вы можете добавитьметоды с использованием неявного преобразования, как это делается для int с RichInt.Включает ли эта «упаковка» примитивного типа в богатый класс какие-либо издержки (создание класса)?По сути, вы можете просто использовать статический метод

def addMonth(date: PrimitiveDate, months: Int): PrimitiveDate = date + 2592000000 * months

и позволить системе типов выяснить, что его нужно применять, когда в вашем коде появляется d addMonth 5.

Редактировать

Кажется, что псевдоним, который вы создаете, записывая type PrimitiveDate = Long, не применяется компилятором scala.Является ли создание надлежащего класса, включающего Long, единственным способом создания принудительного типа в Scala?

Насколько полезна возможность создания псевдонима принудительного типа для примитивных типов?

Ответы [ 3 ]

11 голосов
/ 20 октября 2010

Ну, escape-анализ должен означать, что самые последние JVM на самом деле не должны создавать вашу обогащенную оболочку , чтобы вызвать метод addMonth,

Степень, в которой это действительно происходит на практике , очевидно, будет зависеть от того, сколько времени выполнения hotspot JVM решает, что эти методы добавляются при создании объекта.Когда анализ побега не происходит, очевидно, что JVM придется «поместить» (как вы говорите) Long в новый экземпляр класса-оболочки.Он не включает в себя «создание класса» - это будет включать «создание экземпляра класса».Этот экземпляр, будучи недолговечным, сразу же будет GC-d, поэтому накладные расходы (хотя и небольшие):

  • выделение памяти для экземпляра
  • GC-просмотр экземпляра

Это, очевидно, будет проблемой любого рода, если вы определенно пишете код с очень низкой задержкой, в котором вы пытаетесь свести к минимуму создание мусора (в узком цикле).Только вы знаете, так ли это.

Что касается того, будет ли подход работать для вас (и вам поможет анализ побега), вам придется тестировать в дикой природе.Микро-тесты, как известно, трудно написать для такого рода вещей.


Причина, по которой мне не нравятся эти псевдонимы типов , являющиеся частью общедоступного API , заключается в том, что scala делаетне навязывай их так строго, как хотелось бы.Например:

type PrimitiveDate = Long
type PrimitiveSpeed = Long
type Car = String
type Meeting = String

var maxSpeeds : Map[Car, PrimitiveSpeed] = Map.empty

//OOPS - much too easy to accidentally send the wrong type
def setDate(meeting : Meeting, date : PrimitiveDate) = maxSpeeds += (meeting -> date)
4 голосов
/ 20 октября 2010

Вы на самом деле не создали новый тип в данном примере, это просто псевдоним для уже существующего типа Long.

Это техника, которую я часто использую для работы с громоздкими вложенными соединениями.Например, я бы использовал псевдоним type Grid = Seq[Seq[Int]], чтобы избежать необходимости указывать Seq[Seq[Int]] снова и снова для различных параметров.

Вы можете с радостью передать Long методу, принимающему метод PrimitiveDateХотя вы делаете имеете преимущество в том, что код намного лучше самодокументирован.

Если вы действительно хотите создать новый тип с принудительной безопасностью типов и удобным сопоставлением с образцом, яиспользовать класс case:

case class PrimitiveDate(value:Long)

и, возможно, даже обеспечить неявное преобразование Long => PrimitiveDate для удобства.

3 голосов
/ 24 августа 2015

Через 11 месяцев после того, как вы задали этот вопрос, Майлз Сабин обнаружил очень простой, элегантный и эффективный способ создания распакованных новых типов в Scala.В отличие от псевдонимов типов, теги типов являются обязательными.Примитивным типам нужен минимальный шаблон (одна строка на примитив) для обеспечения специализации.

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

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

...