【发布时间】:2017-01-29 19:18:29
【问题描述】:
我目前正在学习 C#,过去两天我一直在研究 XML 解析器。它实际上工作正常我的问题是解析超过 10k 页所需的时间。这是我的代码。
public static void startParse(int id_min, int id_max, int numberofthreads)
{
int start;
int end;
int part;
int threadnbrs;
threadnbrs = numberofthreads;
List<Thread> workerThreads;
List<string> results;
part = (id_max - id_min) / threadnbrs;
start = id_min;
end = 0;
workerThreads = new List<Thread>();
results = new List<string>();
for (int i = 0; i < threadnbrs; i++)
{
if (i != 0)
start = end + 1;
end = start + (part);
if (i == (threadnbrs - 1))
end = id_max;
int _i = i;
int _start = start;
int _end = end;
Thread t = new Thread(() =>
{
Console.WriteLine("i = " + _i);
Console.WriteLine("start =" + _start);
Console.WriteLine("end =" + _end + "\r\n");
string parse = new ParseWH().parse(_start, _end);
lock (results)
{
results.Add(parse);
}
});
workerThreads.Add(t);
t.Start();
}
foreach (Thread thread in workerThreads)
thread.Join();
File.WriteAllText(".\\result.txt", String.Join("", results));
Console.Beep();
}
我实际上在做的是在不同的线程中拆分一系列需要解析的元素,以便每个线程处理 X 元素。
每 100 个元素大约需要 20 秒。 但是我花了 17 分钟来解析 10 0000 个元素。
我需要的是每个线程同时在这 10 000 个元素中的 100 个上工作,因此可以在 20 秒内完成。有解决办法吗?
解析代码:
public string parse(int id_min, int id_max)
{
XmlDocument xml;
WebClient user;
XmlElement element;
XmlNodeList nodes;
string result;
string address;
int i;
//Console.WriteLine(id_min);
//Console.WriteLine(id_max);
i = id_min;
result = "";
xml = new XmlDocument();
while (i <= id_max)
{
user = new WebClient();
// user.Headers.Add("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");
user.Encoding = UTF8Encoding.UTF8;
address = "http://fr.wowhead.com/item=" + i + "?xml";
if (address != null)
xml.LoadXml(user.DownloadString(new Uri(address)));
element = xml.DocumentElement;
nodes = element.SelectNodes("/wowhead");
if (xml.SelectSingleNode("/wowhead/error") != null)
{
Console.WriteLine("error " + i);
i++;
continue;
}
result += "INSERT INTO item_wh (entry, class, subclass, displayId, ,quality, name, level) VALUES (";
foreach (XmlNode node in nodes)
{
// entry
result += node["item"].Attributes["id"].InnerText;
result += ", ";
// class
result += node["item"]["class"].Attributes["id"].InnerText;
result += ", ";
// subclass
result += node["item"]["subclass"].Attributes["id"].InnerText;
result += ", ";
// displayId
result += node["item"]["icon"].Attributes["displayId"].InnerText;
result += ", ";
// quality
result += node["item"]["quality"].Attributes["id"].InnerText;
result += ", \"";
// name
result += node["item"]["name"].InnerText;
result += "\", ";
// level
result += node["item"]["level"].InnerText;
result += ");";
// bakcline
result += "\r\n";
}
i++;
}
return (result);
}
【问题讨论】:
-
所以解析 100 个元素需要 20 秒...您如何期望获得 1000 倍的吞吐量,在相同的时间内解析 1000 倍的元素?线程不仅神奇地为您提供免费的计算能力或网络带宽(我们不知道这 100 个元素需要花费什么时间)。
-
@JonSkeet - 但是添加线程将允许它们访问多个 CPU 内核,而线性执行最多只能使用一个内核。在多核机器上,线程将把更多的核心加入到程序中。完全同意这里的问题是解析 100 个项目所花费的时间非常多。
-
@PhillipH 在一台典型的现代计算机上,比如说,8 核,你最多可以得到 7-8 倍的加速,而不是 1000 倍。附带说明一下,其他事情很快就会成为瓶颈(如网络或磁盘 IO)。您最好对代码进行分析以找出为什么您的解析需要这么长时间并改正它。
-
@PhillipH:不,它没有提供“无魔法的计算能力”——它可以让你更好地利用现有的能力。 7 或 8 的因数是合理的 - 1000 的因数是完全不合理的,基本上是对魔术的期望。
-
@PhilippeMakzoume 首先,该网站是否可以像这样受到重创?虽然可以在 20 秒内向网络服务器发送 10,000 个请求,但大多数网站管理员不会因此而喜欢你。如果它是您的服务器,我强烈建议您添加一个端点,该端点在单个请求中响应所有项目。如果您不能使用这样的页面并且服务器可以接受请求,那么请改用异步 HTTP。
标签: c# xml-parsing multitasking