Страницы

Поиск по вопросам

воскресенье, 24 ноября 2019 г.

Что такое interning и как им пользоваться


Что такое interning? Для чего оно применяется? Когда стоит его применять и каки
возможны подводные камни? 
    


Ответы

Ответ 1



Interning — это метод хранения лишь одной копии из многих одинаковых объектов. Применяется в C# и Java к строкам, а также (в Java) к небольшим числам. Рассмотрим на примере строк. Когда вы говорите string.Intern(s) в C# или s.intern( в Java для строки s, вы получаете строку с таким же содержимым, но возвращённая строк гарантировано одна и та же (то есть, один и тот же объект), если вы запрашиваете интернированную строку с одним и тем же содержимым. Также, строковые константы автоматически интернируются. Однако, строки полученные другим путём, например, через StringBuilder или конкатенацию не будут интернированы, по крайней мере в текущей версии языков. (Впрочем, оптимизатор может соптимизировать конкатенацию, если сумеет вычислить аргументы во время компиляции, так что рассчитывать на это не стоит.) Пример: // C# object.ReferenceEquals("123", "123") // true object.ReferenceEquals(string.Intern("12" + "3"), "123") // true char[] chars = new[] { '1', '2', '3' }; object.ReferenceEquals(new string(chars), new string(chars)) // false object.ReferenceEquals(new string(chars), "123") // false object.ReferenceEquals(string.Intern(new string(chars)), "123") // true // Java "123" == "123" // true ("12" + "3").intern() == "123" // true new String("123") == new String("123") // false new String("123") == "123" // false new String("123").intern() == "123" // true Это значит, что интернированные объекты можно сравнивать через ReferenceEquals (C#) / == (Java). Когда вызывается метод Intern()/intern(), рантайм-библиотека просматривает пул интернированны объектов в поисках данного или равного ему. Если такой объект находится, он возвращается, если нет, данный объект интернируется и возвращается. Для чего можно пользоваться этим? Например, можно уменьшить расход памяти программы если в ней используется большое количество строк, среди которых много дубликатов. Например у вас есть огромный XML-файл, состоящий из почти одинаковых записей. Или огромный текст программы на каком-нибудь языке программирования. Тогда в некоторых случаях можно уменьшить потребление памяти путём интернирования строк: например, все экземпляры while будут одним и тем же объектом. Внимание! Сама по себе считанная из файла строка не интернируется, даже если он и равна какой-то интернированной строке. Учтите, однако, что однажды интернированую строку нельзя «деинтернировать», и он будет занимать память программы даже когда больше не будет вам нужна. Поэтому имейте в виду, что интернирование строк может оказать и негативный эффект на расход памяти программой! Поэтому если вы решаете применить интернирование в своей программе, обязательно спрофилируйт расход памяти и убедитесь, что ваша оптимизация действительно улучшает ситуацию! (Впрочем, это относится практически ко всем оптимизациям.) Далее, интернирование строки делает поиск в глобальных структурах, и поэтому наверняк будет требовать глобальной блокировки. Поэтому несколько потоков, активно применяющих интернирование, будут «сражаться» за общий ресурс. Ещё одним преимуществом интернированных строк является то, что их можно быстрее сравнивать Например, если вы разбираете программный текст, и все ключевые слова интернированы, вы можете сравнивать их как объекты (что, разумеется, намного скорее). В .NET вы можете управлять тем, будет ли применяться автоматическое интернировани строковых констант на уровне сборок (assembly). По умолчанию строковые константы, как было сказано выше, интернируются, но вы можете запретить это, указав атрибут CompilationRelaxations.NoStringInterning. В Java кроме строк интернируются также и упакованные (boxed) числа. Например, упакованны константы типов Integer и Long в пределах от -128 до 127, Boolean и Byte хранятся в пуле интернированных объектов. Пример: Integer x = 1; Integer y = 1; Integer z = new Integer(1); x == y // true y == z // false

Комментариев нет:

Отправить комментарий