优化输出字典
本文关键字:字典 输出 优化 | 更新日期: 2023-09-27 18:29:13
我有4个字典,其中包含800k个200到6000个字符的字符串。当我把它加载到内存中时,它占用了大约11吉格的内存。我需要2分钟来解析数据,2分钟来输出数据。有没有比我下面使用的更快的数据输出?我只得到每秒20-31 MB的磁盘IO,我知道硬盘驱动器可以做800ish
var hash1 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
var hash2 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
var hash3 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
var hash4 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
....
foreach (var me in mswithfilenames)
{
filename = me.Key.ToString();
string filenamef = filename + "index1";
string filenameq = filename + "index2";
string filenamefq = filename + "index3";
string filenameqq = filename + "index4";
StreamWriter sw = File.AppendText(filenamef);
StreamWriter sw2 = File.AppendText(filenameq);
StreamWriter swq = File.AppendText(filenamefq);
StreamWriter sw2q = File.AppendText(filenameqq);
for (i = 0; i <= totalinhash; i++)
{
if (hashs1[i].ContainsKey(filenamef))
{
sw.Write(hashs1[i][filenamef]);
}
if (hashs2[i].ContainsKey(filenameq))
{
sw2.Write(hashs2[i][filenameq]);
}
if (hashs3[i].ContainsKey(filenamefastaq))
{
swq.Write(hash4[i][filenamefastaq]);
}
if (hash4[i].ContainsKey(filenameqq))
{
sw2q.Write(hash4[i][filenameqq]);
}
}
sw.Close();
sw2.Close();
sw3.Close();
sw4.Close();
swq.Close();
sw2q.Close();
}
你测量了什么吗?听起来您有大量的数据要读和写,所以第一步是为您的磁盘子系统建立绝对的基线,以确定它读/写那么多数据的速度。简单地读取文件,然后向新文件写入您期望的大致数据量,这将显示您在优化它方面可以走多远
您可能会认为您的代码本身不会花费太多的阅读/编写时间。
最昂贵的部分是I/O。这个循环:
for (i = 0; i <= totalinhash; i++)
{
if (hashs1[i].ContainsKey(filenamef))
{
sw.Write(hashs1[i][filenamef]);
}
if (hashs2[i].ContainsKey(filenameq))
{
sw2.Write(hashs2[i][filenameq]);
}
...
}
在不同的文件之间交替。这可能会导致一些额外的头部移动,并产生碎片文件(减缓未来对这些文件的操作)。
我会使用:
for (i = 0; i <= totalinhash; i++)
{
if (hashs1[i].ContainsKey(filenamef))
{
sw.Write(hashs1[i][filenamef]);
}
}
for (i = 0; i <= totalinhash; i++)
{
if (hashs2[i].ContainsKey(filenameq))
{
sw2.Write(hashs2[i][filenameq]);
}
}
...
但你当然应该衡量一下。例如,它在固态硬盘上不会有太大区别,只在机械磁盘上。
您能拥有一个Dictionary<int, Dictionary<string, myCustomDataHolder>>
而不是四个独立的并行Dictionary<int, Dictionary<string, string>
吗?它不仅应该大大减少占用的空间,而且意味着1/4的字典查找。
考虑到你的问题,词典是否完全平行还不太清楚,但对我来说似乎已经足够了
我想添加
if (hashs1[i].ContainsKey(filenamef))
{
sw.Write(hashs1[i][filenamef]);
}
进行2次哈希表访问。一个用于包含键,另一个用于实际访问。许多字典访问可以相加,因此可以使用dictionary tryGetValue方法将这些访问减半。这将把这两个调用合并为一个调用。我可以解释这是如何工作的,但这比我能做的更好:http://www.dotnetperls.com/trygetvalue