Почему избыточная память для строк в Delphi?

Вы были почти там. Вам просто нужно было получить доступ к свойству name вашего объекта "s". В этом сценарии я использовал деструктуризацию , чтобы получить быстрый доступ к свойству «name».

const products=[{id:"pdc",code:"123456",name:"pompa"},{id:"kbr",code:"2365",name:"kit kbr"},{id:"boiler",code:"23165",name:"VPB"}];

const res = products.filter(({name})=>name.includes("kbr"));

console.log(res);

10
задан Deduplicator 14 April 2014 в 17:49
поделиться

8 ответов

Вы попросили, чтобы я лично ответил на Ваш вопрос здесь. Я не знаю точную причину, почему Вы видите такое использование верхней памяти, но необходимо помнить, что TStringList делает намного больше, чем просто загрузка файла. Каждый из этих шагов требует памяти, которая может привести к фрагментации памяти. TStringList должен загрузить Ваш файл в память, преобразовать его от Ansi до Unicode, разделить его на одну строку для каждой строки и наполнить те строки в массив, который будет много раз перераспределяться.

Мой вопрос Вам состоит в том, почему Вы используете TStringList? Файл должен действительно храниться в памяти как отдельные строки? Вы собираетесь изменить файл, в оперативной памяти, или просто отобразить части его? Хранение файла в памяти, поскольку один большой блок и сканирование всего этого с регулярными выражениями, которые соответствуют частям, которые Вы хотите, будут большей памятью, эффективной, чем хранение отдельных строк.

Кроме того, целый файл должен быть преобразован в Unicode? В то время как Ваше приложение является Unicode, Вашим файлом является Ansi. Моя общая рекомендация состоит в том, чтобы преобразовать вход Ansi в Unicode как можно скорее, потому что выполнение так сохраняет циклы ЦП. Но когда у Вас есть 320 МБ данных Ansi, которые останутся как данные Ansi, потребление памяти будет узким местом. Попытайтесь сохранить файл как Ansi в памяти и только преобразуйте части, которые Вы будете отображать пользователю как Ansi.

Если файл на 320 МБ не является файлом данных, Вы извлекаете определенную информацию из, а набор данных, который Вы хотите изменить, рассмотреть преобразование его в реляционную базу данных и позволить механизму базы данных взволновать, как управлять огромным набором данных с ограниченной RAM.

10
ответ дан 3 December 2019 в 14:35
поделиться

Что, если Вы сделали свое исходное рекордное использование AnsiString? Это прерывает его в половине сразу? Просто, потому что значения по умолчанию Delphi к UnicodeString не означают, что необходимо использовать его.

Кроме того, если Вы знаете точно длину каждой строки (в символе, или два) затем могло бы быть лучше использовать короткие строки даже и сбрить еще несколько байтов.

Мне любопытно, если мог бы быть лучший способ выполнить то, что Вы пытаетесь сделать. Загрузка 320 МБ текста в память не могла бы быть лучшим решением, даже если можно свалить его, чтобы только потребовать 320 МБ

8
ответ дан 3 December 2019 в 14:35
поделиться

По умолчанию TStringList 2009 Delphi читает файл как ANSI, если нет Порядок байтов Mark для идентификации файла как что-то еще, или если Вы обеспечиваете кодирование дополнительным вторым параметром LoadFromFile.

Таким образом, если Вы видите, что TStringList поднимает больше памяти, чем Вы думаете, затем что-то еще продолжается.

4
ответ дан 3 December 2019 в 14:35
поделиться

Вы случайно компилируете программу с источниками FastMM из SourceForge и с определенным FullDebugMode? В этом случае FastMM действительно не выпускает неиспользованные блоки памяти, которые объяснили бы проблему.

3
ответ дан 3 December 2019 в 14:35
поделиться

Я использующий Delphi 2009 и файл являются ANSI, но преобразовываются в Unicode после чтения, так справедливо можно сказать, что текст, однажды преобразованный, составляет 48 МБ в размере.

Извините, но я не понимаю это вообще. Если у Вас есть потребность в Вашей программе, чтобы быть Unicode, конечно, файл, являющийся "ANSI" (это должно иметь некоторый набор символов, как WIN1252 или ISO8859_1) не правильная вещь. Я сначала преобразовал бы его, чтобы быть UTF8. Если файл не будет содержать символов> = 128, то он не изменит вещь (это даже будет тот же размер), но Вы подготовлены к будущему.

Теперь можно загрузить его в строки UTF8, которые не удвоят потребление памяти. On-the-fly-conversion нескольких строк, которые могут быть видимы на экране одновременно к строке Unicode Delphi, будет медленнее, но, учитывая меньший объем потребляемой памяти Ваша программа будет работать намного лучше в системах с небольшой (свободной) памятью.

Теперь, если Ваша программа все еще использует слишком много памяти с TStringList, можно всегда использовать TStrings или даже IStrings в Вас программа, и писать класс, который реализует IStrings или наследовал TStrings и не сохраняет все строки в памяти. Некоторые идеи, которые приходят на ум:

  1. Считайте файл в TMemoryStream и поддержите массив указателей на первые символы строк. Возврат строки легок затем, только необходимо возвратить соответствующую строку между запуском строки и запуском следующего с CR и разделенным NL.

  2. Если это все еще использует слишком много памяти, замените TMemoryStream TFileStream и не поддерживайте массив символьных указателей, но массив файловых смещений для строки запускается.

  3. Вы могли также использовать Windows API functions для файлов с отображенной памятью. Это позволяет Вам работать с адресами памяти вместо файловых смещений, но не использует так много памяти как первую идею.

6
ответ дан 3 December 2019 в 14:35
поделиться

Вы полагаетесь на Windows, чтобы сказать Вам, сколько памяти программа использует? Это известно за преувеличение памяти, используемой приложением Delphi.

Я действительно вижу много использования дополнительной памяти в Вашем коде, все же.

Ваша рекордная структура составляет 20 байтов - если существует одна такая запись на строку, Вы смотрите на большее количество данных для записей, чем для текста.

Кроме того, строка имеет свойственные 4 байта наверху - еще 25%.

Я полагаю, что существует определенное количество гранулярности выделения в обработке "кучи" Delphi, но я не вспоминаю то, что это в настоящее время. Даже на уровне 8 байтов (два указателя для связанного списка свободных блоков) Вы смотрите еще на 25%.

Обратите внимание, что мы уже более чем до 150%-го увеличения.

1
ответ дан 3 December 2019 в 14:35
поделиться

Часть его могла быть алгоритмом назначения блока. Когда Ваш список растет, он начинает увеличивать объем памяти, выделенный в каждом блоке. Я не посмотрел на него в долгое время, но я полагаю, что это идет, что-то как удвоение суммы последних выделило каждый раз, когда это исчерпывает память. Когда Вы начинаете иметь дело со списками, настолько большими, Ваши выделения также намного больше, чем Вам в конечном счете нужно.

РЕДАКТИРОВАНИЕ - Как lkessler указанный, это увеличение составляет на самом деле только 25%, но это все еще нужно рассмотреть как часть проблемы. если Ваш только вне переломного момента, мог бы быть огромный блок памяти, выделенной списку, который не используется.

1
ответ дан 3 December 2019 в 14:35
поделиться

Почему Вы загружаете тот объем данных в TStringList? Сам список будет иметь немного служебными. Возможно, TTextReader мог помочь Вам.

0
ответ дан 3 December 2019 в 14:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: