Как уменьшить объем памяти в .NET-приложениях с интенсивной интенсивностью?
У меня есть приложение с ~ 1,000,000 строк в памяти по соображениям производительности. Мое приложение потребляет ~ 200 МБ ОЗУ.
Я хочу уменьшить объем памяти, потребляемой строками.
Я знаю, что .NET представляет строки в кодировке UTF-16 (2 байта за char). Большинство строк в моем приложении содержат чистые английские символы, поэтому их хранение в кодировке UTF-8 будет в 2 раза эффективнее, чем UTF-16.
Есть ли способ сохранить строку в памяти в кодировке UTF-8, разрешая стандартные функции строк? (Мои потребности, в том числе в основном IndexOf с StringComparison.OrdinalIgnoreCase).
Ответы
Ответ 1
К сожалению, вы не можете изменить внутреннее представление строки .Net. Я предполагаю, что CLR оптимизирован для многобайтовых строк.
То, с чем вы имеете дело, - это знаменитая парадигма Пространственно-временное компромисс, в котором говорится, что в чтобы получить память, вам придется использовать больше процессора, или вы можете сохранить процессор, используя некоторую память.
Тем не менее, рассмотрим некоторые соображения здесь. Если бы я был вами, как только вы установили, что для вас будет достаточно памяти, попробуйте написать свой собственный "строковый" класс, который использует кодировку ASCII. Этого, вероятно, будет достаточно.
UPDATE:
Подробнее о деньгах, вы должны проверить этот пост, Из памяти и строки", легендой StackOverflow Jon Skeet, которая занимается проблема, с которой вы сталкиваетесь. Извините, я не упомянул об этом сразу, мне потребовалось некоторое время, чтобы найти точный пост от Джона.
Ответ 2
Есть ли способ сохранить строку в памяти в кодировке UTF-8, позволяя стандартным функциям string > ? (Мои потребности, в том числе в основном IndexOf с StringComparison.OrdinalIgnoreCase).
Вы можете хранить в виде байтового массива и предоставлять свою собственную реализацию IndexOf (поскольку преобразование обратно в строку для IndexOf, вероятно, будет огромным успехом). Используйте для этого функции System.Text.Encoding(лучше всего сделать шаг сборки для преобразования в байты, а затем прочитать массивы байтов с диска - только при необходимости вернитесь к строке для отображения).
Вы можете сохранить их в библиотеке C/С++, позволяя использовать одиночные байтовые строки. Вероятно, вы не захотите их маршалировать, но вы можете просто вывести результаты (я предполагаю, что здесь происходит какой-то поиск) без особого эффекта. С++/CLI может сделать это проще (путем записи кода поиска в С++/CLI, но строка "база данных" на С++).
Или вы можете пересмотреть свои первоначальные проблемы с производительностью, которые нуждаются во всех строках в памяти. Встроенная база данных, индексирование и т.д. Могут как ускорить процесс, так и сократить использование памяти - и быть более удобным.
Ответ 3
Что делать, если вы храните его как bytearray? Просто восстановите строку, когда вам нужно выполнить некоторые операции над ней. Я бы сделал класс для настройки и получения строк, которые внутренне сохраняют его как bytearrays.
totearray:
string s = "whatever";
byte[] b = System.Text.Encoding.UTF8.GetBytes(s);
в строку:
string s = System.Text.Encoding.UTF8.GetString(b);
Ответ 4
попробуйте использовать in-memory-DB для "хранения" и SQL для взаимодействия с данными... Например, SQLite может быть развернута как часть вашего приложения (состоит всего из 1-2 DLL, которые могут быть помещены в той же папке, что и ваше приложение)...
Ответ 5
Что делать, если вы создаете свой собственный строковый класс UTF-8 (UTF8String?) и поставьте неявное преобразование в String? Вы будете жертвовать некоторой скоростью ради памяти, но это может быть то, что вы ищете.