我需要在我的应用程序中创建一个函数来设置其可用的内存使用量。我想要做的是当应用程序运行时,它达到设置的内存设置,我将不得不从保存切换到内存到保存到本地驱动器的文件,以避免应用程序挂起。这是一个更好的方法吗?在内存分配方面做什么事情需要考虑?希望你理解:)
谢谢,
Jepe
答案 0 :(得分:3)
您可以使用System.Diagnostics.Process
或性能计数器进行粗略估算。但是,您可能应该重新考虑这种方法,因为您可能有更好的方法来判断您是应该写入内存还是写入磁盘。
首先,问题可能不是总内存使用量。问题听起来像是生活在一些地方,甚至可能是一个地方。我会考虑通过考虑你的需求来使这件事变得更聪明。然后我会解决设计问题。
也许您需要每次都保存到磁盘,但是使用缓存代理来创建它(以便读取来自内存)。也许您需要System.IO.Stream
的实施,该实施委托给具有预定义容量的MemoryStream
,直到它接近该容量,然后切换到FileStream
。也许它就像使用排队来计算系统某个部分的负载一样简单,这样内存永远不会成为问题。
如果不了解您的具体问题,很难准确告诉您应该做些什么。我只能说,根据内存使用情况预测行为会导致一些难以测试的冒险行为,因此难以维护。
我想,这是我的两分钱。
编辑:
添加请求的类。这不是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 :(得分:1)
您不需要这样做:让操作系统自动处理它,它会随着时间的推移而进行多年的性能调整和改进,并且通常会做很多工作。
对于更长的解释,read this来自Varnish网络代理的制造商。
答案 2 :(得分:0)
您可能需要考虑为此应用程序使用memory mapped file。
如果将数据写入内存映射文件,则可以根据需要通过自动分页获得内存访问大部分数据的好处。