Проверка доступной памяти в C # - PullRequest
3 голосов
/ 22 марта 2010

Мне нужно создать функцию в моем приложении, чтобы установить доступное использование памяти. Что я хочу сделать, это когда приложение работает, и оно достигает установленных настроек памяти, мне придется переключиться с сохранения в память на сохранение в файл на локальный диск, чтобы избежать зависания приложения. Это лучший способ сделать? Что нужно учитывать при распределении памяти? Надеюсь, вы понимаете:)

Спасибо

Jepe

Ответы [ 3 ]

3 голосов
/ 22 марта 2010

Вы можете получить приблизительные оценки с помощью System.Diagnostics.Process или счетчиков производительности. Однако вам, вероятно, следует переосмыслить этот подход, поскольку у вас, вероятно, есть лучшие способы определить, следует ли записывать в память или на диск.

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

Может быть, вам нужно каждый раз сохранять на диск, но для этого используйте кеширующий прокси (чтобы чтение производилось из памяти). Может быть, вам нужна реализация System.IO.Stream, которая делегирует MemoryStream с предопределенной емкостью, пока она не приблизится к этой емкости, а затем переключится на FileStream. Может быть, это так же просто, как использование очередей для измерения нагрузки на определенную часть вашей системы, чтобы память никогда не становилась проблемой.

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

Полагаю, это мои два цента.


Edit:

Добавление запрошенного класса. Это не было сделано TDD, но дает вам представление об одном способе решения этой проблемы.

class UpgradingStream : Stream
{
  // state pattern lives in the problem...
  private abstract class InternalState
  {
    private readonly Stream _underlyingStream;

    protected InternalState(Stream underlyingStream)
    {
      _underlyingStream = underlyingStream;
    }

    internal Stream GetUnderlyingStream()
    {
      return _underlyingStream;
    }

    // template method lives in the implementation of this state pattern
    internal InternalState Seek(long offset, SeekOrigin origin, out long result)
    {
      result = _underlyingStream.Seek(offset, origin);

      return GetNextState();
    }

    internal InternalState SetPosition(long value)
    {
      _underlyingStream.Position = value;

      return GetNextState();
    }

    internal InternalState SetLength(long value)
    {
      _underlyingStream.SetLength(value);

      return GetNextState();
    }

    internal InternalState Write(byte[] buffer, int offset, int count)
    {
      _underlyingStream.Write(buffer, offset, count);

      return GetNextState();
    }

    protected abstract InternalState GetNextState();
  }

  private class InMemoryOnly : InternalState
  {
    private readonly Func<Stream> _getUpgradedStream;
    private readonly int _threshold;

    private InMemoryOnly(int threshold, Func<Stream> getUpgradedStream)
      : base(new MemoryStream(threshold))
    {
      _threshold = threshold;
      _getUpgradedStream = getUpgradedStream;
    }

    internal static InternalState GetInstance(int threshold, Func<Stream> getUpgradedStream)
    {
      return new InMemoryOnly(threshold, getUpgradedStream);
    }

    protected override InternalState GetNextState()
    {
      if (GetUnderlyingStream().Length > _threshold)
      {
        var newStream = _getUpgradedStream();

        CopyStream(newStream);

        return Unrestricted.GetInstance(newStream);
      }

      return this;
    }

    private void CopyStream(Stream newStream)
    {
      var originalPosition = GetUnderlyingStream().Position;

      GetUnderlyingStream().Position = 0;

      int bytesRead;

      var buffer = new byte[65536];

      while ((bytesRead = GetUnderlyingStream().Read(buffer, 0, buffer.Length)) != 0)
      {
        newStream.Write(buffer, 0, bytesRead);
      }

      newStream.Position = originalPosition;
    }
  }

  private class Unrestricted : InternalState
  {
    private Unrestricted(Stream underlyingStream)
      : base(underlyingStream)
    {
    }

    internal static Unrestricted GetInstance(Stream stream)
    {
      return new Unrestricted(stream);
    }

    protected override InternalState GetNextState()
    {
      // state never changes once we are in a file or whatever
      return this;
    }
  }

  private InternalState _state;

  private UpgradingStream(int threshold, Func<Stream> getMoreEfficientStream)
  {
    _state = InMemoryOnly.GetInstance(threshold, getMoreEfficientStream);
  }

  internal static Stream GetInstance(int threshold, Func<Stream> getMoreEfficientStream)
  {
    return new UpgradingStream(threshold, getMoreEfficientStream);
  }

  public override bool CanRead
  {
    get { return _state.GetUnderlyingStream().CanRead; }
  }

  public override bool CanSeek
  {
    get { return _state.GetUnderlyingStream().CanSeek; }
  }

  public override bool CanWrite
  {
    get { return _state.GetUnderlyingStream().CanWrite; }
  }

  public override void Flush()
  {
    _state.GetUnderlyingStream().Flush();
  }

  public override long Length
  {
    get { return _state.GetUnderlyingStream().Length; }
  }

  public override long Position
  {
    get
    {
      return _state.GetUnderlyingStream().Position;
    }
    set
    {
      _state = _state.SetPosition(value);
    }
  }

  public override int Read(byte[] buffer, int offset, int count)
  {
    return _state.GetUnderlyingStream().Read(buffer, offset, count);
  }

  public override long Seek(long offset, SeekOrigin origin)
  {
    long result;

    _state = _state.Seek(offset, origin, out result);

    return result;
  }

  public override void SetLength(long value)
  {
    _state = _state.SetLength(value);
  }

  public override void Write(byte[] buffer, int offset, int count)
  {
    _state = _state.Write(buffer, offset, count);
  }

  public override void Close()
  {
    _state.GetUnderlyingStream().Close();
  }
}
1 голос
/ 22 марта 2010

Вам не нужно этого делать: пусть операционная система автоматически справится с этим, со временем у нее появятся годами улучшения производительности и улучшения, и, как правило, она сделает большую работу.

Дольшеобъяснение, прочитайте это от создателя веб-прокси Varnish.

0 голосов
/ 22 марта 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...