首页 新闻 搜索 专区 学院

求救,大访问量时这段代码性能很差,如何优化?

0
悬赏园豆:50 [已解决问题] 解决于 2018-01-16 19:01

如题,网站增加个统计ip的功能,于是有了如下代码:

每有一个ip访问,都会执行一次Count方法。

在一分钟500ip的时候,IIS就反应不过来了,CPU占用100%,求优化啊

(不含有数据库操作)

public static readonly List<IPLog> IPList = new List<IPLog>();
public void Count(xxxxx)
{
    var log = new IPLog()
    {
        IP = ip,
        VisitTime = DateTime.Now
    };
    IPList.Add(log);
    if (IPList.Count >= 1000)
    {
        var clone = ipList.GetRange(0, IPList.Count);
        IPList.Clear();
        //保存到数据库(clone)
        //每1000IP提交到数据库一次
     //已注释 } }
问题补充:

多谢各位,确实不是这个代码的问题。找到一个问题,稍微缓解了一下,虽然CPU也很高,但还可以接收,是因为Unity有一个特殊的注入,采用的反射的方法占用了资源。

wdwwtzy的主页 wdwwtzy | 菜鸟二级 | 园豆:226
提问于:2012-09-07 16:12
< >
分享
最佳答案
0

如果就你给的这些代码,速度不会慢的,而且都是1000IP才会提交数据库了,那更没理由慢了。

收获园豆:10
秦楼东 | 小虾三级 |园豆:913 | 2012-09-07 16:23

嗯,是啊,想不明白,也不知道从哪里下手分析

wdwwtzy | 园豆:226 (菜鸟二级) | 2012-09-07 16:27

@wdwwtzy: 不确定哪里影响了速度的话,你可以为几个可能影响速度的方法提供计时,将计时结果保存到日志文件里。虽然日志记录本身会有速度影响,但是对分析问题很有用。

秦楼东 | 园豆:913 (小虾三级) | 2012-09-07 16:31

@wdwwtzy: 

明白了,你把方法写成静态的,不然的话,你这样没一个ip都要创建一个对象?用线程安全的集合,采用多线程+异步来处理,

 

线程池呀  什么滴 你看一下就能用,开启并行   我就不信 他还会死机?

架构师修行之路 | 园豆:322 (菜鸟二级) | 2012-09-07 17:12
其他回答(8)
0

可以使用一个缓存数据库,比如使用MongoDB,没一条写一次

每日同步MongoDB to SQL SERVER

收获园豆:5
哇~怪兽 | 园豆:603 (小虾三级) | 2012-09-07 16:26
0

如果你不能确定CPU被谁占用的话,用2-3个DUMP分析下,哪些线程占用CPU时间多。

收获园豆:5
Launcher | 园豆:45045 (高人七级) | 2012-09-07 16:33

sorry 不太清楚如何做,可否给些资料?

支持(0) 反对(0) wdwwtzy | 园豆:226 (菜鸟二级) | 2012-09-07 16:36
支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2012-09-07 16:38

@wdwwtzy: 这个工具应该用起来简单:Debug Diagnostics Tool.可以使用Add Rule 的 Performance,也可以到Processes列表中抓DUMP,然后使用Advanced Analysis来分成报告,一般来说一眼就能看出占用CPU高的线程。如果看不出来,就把DUMP文件交给WinDBG分析,分析方法看上面那篇博文。

支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2012-09-07 16:44

@Launcher: 多谢,我试试

支持(0) 反对(0) wdwwtzy | 园豆:226 (菜鸟二级) | 2012-09-07 17:29
0

你都没找到速度慢的原因在哪,这叫怎么优化  ,另外 你给的这段代码 你都可以自己写个测试程序 循环几百次 来测试

 

另外说一句,你这段代码不安全,多线程存在危险 改进一下吧,省的以后麻烦

收获园豆:5
架构师修行之路 | 园豆:322 (菜鸟二级) | 2012-09-07 16:36

多谢,我这样lock行不?

.....
.....
lock(xxx)
{
IPList.Add(log);
....
}
支持(0) 反对(0) wdwwtzy | 园豆:226 (菜鸟二级) | 2012-09-07 17:16

@wdwwtzy: 

你的问题还没有根本解决 ,线程问题最好用c#的线程安全集合,开启并行

支持(0) 反对(0) 架构师修行之路 | 园豆:322 (菜鸟二级) | 2012-09-07 17:32
0

用缓存,不一定非要使用Redis,Mongdb等等缓存数据库,可以使用.net自带的缓存进行一些常用数据的缓存。

1.数据库方面要对常用Sql语句进行存储过程处理。

2.常用数据,比如排名等等信息进行缓存,避免重复计算。

3.优化程序。

4.对常用数据表加上索引。

5.进行数据库读写分离。

6.对网站做CDN加速,不过要花钱的。

7.如果有记日志的话,将日志表从业务数据库中分离出来。日志记录是一个消耗性能。可以参考使用Log4Net来进行日志记录。

8.尝试使用redis或者mongdb来对常用数据进行缓存。

9.优化系统架构,避免不必要的分层。

10.对大数据表做表分区处理,可以分散压力。

11.使用工具找到网站或者系统的压力点,然后对症下药。祝你好运。

收获园豆:10
jerry-Tom | 园豆:4077 (老鸟四级) | 2012-09-07 16:36
0

每有一个ip访问,都会执行一次Count方法

这么做不对。给你几个建议:

1. 定义一个静态的字典ConcurrentDictionary<string, IPLog>,字典的key是ip(string类型),value是 IPLog 类型。不要使用List<IPLog>,它是非线程安全的,会引起数据错误。

2. 每有一个新的请求过来,就往1中的字典里加入(或者已经存在了就不加入)当前请求的ip信息,这样新的请求很快就处理完了。而不是你之前的做法,“有可能”要执行很长时间(写数据库什么的)

3. 在Application_Start方法里启动一个新线程,这个线程每过n分钟(例如5分钟)就把1中的字典的信息写到数据里去(当然你也可以不立刻写,而是检查数目,等有了5000再写)

收获园豆:5
水牛刀刀 | 园豆:6350 (大侠五级) | 2012-09-07 16:40
0
添加 IPList, 和添加数据库,清空 IPList 用线程分开操作
收获园豆:5
Qlin | 园豆:2403 (老鸟四级) | 2012-09-07 17:50
0

最奇怪的,就是楼主的这段代码没有加锁就访问了静态的字段。

if (IPList.Count >= 1000)
    {
        var clone = ipList.GetRange(0, IPList.Count);
        IPList.Clear();
        //保存到数据库(clone)
        //每1000IP提交到数据库一次
     //已注释 }
这边添加到数据库的代码,就多开个线程去完成吧

收获园豆:5
chenping2008 | 园豆:9836 (大侠五级) | 2012-09-09 20:08
0

可以单独开个线程干这个。

那个线程 优先级稍稍低一点。

 

因为这个东西没必要实时做。 只要最后能做完就行。

undefined | 园豆:698 (小虾三级) | 2012-09-21 17:40
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册