Почему библиотека Scala удвоила свой размер между 2,7 и 2,8? - PullRequest
22 голосов
/ 23 ноября 2010

Сравнение Scala 2.7.7 (последний выпуск 2.7.x) с Scala 2.8.1 (последний выпуск 2.8.x) Я собрал следующие метрики:

 Scala version        |    2.7.7          2.8.1                              
------------------------------------------------
 Compressed jar file  |   3.6 MB         6.2 MB   
 Uncompressed files   |   8.3 MB        16.5 MB
 .class files in .    |   1.8 MB         1.7 MB
   in ./actors        | 554.0 KB         1.3 MB      
   in ./annotation    |   962  B        11.7 KB 
   in ./collection    |   2.8 MB         8.8 MB
   in ./compat        |   3.8 3B         3.8 KB
   in ./concurrent    | 107.3 KB       228.0 KB
   in ./io            | 175.7 KB       210.6 KB
   in ./math          |    ---         337.5 KB
   in ./mobile        |  40.8 KB        47.3 KB
   in ./ref           |  21.8 KB        26.5 KB 
   in ./reflect       | 213.9 KB       940.5 KB
   in ./runtime       | 271.0 KB       338.9 KB
   in ./testing       |  47.1 KB        53.0 KB
   in ./text          |  27.6 KB        34.4 KB
   in ./util          |   1.6 MB         1.4 MB       
   in ./xml           | 738.9 KB         1.1 MB  

Крупнейшими нарушителями являются scala.collection (в 3,1 раза больше) и scala.reflect (в 4,4 раза больше).Увеличение в пакете сбора происходит в то же время, что и переписывание всей инфраструктуры сбора для 2.8, так что я думаю, в этом причина.

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

  • Почему перезапись привела к такому большому увеличениюразмер?

Насколько я знаю, планируется улучшить scala.io , scala.reflect и scala.swing Есть, по крайней мере, две другие библиотеки актеров, которые делают то же самое, что scala.actor (Поднять актеров) или намного больше (Akka) и scala.testing официально уже заменены третьей сторонойбиблиотеки тестирования.

  • Будет ли улучшенный scala.io , scala.reflect или scala.swing привести ксопоставимое увеличение размера или было в случае scala.collection действительно особое обстоятельство?

  • Считается ли делегированием реализации акторов Lift или Akka, если в JDK 8 будет пригодная для использования модульная система?

  • Планируется ли окончательно удалить scala.testing или отделить его от jar-файла библиотеки?

  • Возможно включение SAMтипы, методы Defender или MethodHandles в JDK7 / JDK8 приводят к возможности уменьшения количества классов, которые компилятор Scala должен сгенерировать для анонимного / внутреннего класса / синглетонов / и т. д.?

Ответы [ 4 ]

31 голосов
/ 24 ноября 2010

Специализация была одним из факторов (увеличение банка примерно на 0,9 МБ). Другим фактором являются библиотеки коллекций, которые теперь реализуют больший набор операций равномерно по большому набору типов реализации. Значительное увеличение происходит только в байт-кодах, потому что в новых библиотеках коллекций очень интенсивно используется состав mixin, что приводит к увеличению размера файла класса. У меня нет данных о размере исходного файла, но я считаю, что увеличение было намного меньше.

23 голосов
/ 23 ноября 2010

Я никоим образом не связан ни с проектом Scala, ни с компаниями, которые его поддерживают. Так что примите все ниже, как мое личное мнение ·

  • Почему перезапись привела к такому большому увеличению размера?

Скорее всего, не само переписывание, а специализация . В частности, это определение Function1:

trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R]

означает, что все методы в Function1 будут реализованы 35 раз (по одному для каждого из Int, Long, Float, Double и AnyRef T1 раз каждый Unit, Boolean, Int, Float, Long, Double и AnyRef R.

Теперь посмотрите на Scaladoc и посмотрите известные подклассы для Function1. Я не буду даже копировать это здесь. Также специализируется там, где Function0 и Function2, хотя их влияние намного меньше.

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

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

  • Приведет ли улучшенный scala.io, scala.reflect или scala.swing к сопоставимому увеличению размера или случай scala.collection был действительно особым обстоятельством?

Несопоставимо, потому что переписывание не имеет к этому никакого отношения. Тем не менее, настоящая scala.io библиотека, несомненно, будет намного больше той, что существует в наши дни, и я ожидал бы того же от истинной системы отражений для Scala (о последних были статьи). Что касается swing, я не думаю, что есть что-то, кроме постепенных улучшений, в основном это обертки вокруг библиотек Java, поэтому я сомневаюсь, что это сильно изменится в размере.

  • Считается ли делегированием реализации акторов Lift или Akka, если в JDK 8 будет использоваться используемая система модульности?

У каждой реализации есть свои сильные стороны, и пока я не видел никаких признаков сближения. Что касается JDK 8, как Scala должна быть совместима с JDK 5 при модульности для JDK 8? Я не имею в виду, что это невозможно, но, скорее всего, слишком много усилий для доступных ресурсов.

  • Есть ли планы окончательно удалить scala.testing или разделить его из jar-файла библиотеки?

Это уже обсуждалось, но есть также проблема с наличием некоторого своего рода инфраструктуры тестирования, доступной для самого компилятора, с гибкостью, которую не может обеспечить сторонняя среда тестирования. Впрочем, его вполне можно переместить (или удалить и заменить чем-то другим) в компилятор jar.

  • Может ли включение типов SAM, Defender Methods или MethodHandles в JDK7 / JDK8 привести к возможности уменьшения количества классов, которые компилятор Scala должен сгенерировать для анонимных / внутренних классов / синглетонов / и т. Д.?

Конечно, когда-то больше никто не использует JDK5 / JDK6. Конечно, если JDK7 / JDK8 получат широкое распространение и улучшения будут достаточно полезными, то вполне может наступить момент, когда Scala будет распространяться с двумя различными jar-файлами для своей библиотеки. Но на данный момент еще рано вызывать гипотетические сценарии.

8 голосов
/ 23 ноября 2010

Я думаю, что увеличение размера происходит не от перезаписи, а из-за специализации параметров типа, которые были введены / включены в 2.8.

1 голос
/ 09 ноября 2011

Размер увеличился, но собирается немного снизиться.

В сообщении блога " Подводные камни в Scala: Черта вздора ", опубликованном Тоддом Вирлингом 7 ноября 2011 года, также указывается на Поддержка множественного наследования Scala :

То, как код реализации черты обрабатывается в компиляторе Scala - из-за ограничений JVM - приводит к раздутию файла класса, уменьшению оптимизации JIT и увеличению использования памяти.
Обратите внимание, что эти проблемы не характерны для Scala; другие методологии, такие как смешанный состав АОП, страдают от чрезвычайно похожих проблем.
Поскольку Java-интерфейсы не могут содержать код реализации *, компилятор Scala выполняет несколько трюков, чтобы это произошло.

Сочетание этих ферм методов-заглушек, которые могут напоминать таблицы переходов для тех, которые знакомы с кодом ассемблера, с дополнительными данными, добавленными для сигнатур типа Scala, привело к значительному увеличению классов сбора между 2.7.x и 2.9. .x .
Честно говоря, коллекции унаследовали от слишком многих признаков при слишком большом количестве реализаций по умолчанию, что привело к таким вещам, как дополнительные 40 КБ несжатого размера файла класса для каждого случая такого рода кода:

  ... = new Iterator[X] {
    def hasNext = ...
    def next = ...
  }

... или аналогичная конструкция "расширяет Iterator [X]" на именованный класс.

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

Тодд Вирлинг указывает на эти изменения в скале / стволе [25959: 25964] , что позволяет уменьшить размер scala-library.jar примерно на 1.5MB .

Это немалое количество для библиотеки, которая накапливалась на 9 МБ в Scala 2.9.x, но нулевая функциональность была потеряна.

К счастью, есть спасательный люк. От Преднамеренно инициируя создание метода-заглушки в известной точке в цепочке наследования классов, можно уменьшить количество генерируемых заглушек для каждой специализации, необходимой для всей библиотеки.
Это делается с помощью очень простой конструкции: абстрактного класса, который наследуется от обычно специализированной черты.

...