检查在C#中可用内存分配分配、内存

2023-09-03 05:54:07 作者:兴起

我需要在我的应用程序来设置它的可用内存使用量创建一个函数。在应用程序运行时,我想要做的是,它达到设定的内存设置,我将不得不从保存到内存中保存到文件到本地驱动器,以避免应用程序挂起切换。这是一个更好的办法吗?考虑什么东西在内存分配方面这样做时?希望大家明白了:)

i need to create a function in my application to set its available memory usage. What i want to do is when the application is running, and it reaches to the set memory settings, i'll have to switch from saving to the memory to saving to a file to the local drive to avoid application hang. Is this a better way to do? What things to consider when doing this in terms of memory allocation? Hope you understand :)

谢谢

Jepe

推荐答案

您可以粗略估计与的System.Diagnostics.Process 或性能计数器。然而,你也许应该重新考虑这种方法,因为你可能有更好的方法来告诉你是否应该写入内存或磁盘。

You can get rough estimates with System.Diagnostics.Process or with performance counters. However, you probably should rethink this approach as you probably have better ways to tell if you should write to memory or to a disk.

首先,它可能不是总内存使用情况的问题。这个问题听起来就像是生活在一个几,或者甚至一,地点。我会考虑这件事被聪明考虑到您的需求是什么。然后,我会解决这个问题设计的。

First off, it's probably not total memory usage that is the issue. The problem sounds like it lives in a few, or perhaps even one, place. I would consider making that thing smarter by taking into consideration what your needs are. Then I would address the problem with design.

也许你需要每次都保存到磁盘上,而使用缓存代理服务器,使之(使读取是从内存)。也许你需要的的System.IO.Stream 委托给一个的MemoryStream 以predefined能力,直到它的实现得到接近产能,然后切换到的FileStream 。也许这是简单,只要用排队计出负载系统的某一部分,这样的内存永远不会成为一个问题。

Maybe you need to save to disk every time but use a caching proxy to make it (so that reads are from memory). Maybe you need an implementation of System.IO.Stream that delegates to a MemoryStream with predefined capacity until it gets close to that capacity and then switches over to a FileStream. Maybe it's as simple as using queuing to meter out load on a certain part of your system so that memory never becomes an issue.

不知道更多关于你的具体问题,很难确切地告诉你你应该做的。我只能说是一种基于内存的使用情况是predicting行为将导致一些冒险的行为,这将是难以测试的,因此,难以维持。

Without knowing more about your specific problem, it is difficult to tell you exactly what you should do. All I can say is that predicting behavior based on memory usage is going to lead to some dicey behavior that will be difficult to test and, therefore, difficult to maintain.

这是我的两分钱,我想。

That's my two cents, I suppose.

编辑:

添加请求的类。这是没有这样做TDD,但为您提供了解决这个问题的一种方法的想法。

Adding the requested class. This was not done TDD but gives you an idea of one way to solve this problem.

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();
  }
}