Повторное использование строк читать от ввода/вывода


Я работаю на приложение, которое считывает большой объем данных из сети и кладет его в сетку. Я заметил, что я мог бы сэкономить память за счет повторного использования существующих строк, а не всегда используя новые строки, которые оторвались провода. Так вот класс, который я написал для этого. Это просто и это работает. Но мне было интересно, если это имя и, конечно, если код может быть улучшен. Одна вещь, которая мне не нравится, что я храню две ссылки на каждую строку.

public class StringCollection
{
  private Dictionary<string, string> lookup_ = new Dictionary<string, string>();

  public string Reuse(string s)
  {
    if (s == null)
    {
      return null;
    }
    string existing;
    if (lookup_.TryGetValue(s, out existing))
    {
      return existing;
    }
    else
    {
      lookup_.Add(s, s);
      return s;
    }
  }

  public void Clear()
  {
    lookup_.Clear();
  }

  public int Count { get { return lookup_.Count; } }

}


1155
11
задан 19 октября 2011 в 02:10 Источник Поделиться
Комментарии
3 ответа

Вы можете захотеть взглянуть на интернировании строк:


Среда CLR экономит пространство для хранения строк, сохраняя таблице, называемой пул интернирования, которая содержит по одной ссылке на каждый уникальный строковый литерал объявляется или созданный в программе. Следовательно, экземпляр строкового литерала с определенным значением существует только один раз в системе.

В то время как он имеет некоторые памяти-родственные побочные эффекты, можно избежать того, чтобы создать такой словарь и выбросить выделенные строки, чтобы постоянно обновляйте его.

10
ответ дан 19 октября 2011 в 04:10 Источник Поделиться

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

Я использовал этот метод, чтобы решить это:

public class LocalIntern {

private HashSet<string> _lookup = new HashSet<string>();

public string Reuse(string s) {
if (s != null) {
if (_lookup.Contains(s)) {
s = _lookup.Where(i => i == s).First();
} else {
_lookup.Add(s);
}
}
return s;
}

public void Clear() {
_lookup.Clear();
}

public int Count { get { return _lookup.Count; } }

}

Основные функции проверки:

LocalIntern intern = new LocalIntern();

// store a string
string data = "asdf";
intern.Reuse(data);

// create another string instance with the same value
string data2 = String.Concat("as", "df");
// verify that they are in fact separate instances
Debug.Assert(!Object.ReferenceEquals(data, data2));

// look for the string
string d = intern.Reuse(data2);
// verify that the string was replaced
Debug.Assert(Object.ReferenceEquals(data, d));

1
ответ дан 19 октября 2011 в 07:10 Источник Поделиться

Идеальным вариантом здесь будет WeakDictionary (или, еще лучше, вариация WeakHashSet что позволило получить ссылку на сохраненный элемент, который соответствует прилагаемого ключа). Такая структура данных будет гарантировать, что строки были совместно, когда это возможно (поведения, которое могло бы не только уменьшить требования к памяти, но и ускорения сравнения между ними, так как, сравнивая два разных показателя-символьные строки, которые оказались равными займет гораздо больше времени, чем сравнение двух ссылок на одну и ту же строку). Если один использует словарь, который является лучшим из существующих классов для этой цели, это может быть хитрым, чтобы убедиться, что строки вам, как они могут быть полезны, не имея словарь сохранить их даже после того, как они становятся бесполезными (если строковое значение, был использован один раз, прежде чем но все ссылки за пределами словаря были брошенные, строки остаются в словаре мимо очередного ГХ цикла обычно служат никакой цели, и даже если одна и та же последовательность символов получает читать снова, как правило быстрее старую строку испаряться и сохранять новую строку в словарь, чем нужно сравнивать все символы в новую строку с теми, которые в старое и отказываться от нового).

0
ответ дан 17 октября 2012 в 03:10 Источник Поделиться