【发布时间】:2012-03-27 13:59:54
【问题描述】:
我的 C# 应用程序读取以下结构的 XML 文件。 150mb 的文件里面大约有 250,000 字。
<word>
<name>kick</name>
<id>485</id>
<rels>12:4;4256:3;754:3;1452:2;86:2;125:2;</rels>
</word>
我想将 XML 文件读入字典。这些是我阅读班的一些班员。
private XmlReader Reader;
public string CurrentWordName;
public int CurrentWordId;
public Dictionary<KeyValuePair<int, int>, int> CurrentRelations;
这是我阅读课的主要方法。它只是从文件中读取下一个单词并获取name、id,并将关系存储到字典中。
CurrentWordId = -1;
CurrentWordName = "";
CurrentRelations = new Dictionary<KeyValuePair<int, int>, int>();
while(Reader.Read())
if(Reader.NodeType == XmlNodeType.Element & Reader.Name == "word")
{
while (Reader.Read())
if (Reader.NodeType == XmlNodeType.Element & Reader.Name == "name")
{
XElement Title = XElement.ReadFrom(Reader) as XElement;
CurrentWordName = Title.Value;
break;
}
while (Reader.Read())
if (Reader.NodeType == XmlNodeType.Element & Reader.Name == "id")
{
XElement Identifier = XElement.ReadFrom(Reader) as XElement;
CurrentWordId = Convert.ToInt32(Identifier.Value);
break;
}
while(Reader.Read())
if (Reader.NodeType == XmlNodeType.Element & Reader.Name == "rels")
{
XElement Text = XElement.ReadFrom(Reader) as XElement;
string[] RelationStrings = Text.Value.Split(';');
foreach (string RelationString in RelationStrings)
{
string[] RelationsStringSplit = RelationString.Split(':');
if (RelationsStringSplit.Length == 2)
CurrentRelations.Add(new KeyValuePair<int,int>(CurrentWordId,Convert.ToInt32(RelationsStringSplit[0])), Convert.ToInt32(RelationsStringSplit[1]));
}
break;
}
break;
}
if (CurrentRelations.Count < 1 || CurrentWordId == -1 || CurrentWordName == "")
return false;
else
return true;
我的 Windows 窗体有一个 backgroundWorker 来读取所有单词。
private void bgReader_DoWork(object sender, DoWorkEventArgs e)
{
ReadXML Reader = new ReadXML(tBOpenFile.Text);
Words = new Dictionary<int, string>();
Dictionary<KeyValuePair<int, int>, int> ReadedRelations = new Dictionary<KeyValuePair<int, int>, int>();
// reading
while(Reader.ReadNextWord())
{
Words.Add(Reader.CurrentWordId, Reader.CurrentWordName);
foreach (KeyValuePair<KeyValuePair<int, int>, int> CurrentRelation in Reader.CurrentRelations)
{
ReadedRelations.Add(new KeyValuePair<int, int>(CurrentRelation.Key.Key, CurrentRelation.Key.Value), CurrentRelation.Value);
}
}
通过调试,我注意到应用程序启动非常快,并且随着时间的推移变慢。
- 前 10,000 个单词需要 7 秒
- 前 200,000 个单词 30 分钟
- 前 220,000 个单词 35 分钟
我无法解释这种行为!但我确信 XML 文件中的单词平均大小相同。也许Add()-方法会因字典长度而变慢。
如何加快申请速度?
【问题讨论】:
-
查看 Linq to XML 而不是逐个节点阅读
-
也许使用
Dictionary<int, Dictionary<int, int>>并使用双键索引两次而不是一次索引可能会有所帮助。取决于数据。 -
@Lloyd,这将如何帮助提高性能?
-
@svick 自己试试看
-
@harold:
relation是两个单词之间的连接,其权重是整数。我使用源词的Id和目标词的Id作为key。我认为这是有道理的,不是吗?
标签: c# xml performance dictionary