首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

由前帖挑动:代码可读性与性能的选择

2012-10-14 
由前帖引发:代码可读性与性能的选择前一帖子参考:for的效率测试和结果,分享一下里面很多同学都说,我提的那

由前帖引发:代码可读性与性能的选择
前一帖子参考:for的效率测试和结果,分享一下
里面很多同学都说,我提的那点性能,影响不大,不建议改进,而建议使用可读性好的代码写法,这里我分享一个我的实际经验。

我现在负责一个日pv访问过千万的搜索接口,数据大约几十万条
因为SqlServer的LIKE效率太低,而SqlServer的全文检索又不尽人意,于是方案定为把这些记录全部加载到内存,代码一开始如下:
Dictionary<string, int> name_id = 加载几十万条 标题_id 的记录;
string key = "要搜索的关键词";
StringBuilder sb = new StringBuilder(10000);
foreach (KeyValuePair<string, int> pair in name_id)
{
  if (pair.Key.IndexOf(key) >= 0)
  sb.AppendFormat("{0},", pair.Value);
}
return sb.ToString()

这段代码上线后,执行效率不是很好,后来通过性能工具测试,发现问题比较大的一个地方,就是
IndexOf(key)和AppendFormat("{0},", pair.Value)占用了大约30%的执行时间
因为访问量大,加上每次访问都要循环执行IndexOf(key)几十万次
后面改成了:
foreach (KeyValuePair<string, int> pair in name_id)
{
  if (pair.Key.IndexOf(key, StringComparison.Ordinal) >= 0)
  sb.AppendFormat("{0},", pair.Value.ToString());
}

由这个例子,虽然每次的IndexOf(key)或AppendFormat("{0},", pair.Value),影响的效率可能是微秒计,但是如果执行次数多了,效率也是很可观的,比如上述例子就占了1/3的执行时间

想起了一句话:勿以善而不为。不要以为性能改善极其微小,就按自己的想法去做

[解决办法]
你还来啊

[解决办法]
真那么在乎性能的话就该直接用哈希表,或者专门写个key的搜索算法。
[解决办法]
pair.Key.IndexOf(key) 看看这个是怎么实现的,是否能够手写优化

[解决办法]
俺写的代码可读性与性能都很好。

[解决办法]
我认为举得例子非常不好。这个应用需求其实应该使用搜索引擎实现,而不是这样的笨办法。
这种情况下,你无论怎么调优,怎么优化代码,搞各种技巧,能够加百分之几就非常不错了,而付出的代价则很大。不容易维护、BUG、开发调试周期长、人员变动没人敢维护等等。还不如干脆加钱买新服务器呢。
但是如果使用了合理的解决方案、效率更高的算法,则可以一下子提高几十几百倍的效率。
[解决办法]
细节是需要关注的,for循环的写法大多数写的不规范,不过影响不大是因为数据量少,js里面就有个习惯要把长度给预存起来。
搜索引擎的查找原理也是索引起来,具体情况不知道呵呵
[解决办法]
支持············
[解决办法]

探讨

这种设计,要是被sp1234看到
肯定又是一顿喷

[解决办法]
探讨

恩,通过IL查看明白了,还是基础知识不牢固

C# code
int i = 123;
Console.WriteLine((object)i.ToString());



Assembly code
.method private hidebysig static void Main(string[] args) cil managed
{
.e……

[解决办法]
性能的问题根本就不是问题。可读性的问题,才是大问题。
[解决办法]
。。。http://community.csdn.net/help/GetUsablePoint.htm
[解决办法]
代码应该先保证可读性。
关于性能,只有通过测试,某段确实有性能问题,才会牺牲可读性换取性能。
不要一开始就纠结于性能。
[解决办法]
不要函数调用 所有东西写在一起,性能最好
[解决办法]
探讨
这种设计,要是被sp1234看到
肯定又是一顿喷

[解决办法]
忍不住给楼主提个方案

思路:通过建立单词索引,缩小搜索范围
算法:
S1.对标题分词,建立 关键词 到 标题集合 的映射(剔除那些集合过大的单词)
S2.对用户输入分词W[1..n]
S3.找出词频最小的词 Wmin ,(词频:关键词对应的集合大小)
S3.1 在映射中找出 Wmin 对应的标题集合,调用楼主原有算法
return
S3.2. 所有的词都不出现在关键词中


调用楼主原有算法
return
分析:
S1是预计算步骤,仅在初次加载标题时执行,若标题有变化,那么动态调整映射
耗时可以平摊到后序查找过程中,于是代价忽略
S2 分词可以快速完成,代价较小
S3 如果大多数情况下能在S3.1处结束,极少数在S3.2结束,且S3.1比S3.2快出许多
那么查找的平均性能会提高

[解决办法]
境界太高了
[解决办法]
不知道你想干什么, 全文搜索?

你这个foreach对每篇文章都做了一次indexOf这个 复杂度是 O(文章数量*文章长度) 
我觉得不太可能比sql的算法还快
[解决办法]
why not using Lucene.NET?
[解决办法]
你的代码肯定没有问题,当数据量大的时候出了问题,就要掂量下你的思路是否需要改变了
你的代码其实做了两件事情,“查找”和“匹配”,如果你把他们分开,你确保你只要查找就是你想要的结果就可以了
[解决办法]
楼主的例子恰恰生动地说明了,单纯地抠语法而不注重大局的性能。

不管是Hash还是二分法都比你这种原始的循环效率高出几个数量级。

还一再提要用obj.Tostring()来代替obj.
那你试试这个吧。

obj =null;
obj.ToString();
结果会怎样?
[解决办法]
算法问题。SP1234没说错。
可以考虑NON SQL啊,IN MEMORY db a...
[解决办法]

探讨
前一帖子参考:for的效率测试和结果,分享一下
里面很多同学都说,我提的那点性能,影响不大,不建议改进,而建议使用可读性好的代码写法,这里我分享一个我的实际经验。

我现在负责一个日pv访问过千万的搜索接口,数据大约几十万条
因为SqlServer的LIKE效率太低,而SqlServer的全文检索又不尽人意,于是方案定为把这些记录全部加载到内存,代码一开始如下:
Dictionary<s……

[解决办法]
sql啥的咱是白痴,不扯那个,就代码看起来LZ是想实现在标题中查找指定关键字.
同时标题却又作为hash的key了.于是干脆就遍历

这种情况其实用SortedDictionary更好吧?hash的存储可不保证给你按序排放啊.
按key排序后再二分查找如sp1234所说比你现在的方式效率高了不是一点半点啊..

放下这个不说,那
sb.AppendFormat("{0},", pair.Value);
明显不如
sb.Append(pair.Value.ToString());
sb.Append(',');

至于后面那个
sb.AppendFormat("{0},", pair.Value.ToString());
LZ你是在卖萌吧?

既然效率都那么差了你还弄个格式字符串去让它解析一下,完了还让它判断下参数类
型后给你copy到指定位置?

最后:
hash表和stringbuilder真心不是这么用的...
[解决办法]
为什么没人提到内存占用的问题?那么多数据加到内存,敢想?
[解决办法]
如果技术够好,就写个极速算法
[解决办法]
我觉得不重视重用的时候不用太重视可读
[解决办法]
探讨

楼主的例子恰恰生动地说明了,单纯地抠语法而不注重大局的性能。

不管是Hash还是二分法都比你这种原始的循环效率高出几个数量级。

还一再提要用obj.Tostring()来代替obj.
那你试试这个吧。

obj =null;
obj.ToString();
结果会怎样?

[解决办法]
你这问题与for有什么关系啊?

你对一个dictionary进行遍历(我从来没见过),功能退化为vector,性能和所占内存以及构造还不如vector。

楼主的问题是一个非常复杂的算法问题。我也没想到好的办法,所以就不说了。

我很想知道的是,楼主修改代码之后,性能提高了吗?我不太信。
就算提高了一点点,那也是因为你for循环太多的问题,如果你的for循环占用了90%的cpu(夸张一点,明白我的意思即可),那么在for循环里面稍微优化一下,的确是提高不少性能,但这是建立在你设计错误的基础之上的(比如你举的例子)——为什么for循环要占用这么多的cpu?
[解决办法]
我就不懂了,可读性与性能之间为什么只能二选一呢?

看到后面的例子我就更不懂了,这个例子跟标题有一毛钱关系吗?
[解决办法]
弱弱的说一下。。Dictionary<K,V>的TryGetValue方法比先判断ContainsKey再GetValue的做法效率更佳。。。
[解决办法]
第一条CSDN社区的回复
[解决办法]
探讨



sql啥的咱是白痴,不扯那个,就代码看起来LZ是想实现在标题中查找指定关键字.
同时标题却又作为hash的key了.于是干脆就遍历

这种情况其实用SortedDictionary更好吧?hash的存储可不保证给你按序排放啊.
按key排序后再二分查找如sp1234所说比你现在的方式效率高了不是一点半点啊..

放下这个不说,那
sb.AppendFormat("{0},", pa……


[解决办法]
我现在可以发帖了吗
[解决办法]
谢谢楼主分享啊!
[解决办法]
谢谢楼主您的分享
[解决办法]
感谢楼主分享!
[解决办法]
感谢楼主分享!
[解决办法]
我看还不错啊
[解决办法]
这种查询的还写个算法去处理吧,暂不说代码咋样,几十万条数据放到内存本身就是个错误。

没有弄过这种所以也给不了什么建议, 希望牛人给楼主建议而不是指责。
[解决办法]
来学习,多赐教

热点排行