我目前正在学习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);
}
答案 0 :(得分:0)
CPU绑定工作(例如解析)的最佳解决方案是启动与计算机中核心数量一样多的线程,少于此并且您没有利用所有核心,超过这个并且过多上下文切换可能会启动并阻碍性能。
基本上,threadnbrs应设置为Environment.ProcessorCount
另外,请考虑使用Parallel类而不是自己创建线程:
Parallel.ForEach(thingsToParse, (somethingToParse) =>
{
var parsed = Parse(somethingToParse);
results.Add(parsed);
});
您必须同意它看起来更干净,更容易维护。 此外,您最好使用ConcurrentBag而不是常规的List +锁,因为ConcurrentBag更适合并发加载,并且可以为您提供更好的性能。
答案 1 :(得分:0)
最后!通过同时启动我的应用程序的多个过程来实现它。
Witch意味着我有10个k元素,我在1000个元素的10个过程中运行。增加进程数量以减少元素数量,它会越来越快! (我目前正在以非常快的Internet速度运行)并拥有三星M.2 960作为存储以及核心I7 Skylake 6核心
答案 2 :(得分:0)
好的,所以我发现&#34; Trying to run multiple HTTP requests in parallel, but being limited by Windows (registry)&#34;它被称为&#34;线程池&#34;我最终决定直接下载XML文件,然后直接解析文档,而不是直接解析网站以获得SQL格式。新的方法工作,我可以在9秒内下载和写入多达10 000 K XML。我试图把它推到150 K(所有网站页面),但现在我得到了一个奇怪的错误,我得到了重复的项目......我将尝试使用正确的方法重写完整的代码,多任务/线程,字典和IEnumerable容器交叉手指在150 k项目上运行而不会丢失正在处理的数据并回发完整代码。