powered by simpleCommunicator - 2.0.30     © 2024 Programmizd 02
Map
Форумы / Java [игнор отключен] [закрыт для гостей] / Generics - для чего нужно стирание типов
12 сообщений из 12, страница 1 из 1
Generics - для чего нужно стирание типов
    #40065440
JohnSparrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день.

Вопрос скорее теоретический, но все же. В Java generics информация о типах стирается и на этапе исполнения вместо них используется Object. Чем хуже подход C++/C#, когда для каждого варианта использования generic'a на этапе компиляции создается свой конкретный класс?

В первом томе книги Хорстманна на эту тему есть следующее сообщение:
авторНА ЗАМЕТКУ C++! В этом отношении обобщения в Java заметно отличаются от шаблонов в C++. Для каждого экземпляра шаблона в C++ получается свой тип. Это неприятное явление называется "раздуванием кода шаблона". Этим недостатком Java не страдает.
Т.н. "раздувание кода шаблона" - действительно неприятное явление?

Второй вопрос. Т.к. на этапе исполнения информация о типах стерта, элементы коллекции извлекаются примерно следующим образом:
Код: java
1.
ConcreteType item = (ConcreteType)list.Get(0);


Насколько значимы затраты на приведение типов при массированных вызовах list.Get() в данном случае?
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065445
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JohnSparrow
Добрый день.

Вопрос скорее теоретический, но все же. В Java generics информация о типах стирается и на этапе исполнения вместо них используется Object. Чем хуже подход C++/C#, когда для каждого варианта использования generic'a на этапе компиляции создается свой конкретный класс?

В первом томе книги Хорстманна на эту тему есть следующее сообщение:
авторНА ЗАМЕТКУ C++! В этом отношении обобщения в Java заметно отличаются от шаблонов в C++. Для каждого экземпляра шаблона в C++ получается свой тип. Это неприятное явление называется "раздуванием кода шаблона". Этим недостатком Java не страдает.

Т.н. "раздувание кода шаблона" - действительно неприятное явление?

Второй вопрос. Т.к. на этапе исполнения информация о типах стерта, элементы коллекции извлекаются примерно следующим образом:
Код: java
1.
ConcreteType item = (ConcreteType)list.Get(0);


Насколько значимы затраты на приведение типов при массированных вызовах list.Get() в данном случае?

Понамешано конечно у вас в вопросе...
1) Начнем с того почему в java не создаются специализированные версии templates и является ли раздувание кода проблемой. Честно скажу, я C++ знаю поверхностно, поэтому у меня возникает вопрос, а как там обстоят дела если нужно создать template для неизвестного на этапе компиляции класса?(допустим подгрузили модуль с реализацией)? В Java есть механизм reflection, по динамической подгрузке классов, поэтому слабо себе представляю как и главное зачем реализовывать в java специализацию. В Scala есть подобная штука, но там ты должен добавить аннотацию specialised и указать прямо типы для которых сгенерить оптимальный код. Но как показывает практика никому это нафиг не нужно. Далее, так как JVM оптимизирует в рантайме, то ничего в принципе не мешает ей скопилировать версию кода под определенный тип налету(не удивлюсь если так оно и работает).
По поводу раздутости - ну бинарник разбухает в случае C++ - насколько критично не мне судить, если это какие микроконтроллеры то вполне вероятно может быть критично.
2) Почему реализовано стирание типов. Все очень просто - главная фишка Java это обратная совместимость. Generics ввели только в версии 1.5, а до этого с коллекциями работали через Object. Ну собственно чтобы старый код не сломать и придумали это стирание, и вместо типобизеопасного кода на кэране компилятор добавляет рантайм касты. Сильно на производительность это не влияет, ты 100% не ощутишь. И вообще думать о таких микрооптимизациях программируя на Java - верная дорога выстрелить себе в голову, JVM в любом случае умнее тебя и соптимизирует лучше, поэтому расслабься и пиши ПОНЯТНЫЙ код, а если вдруг где будет тормозить - разбираться с этим локально. Уже давно никого не интересует в мире Java энтерпрайза последний выжатый из CPU тик, можно либо докупить новый мощный сервер либо распараллелить работу на 2 мелких, это будет дешевле чем платить программисту за оптимизацию
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065470
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JohnSparrow

Насколько значимы затраты на приведение типов при массированных вызовах list.Get() в данном случае?

Сам как раз на днях задался этим вопросом - так как нужно было сделать оптимизацию
при анализе обнаружил чо касты практически не влияют на производительность
на примере перегона 15 тысяч записей из монго в бд я не обнаружил ощутимой разницы с кастами и без.
Тоесть по факту перегонка шла 11 мин+- какие то секунды ,тоже самое с и кастами теже 11 мин
причем касты вложенные из объекта в лист далее в какой то определенный тип - например тот же Document оттуда еще каст))
так что на счет этого не думай вообще,сколько бы ты там не кастовал на производительность это не повлияет.
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065471
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник

Насколько значимы затраты на приведение типов при массированных вызовах list.Get() в данном случае?


Понамешано конечно у вас в вопросе...
В Scala есть подобная штука, но там ты должен добавить аннотацию specialised и указать прямо типы для которых сгенерить оптимальный код. [/quot]
в java это тоже уже есть(точней скоро будет)-немного не таком виде правда
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065473
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79
JohnSparrow

Насколько значимы затраты на приведение типов при массированных вызовах list.Get() в данном случае?

Сам как раз на днях задался этим вопросом - так как нужно было сделать оптимизацию
при анализе обнаружил чо касты практически не влияют на производительность
на примере перегона 15 тысяч записей из монго в бд я не обнаружил ощутимой разницы с кастами и без.
Тоесть по факту перегонка шла 11 мин+- какие то секунды ,тоже самое с и кастами теже 11 мин
причем касты вложенные из объекта в лист далее в какой то определенный тип - например тот же Document оттуда еще каст))
так что на счет этого не думай вообще,сколько бы ты там не кастовал на производительность это не повлияет.
это и без анализа понятно что не влияет. Чуйка должна работать.
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065476
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PetroNotC Sharp
asv79
пропущено...

Сам как раз на днях задался этим вопросом - так как нужно было сделать оптимизацию
при анализе обнаружил чо касты практически не влияют на производительность
на примере перегона 15 тысяч записей из монго в бд я не обнаружил ощутимой разницы с кастами и без.
Тоесть по факту перегонка шла 11 мин+- какие то секунды ,тоже самое с и кастами теже 11 мин
причем касты вложенные из объекта в лист далее в какой то определенный тип - например тот же Document оттуда еще каст))
так что на счет этого не думай вообще,сколько бы ты там не кастовал на производительность это не повлияет.
это и без анализа понятно что не влияет. Чуйка должна работать.

чуйка работает)
есть цикл - создаем объект в нем и с ним работаем
либо кастуем каждый раз - в итоге на 15 к итераций разница в несколько минут
поэтому лучше на существующем объекте хоть обкастоваться чем новый создавать ,особенно это касается коллекций
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065491
JohnSparrowВ Java generics информация о типах стирается и на этапе исполнения вместо них используется Object. Чем хуже подход C++/C#, когда для каждого варианта использования generic'a на этапе компиляции создается свой конкретный класс?
Я про стирание типов знаю только как о недостатке. Страшно ли что кол-во классов разбухнет от шаблонов? Может в некоторых случаях и так, но в .NET'e решили именно так сделать а не идти по стопам Java (которая как выше было сказано должна была это сделать для обратной совместимости), думаю это все не спроста. Но то что мы не можем создать Generic с примитивом порой сильно бьет по производительности. И приходится либо писать/использовать не стандартные коллекции написанные под каждый тип отдельно.

И да, в C# женерики генерируются в runtime . Но что интересно новые классы создаются только на каждый тип примитива (если он был нужен в коде), а на ссылочные типы создается только одна реализация:
C# guideUnlike with value types, another specialized version of the Stack<T> class is not created for the Order type. Instead, an instance of the specialized version of the Stack<T> class is created and the orders variable is set to reference it. Так что нет ни большого раздутия, ни стирания типов.
JohnSparrowНасколько значимы затраты на приведение типов при массированных вызовах list.Get() в данном случае?Я в JVM реализацию не смотрел, но думаю что это намного менее затратно нежели создание wrapper'a типа Integer/Long.

Ну и кстати.. generic типы стираются у объектов. У классов они остаются. Т.е. если мы напишем
Код: java
1.
class MyCustomList implements List<User> {}

то инфа про то что там указан User сохраняется и ее можно вытащить через Reflection.
забыл никможно либо докупить новый мощный сервер либо распараллелить работу на 2 мелких, это будет дешевле чем платить программисту за оптимизациюНу или не будет. Если код написан не оптимально, то он будет медленно работать как при вертикальном, так и при горизонтальном масштабировании. Даже самое крутое железо не сделает из квадратичной сложности логарифмическую. А добавив машинки мы увеличим throughput, но не улучшим latency.
PetroNotC Sharpэто и без анализа понятно что не влияет. Чуйка должна работать.Чуйка - это наугад. Еще полезно вещи знать точно. Про производительность можно сколько угодно гадать, но там столько нюансов, что проверять нужно обязательно.
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065492
JohnSparrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник

2) Почему реализовано стирание типов. Все очень просто - главная фишка Java это обратная совместимость. Generics ввели только в версии 1.5, а до этого с коллекциями работали через Object. Ну собственно чтобы старый код не сломать и придумали это стирание, и вместо типобизеопасного кода на кэране компилятор добавляет рантайм касты.


Это был единственный ответ на мой вопрос, спасибо. Что-то подобное, припоминаю, встречал в книге г-на Хорстманна, так что, вероятно, обратная совместимость и есть причина.

Странно (с точки зрения новичка), что было принято решение обеспечивать обратную совместимость таким способом. В .NET, к примеру, при компиляции для сборки задается целевая платформа (версия .NET). Хотите использовать разные новые возможности - компилируете для соотв. версии .NET, но тогда пользователям придется ее ставить. Не хотите - пишете на старой версии (без дженериков, например), но тогда пользователям меньше проблем.

Причина вопроса. Изучая Java (в данном случае после С++/С#, но не суть) я пишу некий код, например, с LinkedList<SomeType>. Не зная про стирание типов ожидаю, что он будет откомпилирован именно в LinkedList, оперирующий SomeType или его потомками. Вместо этого получаю LinkedList<Object>, а в качестве бонуса - встроенное приведение типов, да еще и невозможность в рамках одного класса сделать перегрузки вида
Код: java
1.
2.
3.
4.
5.
    public void SomeFunc(List<String> arg) {
    }

    public void SomeFunc(List<Date> arg) {
    }


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

По всему остальному. На С++ я программировал давно, тогда это дело называлось шаблонами, их не использовал. Потом писал на C#, а там набор готовых коллекций, как и в Java, построен на дженериках (только как в С++, порождающих новые классы для каждого набора типов аргументов). Относительно Вашего вопроса про Reflection применительно к C#: если в одной сборке есть переменная LinkedList<SomeType>, а в подгружаемой сборке есть класс - потомок SomeType или реализующий SomeType (если SomeType - интерфейс), то никаких проблем. Да, в случае с подгружаемой сборкой будет выполняться приведение типов между реальными объектами и SomeType, но на этапе выполнения список будет именно LinkedList<SomeType>, а не LinkedList<Object>.

Затраты времени на приведение типов, конечно, незначительны, да и Java - не Ассемблер. Но это, все таки, минус. Почитал обсуждение, стало интересно, насколько значимый. Понятно, что приведение типов при загрузке данных из БД - не самое узкое место (тест, кстати, не совсем адекватен задаче; а если файлы копировать, в т.ч. гигабайтного объема, приведения типов вообще никак заметно не будет). Сделал условно чистый пример - поиск максимальной строки в массиве большого объема. Один массив - из строк, второй - из объектов (по факту - тех же строк). Во случае с массивом объектов время поиска устойчиво на 5-6% больше, а разница только в наличии/отсутствии приведения типов. Вот код теста:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
import java.util.UUID;

public class Main {

    public static void main(String[] args) {
        final int count = 1_000_000;

        String strings[] = new String[count];
        Object objects[] = new Object[count];

        long start, durationString, durationObject;

        // init arrays
        String s;
        for(int i = 0; i < count; i++) {
            s = UUID.randomUUID().toString();
            strings[i] = s;
            objects[i] = s;
        }

        // process object array
        String maxObject = "";
        start = System.nanoTime();
        for(int i = 0; i < count; i++) {
            s = (String)objects[i];
            if(s.compareTo(maxObject) > 0)
                maxObject = s;
        }
        durationObject = System.nanoTime() - start;

        // process string array
        String maxString = "";
        start = System.nanoTime();
        for(int i = 0; i < count; i++) {
            s = strings[i];
            if(s.compareTo(maxString) > 0)
                maxString = s;
        }
        durationString = System.nanoTime() - start;
    }
}



На 10 млн. записей время поиск макс. строки в массиве строк - 419 мс, в массиве объектов - 458 мс, разница - 39 мс, т.е. 9.3% от времени на обработку массива строк. Почти 10% - неплохо так. Тест сделал раз 20, результаты все время схожие.

----
Пока писал, не увидел новое сообщение. Да, точно, упаковка/распаковка типов значений для работы с коллекциями - тоже плохо, да и затратно.
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065509
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stanislav Bashkyrtsev,
Не. Приведение типов работает быстро. Либо это не узкое место.
Я же прикладник. Не будет тут тормозов для прикладной задачи.
Для надуманной типа класс из 600 полей возможно.
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065513
JohnSparrowНа 10 млн. записей время поиск макс. строки в массиве строк - 419 мс, в массиве объектов - 458 мс, разница - 39 мс, т.е. 9.3% от времени на обработку массива строк. Почти 10% - неплохо так. Тест сделал раз 20, результаты все время схожие.
Не, это такой себе бенчмарк, на не разогретой JVM.. Что скажет если поменять местами эти циклы? :) К бенчмаркам нужно подходить с осторожностью, написать их хорошо не так просто, да и понять результаты тоже. А пока не умеешь (а их мало кто умеет писать), то к любым результатам нужно подходить с долей недоверия.
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065521
JohnSparrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stanislav Bashkyrtsev
Не, это такой себе бенчмарк, на не разогретой JVM.. Что скажет если поменять местами эти циклы? :) К бенчмаркам нужно подходить с осторожностью, написать их хорошо не так просто, да и понять результаты тоже. А пока не умеешь (а их мало кто умеет писать), то к любым результатам нужно подходить с долей недоверия.

Циклы местами менял, код есть, можете сами проверить. Результаты (численные значения) получены из-под отладчика IntelliJ.
Дело не в бенчмарках, удивило стирание типов, как таковое. Приведение типов и пр. моменты - частные следствия.
...
Рейтинг: 0 / 0
Generics - для чего нужно стирание типов
    #40065536
JohnSparrow
Stanislav Bashkyrtsev
Не, это такой себе бенчмарк, на не разогретой JVM.. Что скажет если поменять местами эти циклы? :) К бенчмаркам нужно подходить с осторожностью, написать их хорошо не так просто, да и понять результаты тоже. А пока не умеешь (а их мало кто умеет писать), то к любым результатам нужно подходить с долей недоверия.

Циклы местами менял, код есть, можете сами проверить.
Так я проверил, у меня выходит что кто первый, тот и медленней.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Generics - для чего нужно стирание типов
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]