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的问题。