Streaming/Tailing 使用 C# 和 SSH.NET 通过 SSH 的数据泄漏内存
Streaming/Tailing data over SSH using C# with SSH.NET leaks memory
我正在尝试使用 C# 通过 SSH 跟踪文件。这个文件从一开始就被读取,然后在保持 SSH 连接的同时继续被监视几个小时。我正在使用 SSH.NET 库来为 SSH 提供功能。文件大小最大可达 ~2GB。当前的实现是可行的,但内存使用情况非常糟糕。
测试: 为了测试此功能,我使用 Visual Studio 2012,针对 .NET Framework 4.5,使用以下代码创建一个小型控制台应用程序。我正在跟踪一个大约 127MB 的静态文件。
问题: 从功能上讲,这工作正常,但内存使用情况非常糟糕。应用程序将在调用 shellStream.WriteLine
之前使用 ~7MB,然后使用 ~144MB 快速增加并稳定下来(当所有当前文件内容已从流中读取时稳定)。
下面是我正在尝试使用的代码。
private SshClient sshClient;
private ShellStream shellStream;
//Command being executed to tail a file.
private readonly string command = "tail -f -n+1 {0}";
//EventHandler that is called when new data is received.
public EventHandler<string> DataReceived;
public void TailFile(string server, int port, string userName, string password, string file)
{
sshClient = new SshClient(server, port, userName, password);
sshClient.Connect();
shellStream = sshClient.CreateShellStream("Tail", 0, 0, 0, 0, 1024);
shellStream.DataReceived += (sender, dataEvent) =>
{
if (DataReceived != null)
{
DataReceived(this, Encoding.Default.GetString(dataEvent.Data));
}
};
shellStream.WriteLine(string.Format(command, file));
}
是否缺少一些东西来阻止内存增加,或者任何其他可以实现相同目标的解决方案?
您不使用流中的数据,因此它会累积。
参见how the ShellStream.DataReceived
event is implemented:
private void Channel_DataReceived(object sender, ChannelDataEventArgs e)
{
lock (this._incoming)
{
// this is where the memory "leaks" as the _incoming is never consumed
foreach (var b in e.Data)
this._incoming.Enqueue(b);
}
if (_dataReceived != null)
_dataReceived.Set();
this.OnDataReceived(e.Data);
}
不使用 ShellDataEventArgs.Data
,而是使用 ShellStream.Read
:
shellStream.DataReceived += (sender, dataEvent) =>
{
if (DataReceived != null)
{
DataReceived(this, shellStream.Read());
}
};
我正在尝试使用 C# 通过 SSH 跟踪文件。这个文件从一开始就被读取,然后在保持 SSH 连接的同时继续被监视几个小时。我正在使用 SSH.NET 库来为 SSH 提供功能。文件大小最大可达 ~2GB。当前的实现是可行的,但内存使用情况非常糟糕。
测试: 为了测试此功能,我使用 Visual Studio 2012,针对 .NET Framework 4.5,使用以下代码创建一个小型控制台应用程序。我正在跟踪一个大约 127MB 的静态文件。
问题: 从功能上讲,这工作正常,但内存使用情况非常糟糕。应用程序将在调用 shellStream.WriteLine
之前使用 ~7MB,然后使用 ~144MB 快速增加并稳定下来(当所有当前文件内容已从流中读取时稳定)。
下面是我正在尝试使用的代码。
private SshClient sshClient;
private ShellStream shellStream;
//Command being executed to tail a file.
private readonly string command = "tail -f -n+1 {0}";
//EventHandler that is called when new data is received.
public EventHandler<string> DataReceived;
public void TailFile(string server, int port, string userName, string password, string file)
{
sshClient = new SshClient(server, port, userName, password);
sshClient.Connect();
shellStream = sshClient.CreateShellStream("Tail", 0, 0, 0, 0, 1024);
shellStream.DataReceived += (sender, dataEvent) =>
{
if (DataReceived != null)
{
DataReceived(this, Encoding.Default.GetString(dataEvent.Data));
}
};
shellStream.WriteLine(string.Format(command, file));
}
是否缺少一些东西来阻止内存增加,或者任何其他可以实现相同目标的解决方案?
您不使用流中的数据,因此它会累积。
参见how the ShellStream.DataReceived
event is implemented:
private void Channel_DataReceived(object sender, ChannelDataEventArgs e)
{
lock (this._incoming)
{
// this is where the memory "leaks" as the _incoming is never consumed
foreach (var b in e.Data)
this._incoming.Enqueue(b);
}
if (_dataReceived != null)
_dataReceived.Set();
this.OnDataReceived(e.Data);
}
不使用 ShellDataEventArgs.Data
,而是使用 ShellStream.Read
:
shellStream.DataReceived += (sender, dataEvent) =>
{
if (DataReceived != null)
{
DataReceived(this, shellStream.Read());
}
};