Интернирование строк - String interning
В информатике интернирование струн это метод хранения только одной копии каждого отдельного нить значение, которое должно быть неизменный.[1] Интернирование строк делает некоторые задачи обработки строк более эффективными по времени или пространству за счет того, что для создания или интернирования строки требуется больше времени. Различные значения хранятся в струнный внутренний бассейн.
Единственная копия каждой строки называется ее стажер и обычно ищется методом строкового класса, например String.intern ()[2] в Ява. Все строки констант времени компиляции в Java автоматически интернируются с использованием этого метода.[3]
Интернирование строк поддерживается некоторыми современными объектно-ориентированный языки программирования, включая Java, Python, PHP (начиная с 5.4), Lua,[4] Рубин (со своими символами),Юля и .NET языки.[5] Лисп, Схема, и Болтовня входят в число языков с символ тип, которые в основном представляют собой интернированные строки. Библиотека Стандартный ML Нью-Джерси содержит атом тип, который делает то же самое. Цель-C Селекторы, которые в основном используются как имена методов, представляют собой интернированные строки.
Могут быть интернированы объекты, отличные от строк. Например, в Java, когда примитивные значения в штучной упаковке в объект-оболочка, определенные значения (любые логический
, любой байт
, любой char
от 0 до 127 и любые короткая
или же int
между -128 и 127) интернированы, и любые два упаковочных преобразования одного из этих значений гарантированно приведут к одному и тому же объекту.[6]
История
Лисп ввел понятие интернированных строк для своих символы. Исторически структура данных, используемая в качестве внутреннего пула строк, называлась облист (когда он был реализован как связанный список) или Obarray (когда он был реализован в виде массива).
Современные диалекты Lisp обычно различают символы от строк; интернирование данной строки возвращает существующий символ или создает новый, чей имя это та строка. Символы часто имеют дополнительные свойства, которых нет у строк (например, хранилище для связанных значений или пространство имен): различие также полезно для предотвращения случайного сравнения интернированной строки с необязательно интернированной строкой, что может привести к периодическим сбоям в зависимости от шаблоны использования.
Мотивация
Интернирование строк ускоряет сравнение строк, которое иногда является узким местом производительности в приложениях (например, компиляторы и язык динамического программирования время выполнения), которые сильно зависят от ассоциативные массивы со строковыми ключами для поиска атрибутов и методов объекта. Без интернирования сравнение двух разных строк может включать изучение каждого символа обеих.[Примечание 1] Это происходит медленно по нескольким причинам: На) по длине струн; обычно требуется чтение из нескольких регионов объем памяти, которые требуют времени; а операции чтения заполняют кэш процессора, а это означает, что для других нужд остается меньше кеша. С интернированными строками простой проверка идентичности объекта достаточно после первоначальной стажировки; обычно это реализуется как проверка на равенство указателей, обычно это всего лишь одна машинная инструкция без ссылки на память вообще.
Интернирование строк также снижает использование памяти, если имеется много экземпляров одного и того же строкового значения; например, он читается из сеть или из место хранения. Такие строки могут включать магические числа или же сетевой протокол Информация. Например, синтаксические анализаторы XML могут использовать имена тегов и атрибутов для экономии памяти. Сетевая передача объектов через потоки объектов сериализации Java RMI может передавать строки, которые интернируются более эффективно, поскольку дескриптор объекта String используется вместо дублирующих объектов при сериализации.[7]
вопросы
Многопоточность
Одним из источников недостатков является то, что интернирование строк может быть проблематичным при смешивании с многопоточность. Во многих системах требуется, чтобы стажеры по строкам были глобальными для всех потоков в адресном пространстве (или в любых контекстах, которые могут совместно использовать указатели), таким образом, внутренний пул (ы) - это глобальные ресурсы, которые должны быть синхронизированы для безопасного одновременного доступа. Хотя это влияет только на создание строки (при необходимости внутренний пул должен быть проверен и изменен), и двойная проверка блокировки может использоваться на платформах, где это безопасная оптимизация, необходимость взаимного исключения при изменении внутреннего пула может быть дорогостоящей.[8]
Конкуренцию также можно уменьшить, разделив пространство строк на несколько пулов, которые можно синхронизировать независимо друг от друга.
Восстановление неиспользованных интернированных строк
Многие реализации интернированных строк не пытаются вернуть (вручную или иным образом) строки, которые больше не используются. Для приложений, в которых количество интернированных строк невелико или фиксировано, или которые недолговечны, потеря системных ресурсов может быть допустимой. Но для систем с длительным сроком эксплуатации, в которых во время выполнения создается большое количество стажеров-подрядчиков, может возникнуть необходимость вернуть неиспользованных стажеров. С этой задачей может справиться уборщик мусора, хотя для правильной работы слабые ссылки для набора стажеров должны храниться в пуле молодых специалистов.
Смотрите также
Примечания
- ^ Сравнение строк может быть остановлено при несовпадении первого символа. Для строгого равенства длины строк также можно сравнить перед обходом строки: но нахождение длины строки с завершающим нулем сам по себе требует обхода строки.
Рекомендации
- ^ "String.Intern Method (String)". Сеть разработчиков Microsoft. Получено 25 марта 2017.
- ^
String.intern ()
- ^ «Глава 15. Выражения». docs.oracle.com. Получено 30 января 2019.
- ^ "lua-users wiki: неизменяемые объекты". lua-users.org. Получено 30 января 2019.
- ^ рпетруша. «Строковый класс (система)». docs.microsoft.com. Получено 30 января 2019.
- ^ «Глава 5. Конверсии и акции». docs.oracle.com. Получено 30 января 2019.
- ^ «Спецификация сериализации объектов Java: 1 - Архитектура системы». docs.oracle.com. Получено 30 января 2019.
- ^ админ (3 сентября 2013). "String.intern в Java 6, 7 и 8 - многопоточный доступ". java-performance.info. Получено 30 января 2019.