C# 大数据量代码性能优化

天罡gg 2011-07-15 10:04:21
直接上代码,现在用时大约在2分钟以上

static void ParseTxt()
{
/*
* a.txt 数据
* 操作系统确定程序是否成功执行完毕
* 函数体函数定义的最后部分
* 程序编写完后需要进行编译
* 标准库定义了 4 个 IO 对象
* 系统将这些对象与执行程序的窗口联系起来
* 编译器要使用库
*
* b.txt 数据
* 讲解
* 函数部分
* 程序编译
* 标准库对象
* 系统窗口
* 编译器讲解
*
* 解析后新生成的newa.txt应该是这样的
* 操作系统确定程序是否成功执行完毕 【未找到】
* 函数体函数定义的最后部分 体函数定义的最后部分
* 程序编写完后需要进行编译 编写完后需要进行编译
* 标准库定义了 4 个 IO 对象 定义了 4 个 IO 对象
* 系统将这些对象与执行程序的窗口联系起来 将这些对象与执行程序的窗口联系起来
* 编译器要使用库 要使用库
*/
string aPath = "a.txt";//16W+数据
string bPath = "b.txt";//2000+数据
string newaPath = "newa.txt";//与a.txt数据量相同
string[] arrA = File.ReadAllLines(aPath);
string[] arrB = File.ReadAllLines(bPath);
StringBuilder sb = new StringBuilder();
bool isHave = false;
string titleTrim = string.Empty;
string subTitle = string.Empty;
char[] sChar = new char[] { ' ', '[', '[', '(', '『', '(', '{', '【' };
char[] eChar = new char[] { ' ', ']', '+', '/', '』', ']', ')', '-', '}', '】' };
foreach (string title in arrA)
{
titleTrim = title.TrimStart(sChar);
for (int i = 2; i < titleTrim.Length; i++)
{
isHave = false;
subTitle = titleTrim.Substring(0, i);
foreach (string b in arrB)
{
if (b.Contains(subTitle))
{
isHave = true;
break;
}
}
if (!isHave)
{
if (i == 2)
{
sb.Append(title + "\t【未找到】\r\n");
}
else
{
sb.Append(title + "\t" + titleTrim.Substring(i - 1, titleTrim.Length - i + 1).TrimStart(eChar) + "\r\n");
}
break;
}
}
}
File.WriteAllText(newaPath, sb.ToString());
}
...全文
1476 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
天涯倦客 2011-07-19
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 scm_2008 的回复:]

又修改了下,在我这双核上只能跑到20S左右,在I7上只要2S左右了,差距太大了。代码有点乱
C# code

class Test
{
private delegate string FuncHandle(string[] arrA, string b);
//调用方法
public void ParseTxt()
{
……
[/Quote]

读盘速度 用不用多线程都一样的。。
先一次txt映射到内存在处理。。
huzanqiang88 2011-07-19
  • 打赏
  • 举报
回复
string[] arrA = File.ReadAllLines(aPath);
string[] arrB = File.ReadAllLines(bPath);
不用数组,这个查找效率O(n),改为HashSet存储字符串值再查找比较,内部采用hash算法比较时间为O(1),改为这两个数据结构,应该会快蛮多。你测试看看
随枫而来 2011-07-19
  • 打赏
  • 举报
回复
学习!
ohkuy 2011-07-15
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 scm_2008 的回复:]
现在要30秒+了
正则表达式不知道写合适,就想着怎么优化(好昵称都被占用了) 说的那段代码,我是这么优化的,就是把arrB换成了string b

[/Quote]
感觉还是太长了。。。
你可以看一下notepad这个软件,开源的,
它打开8M左右的txt文件只要2秒左右,
用的是多线程,还有内存映射文件技术,
你用上了估计能减少到5秒以内
mjp1234airen4385 2011-07-15
  • 打赏
  • 举报
回复
这种情况尤其是在多核cpu的服务器上,效果会比较明显。
mjp1234airen4385 2011-07-15
  • 打赏
  • 举报
回复
恩,使用多线程的话,应该还会下降的。
mjp1234airen4385 2011-07-15
  • 打赏
  • 举报
回复
就你目前的这个方法,如果想提高效率,可以使用多线程。
string[] arrA = File.ReadAllLines(aPath);

这个数据比较大(16W+),建立10个线程,
每一个线程读取16000的数据,每个线程里的arrB(2000)都是全部数据,
这样处理的话,初步估计在30秒内可以完成
天罡gg 2011-07-15
  • 打赏
  • 举报
回复
现在要30秒+了
正则表达式不知道写合适,就想着怎么优化(好昵称都被占用了) 说的那段代码,我是这么优化的,就是把arrB换成了string b

static void ParseTxt()
{
string aPath = "a.txt";//16W+数据
string bPath = "b.txt";//2000+数据
string newaPath = "newa.txt";//与a.txt数据量相同
string[] arrA = File.ReadAllLines(aPath);
string b = File.ReadAllText(bPath);
StringBuilder sb = new StringBuilder();
bool isHave = false;
string titleTrim = string.Empty;
string subTitle = string.Empty;
char[] sChar = new char[] { ' ', '[', '[', '(', '『', '(', '{', '【' };
char[] eChar = new char[] { ' ', ']', '+', '/', '』', ']', ')', '-', '}', '】' };
foreach (string title in arrA)
{
titleTrim = title.TrimStart(sChar);
for (int i = 2; i < titleTrim.Length; i++)
{
isHave = false;
subTitle = titleTrim.Substring(0, i);
if (b.Contains(subTitle))
{
isHave = true;
}
if (!isHave)
{
if (i == 2)
{
sb.Append(title + "\t【未找到】\r\n");
}
else
{
sb.Append(title + "\t" + titleTrim.Substring(i - 1, titleTrim.Length - i + 1).TrimStart(eChar) + "\r\n");
}
break;
}
}
}
File.WriteAllText(newaPath, sb.ToString());
}

天罡gg 2011-07-15
  • 打赏
  • 举报
回复
谢谢(老毕) 和(好昵称都被占用了) 给我提供了一个新思路,我用正则表达式试试
天罡gg 2011-07-15
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 colinmelody 的回复:]
毕竟数据量在那呢,估计速度再快也快不起来。

不过你可不可以试着分批操作呢?
将数据量较大的txt分成多个操作。
[/Quote]

我想过把据量较大的txt分成10个,然后分10条线程操作,理论上会快10倍?
那样的话多线程要传参并且有返回值,不太好弄啊。
ohkuy 2011-07-15
  • 打赏
  • 举报
回复
要用正则表达式来做
ohkuy 2011-07-15
  • 打赏
  • 举报
回复
我觉得是:
subTitle = titleTrim.Substring(0, i);
foreach (string b in arrB)
{
if (b.Contains(subTitle))
{
isHave = true;
break;
}
}
这里最浪费时间,要优化
老毕 2011-07-15
  • 打赏
  • 举报
回复
大致看了一下代码,似乎是在B中查找A中的串,然后把匹配的结果存入C。期间要把A的左右括号去掉。

我在想,利用正则表达式Regex.Replace(),是不是会好一些?这比你反复地取用同一个串,在B中进行遍历应该会效率许多。

其中每次查找的Regex,根据A中单词的不同进行动态构造,然后在B中进行Replace。具体的我还没细想。
ColinMelody 2011-07-15
  • 打赏
  • 举报
回复
毕竟数据量在那呢,估计速度再快也快不起来。

不过你可不可以试着分批操作呢?
将数据量较大的txt分成多个操作。
天罡gg 2011-07-15
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 ohkuy 的回复:]
用Linq试了没?
多长时间?
[/Quote]

Linq没试,不会Linq,.net2.0下
或者用C++是否会提高效率?
ohkuy 2011-07-15
  • 打赏
  • 举报
回复
用Linq试了没?
多长时间?
天罡gg 2011-07-15
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 bdmh 的回复:]
File.WriteAllText(newaPath, sb.ToString());
好像在循环内部,你考虑把它移到外部行不行,这个应该很占时间的,IO操纵很费时
[/Quote]

这行代码是在方法的最后,是在循环外
我用时间测试就是循环里的操作最费时
ohkuy 2011-07-15
  • 打赏
  • 举报
回复
先点位,
再研究
bdmh 2011-07-15
  • 打赏
  • 举报
回复
File.WriteAllText(newaPath, sb.ToString());
好像在循环内部,你考虑把它移到外部行不行,这个应该很占时间的,IO操纵很费时
evil_ghost 2011-07-15
  • 打赏
  • 举报
回复
占位,观
加载更多回复(2)

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧