首页 > 代码库 > Web API的CPU占用100%

Web API的CPU占用100%

我用Web API做了一个网站,网站很简单,请求就是几个普通的参数,提交到服务器后,在Web API里做一下参数验证,然后去访问Redis里的TIME命令,最后把TIME命令返回的结果计算出yyyy-MM-dd HH:mm:ss的形式,返回JSON格式。
每秒请求数:1500次。
CPU占用100%
内存和IO都比较低。

 

CPU:E5800

内存:4G+2G

硬盘:普通蓝盘500G


各位,有人遇到过这样的情况吗?

 

--------------------------------------------------------------------------华丽的分割线-------------------------------------------------------------------------------

测试电脑配置:

CPU:I7-3770

内存:4G+4G

硬盘:SSD

系统:Win7 64位

.Net Framework:4.5

IIS配置:版本:7.5,队列长度:5000,Web园:5个。

 

关于上面提到的问题,很多人的说法都不太一样,我一个一个整理,排名是乱的,大家别介意:

1、大石头:在这个过程里面,Json的序列化和反序列化是非常耗时的,远远超过普通asp.net处理其实

  可以试试。

 

2、Melas:缓存相同请求的数据

  因为我的数据都是不同的,所以没有办法缓存。

 

3、肖伦军:微软自带的json,不要用第三方的。

  可以试试。

 

4、泥水佬:json也不会差到这程度的,除非服务器配置很低 

  不到万不得已,我不愿意考虑硬件的问题。

  很久以前,在泥水佬的建议下,我用了jetbrains dottrace,测试结果是有一个东西占了百分之九十多的CPU,“ [Native or optimized code] ”,我对这个一直不了解,也不知道这个为什么占这么高的CPU。

 

根据上面4位的建议,我选择大石头和肖伦军说的json的序列化测试。

源码:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Diagnostics;
 4 using System.IO;
 5 using System.Linq;
 6 using System.Runtime.Serialization.Json;
 7 using System.Text;
 8 using Newtonsoft.Json;
 9 using Formatting = System.Xml.Formatting;
10 
11 namespace TestSerializationConsole
12 {
13     class Program
14     {
15         static void Main(string[] args)
16         {
17             Stopwatch timer = new Stopwatch();
18             timer.Start();
19             List<ApiResult> list = new List<ApiResult>();
20             for (int i = 0; i < 1000000; i++)
21             {
22                 ApiResult result = new ApiResult
23                 {
24                     Code = i,
25                     ErrorMsg = string.Format("当前编号:{0}", i),
26                     IsError = (i % 2 == 0),
27                     Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
28                     Guid = Guid.NewGuid().ToString()
29                 };
30                 list.Add(result);
31             }
32             timer.Stop();
33             Console.WriteLine("共创建{0}项\t共耗时:{1}毫秒", list.Count, timer.ElapsedMilliseconds);
34             timer.Restart();
35             int count1 = list.Select(apiResult => Serialize1(apiResult)).Count(jsonResult => jsonResult.Length > 60);
36             timer.Stop();
37             Console.WriteLine("System.Runtime.Serialization.Json序列化{0}项\t共耗时:{1}毫秒", count1, timer.ElapsedMilliseconds);
38             timer.Restart();
39             int count2 = list.Select(apiResult => Serialize2(apiResult)).Count(jsonResult => jsonResult.Length > 60);
40             timer.Stop();
41             Console.WriteLine("Newtonsoft.Json.dll序列化{0}项\t共耗时:{1}毫秒", count2, timer.ElapsedMilliseconds);
42             Console.ReadKey();
43         }
44 
45         private static string Serialize1(ApiResult obj)
46         {
47             string jsonContent = string.Empty;
48             DataContractJsonSerializer serialize = new DataContractJsonSerializer(typeof(ApiResult));
49             using (MemoryStream ms = new MemoryStream())
50             {
51                 serialize.WriteObject(ms, obj);
52                 jsonContent = Encoding.UTF8.GetString(ms.ToArray());
53             }
54             return jsonContent;
55         }
56 
57         private static string Serialize2(ApiResult obj)
58         {
59             string jsonContent = string.Empty;
60             jsonContent = JsonConvert.SerializeObject(obj);
61             return jsonContent;
62         }
63     }
64 
65     public class ApiResult
66     {
67         public int Code { get; set; }
68         public string ErrorMsg { get; set; }
69         public bool IsError { get; set; }
70         public string Time { get; set; }
71         public string Guid { get; set; }
72     }
73 }

测试结果:

共创建1000000项 共耗时:1987毫秒
System.Runtime.Serialization.Json序列化1000000项 共耗时:2843毫秒
Newtonsoft.Json.dll序列化1000000项 共耗时:1747毫秒

测试结果证明,不是序列化的问题。

 

继续测试:

不使用redis,而是直接使用系统提供的DateTime.Now属性,每秒请求数能增加33%

这个结果证明,不是redis的问题。