作为一只从事.NET开发长达6年的程序狗,个人对.NET又爱又恨,爱的是强大的基础类库和全面的api文档让我所有的问题都能找到答案,恨的是因为微软的封闭策略丧失了大批的开发者的支持,让大多数人转向了Java的怀抱,让Java的生态圈蓬勃发展。从2015年开始微软发布.NET CORE开始,以全新的开源+重构的方式展现了全新的.NET,内部API经过了一些列的重构,号称在性能上有很大突破,今天闲来无事,就性能问题做一个对比。
实验的方案如下,分别用.NET的WebAPI2.0和.NET Core API以及Go语言写一个服务端,然后再写一个客户端程序分别新建1000个线程同时访问这三个服务,记录每次从服务开始到服务返回所花费的时间以及服务端的内存使用情况。本次对比不针对指定代码,主要是测试3个平台框架提供的基础处理和并发能力,为以后的技术选型提供一定的支持。
.NET的项目结构如下。
在Model中新建两个类,Request和Response用来记录传递的数据
using System;
namespace APICompare.Model
{
public class RequestInfo
{
/// <summary>
/// 记录的Request是哪个线程发送的
/// </summary>
public int RequestIndex { get; set; }
/// <summary>
/// 唯一Guid
/// </summary>
public string RequestGuid { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public DateTime BeginTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime EndTime { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace APICompare.Model
{
public class ResponseInfo
{
/// <summary>
/// 返回开始时间
/// </summary>
public DateTime BeginTime { get; set; }
public DateTime EndTime { get; set; }
public RequestInfo Request { get; set; }
/// <summary>
/// 当前工作集(bytes)
/// </summary>
public long WorkSet { get; set; }
}
}
新建API2.0的项目,并新建一个CostController,实现Get方法,接收RequestInfo参数,返回ResponseInfo
新建.NET Core API项目,处理过程参考API2.0
新建Go目录和对应的Model
在ResponseInfo.go中新建两个Model如下
package main
import "time"
type ResponseInfo struct {
BeginTime time.Time
EndTime time.Time
Request RequestInfo
WorkSet uint64
}
type RequestInfo struct {
RequestIndex int
RequestGuid string
BeginTime time.Time
EndTime time.Time
}
新建Http服务端主程序Server.go
package main
import (
"encoding/json"
"log"
"net/http"
"net/url"
"time"
"strings"
//"os"
"runtime"
"strconv"
)
func main() {
http.HandleFunc("/", handlerHttpRequest)
err := http.ListenAndServe(":8058", nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
log.Fatal("ListenAndServe on 8058")
}
func handlerHttpRequest(w http.ResponseWriter, r *http.Request) {
log.Println("r.URL.RawQuery:", r.URL.RawQuery)
query, err := url.QueryUnescape(r.URL.RawQuery)//解码url
if err != nil {
log.Fatal("url.QueryUnescape:", r.URL.RawQuery)
}
queryStrings :=strings.Split(query,"&")
var request RequestInfo
for _,queryStr := range queryStrings{
if strings.Contains(queryStr,"RequestIndex"){
request.RequestIndex,err=strconv.Atoi(strings.Split(queryStr,"=")[1]);
if err!=nil{
log.Println("strconv.Atoi:",err)
}
}
if strings.Contains(queryStr,"RequestGuid"){
request.RequestGui