Подтвердить что ты не робот

Почему библиотека Scala удвоила размер от 2.7 до 2.8?

Сравнение 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(Lift актеры) или намного больше (Akka) и scala.testing официально уже заменена сторонними библиотеками тестирования.

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

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

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

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

4b9b3361

Ответ 1

Я никоим образом не связан с проектом 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 файла библиотеки?

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

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

Сообщение в блоге Scala Ловушки: Trait Bloat "отправлено Todd Vierling от 7 ноября 2011 года также указывает на Scala поддержку нескольких наследований:

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

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

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

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

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

Тодд Вирлинг указывает на те изменения в scala/trunk [25959: 25964], что позволяет уменьшить размер scala-library.jar примерно 1,5 МБ.

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

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