Comments 9
Иногда бывает полезно реализовывать собственную тематическую таблицу для интернирования строк и юзать какой-нибудь ConcurrentDictionary или массив. Или thread-local.
Например, для хранения строкового представления байтов в проге, если надо выводить много раз строковое представление байтов.
Например, для хранения строкового представления байтов в проге, если надо выводить много раз строковое представление байтов.
Было бы очень любопытно узнать, какой же прирост в производительности дало вам интернирование.
На первый взгляд выглядит так, что вы героически решаете проблемы, которые сами же создали :).
На первый взгляд выглядит так, что вы героически решаете проблемы, которые сами же создали :).
Изначально, как я понимаю, интернирование было использовано, чтобы просто уменьшить расход памяти, без цели увеличения производительности, скорее всего его там и не было. Ради интереса я убирал интернирование и видел, как процесс увеличивался почти в два раза — с 6 ГБ до 12 ГБ.
Частично так и есть — уменьшили расход памяти процессом, но создали несовсем очевидную проблему производительности в сценариях работы в системах с большим колличеством потоков (по типу использования IncrediBuild для расспараллеливания).
На первый взгляд выглядит так, что вы героически решаете проблемы, которые сами же создали :).
Частично так и есть — уменьшили расход памяти процессом, но создали несовсем очевидную проблему производительности в сценариях работы в системах с большим колличеством потоков (по типу использования IncrediBuild для расспараллеливания).
Не совсем по теме. но: недавно велосипедил интернирование через concurrentdictionary. В двух словах — обработка здоровых корпусов текстов (токенизация и т.п), надо было вести статистику по отдельным словам.
В общем, это замедлило чтение раз в 5 (не всю программу, просто чтение), дав при этом экономию памяти раза в 4.
Стоит ли игра свеч? Универсальных ответов, как водится, не бывает.
а не экспериментировали с альтернативами? Например stringpool https://docs.microsoft.com/ru-ru/windows/communitytoolkit/high-performance/stringpool. Или, например, кастомный lockfree пул с неблокирующей записью, основанный на слабых ссылках?
Раз пошла тема про интернирование, вытащу вопрос со SO, который появился у меня недавно. Я баловался со строками и заметил разницу в поведении памяти при интернировании. Если коротко, то генерировал много строк из ограниченного набора символов. В net.core 3.1 размер кучи почему-то не уменьшался после сборки мусора, если количество строк (размер в памяти?) была больше определенного значения.
А .net Framework и 5.0 работали как я предполагал.
Код
class Program
{
public static void Main(string[] args)
{
long memory = GC.GetGCMemoryInfo().HeapSizeBytes;
Console.WriteLine(memory);
Get10MillionStringsInterned();
memory = GC.GetGCMemoryInfo().HeapSizeBytes;
Console.WriteLine(memory);
GC.Collect();
memory = GC.GetGCMemoryInfo().HeapSizeBytes;
Console.WriteLine(memory);
memory = GC.GetTotalMemory(true);
Console.WriteLine(memory);
Console.ReadKey();
}
static void Get10MillionStringsInterned()
{
var chars = new char[] { 'a', 'b', 'c', };
char[] word = new char[4];
Random r = new Random();
string[] strings = new string[10_000_000];
for (int i = 0; i < strings.Length; i++)
{
for (int j = 0; j < word.Length; j++)
{
word[j] = chars[r.Next(chars.Length)];
}
strings[i] = string.Intern(new string(word));
}
Console.WriteLine(strings[r.Next(strings.Length)]);
}
}
Вывод консоли
Разница, если малость прибавить символов в массив chars:
0
aabb
80082696
77312 <-- Heap size
76480
Разница, если малость прибавить символов в массив chars:
0
badb
80092448
80086896 <-- Heap size
86200
А .net Framework и 5.0 работали как я предполагал.
Первое, что надо сделать — это разобраться, что за метрики Вы выводите, и на какие на самом деле надо смотреть.
Рекомендую вот это чтиво: www.apress.com/gp/book/9781484240267
Рекомендую вот это чтиво: www.apress.com/gp/book/9781484240267
Sign up to leave a comment.
Подводные камни в бассейне строк, или ещё один повод подумать перед интернированием экземпляров класса String в C#