You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
10 KiB
287 lines
10 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
using Sog;
|
|
using Sog.Crypto;
|
|
using Google.Protobuf.WellKnownTypes;
|
|
|
|
namespace TestSog
|
|
{
|
|
/// <summary>
|
|
/// 1.
|
|
/// 性能测试 : Intel Xeon CPU E3-1230 3.3G (2016/8/11) OS Windows
|
|
/// 结果分析:Debug模式下,tea加密解密100000次消耗400毫秒(优化后是250毫秒),protobuf打包解包100000次消耗500毫秒,Release模式下消耗时间是Debug模式的36~40%
|
|
/// GateServer由于处理大规模的网络消息,连接多,应该是整个服务器的瓶颈,这里以GateServer为参考做计算
|
|
/// GateServer进程的极限消息处理能力也就是10万左右(包括打包一次,解包一次,加密一次,解密一次),毕竟还要处理socket等等逻辑
|
|
/// 对GateServer来说,每从客户端收到一个消息,需要解密一次,转发给后端需要几次内存拷贝,粗略估计相当于打包一次,解包一次的计算量,发送消息也是一样,那么我们
|
|
/// 把打包一次+加密一次或者打包一次+解包一次作为计算能力单位1,GateServer的计算能力为20万左右
|
|
/// 考虑到棋牌游戏特点,在玩牌的玩家平均一秒估计(收1个消息,发4个消息),计算能力单位为5,那么一个GateServer进程大概能够承载玩家约为20/5=4万人左右
|
|
/// 加上误差和冗余,承载2万人应该是不成问题的
|
|
/// 以泰国三公作为参考对象,DAU为60万,最高在线为6万人,那么需要游戏开启3组游戏服务器,每组游戏服务器包含(Gate+Game+Room)3个进程
|
|
/// 如果是4核心(不考虑超线程)CPU的机器,需要3台Game,1台world+lobby,2台db,1台log,总共需要7台机器,成本在每个月4万人民币,收入预计100~200万人民币
|
|
/// 虚拟机由于cpu比较坑爹,也许需要所谓的8核机器
|
|
/// 2.
|
|
/// 性能优化: 后期再做
|
|
/// a)优化的思路主要就是减少new的调用,比如各种new byte[],用来处理消息,这方面有很大优化空间,包括消息加密解密,收消息,发消息,消息打包,解包等
|
|
/// 经过各种测试,其实发现C#各种new 小对象的效率并不低,优化的空间不一定很大,到时候看
|
|
/// tea加密解密已经优化,采用SogFastXTEAKey代替原有XXTea算法,速度提高80~100%
|
|
/// b)还有就是某些hash表查找改成数组,比如消息id和parse的对应关系,消息handler和id的对应关系等等
|
|
/// c)打印日志的优化,C#和C++程序不一样,因为没有宏,日志虽然会由于日志等级原因不写到文件里,但是字符串和变量的封装都会执行,这个比较影响性能,到时候优化.
|
|
/// 现在还不知道有什么好的办法
|
|
/// d)由于打印消息大量调用的ServerIDUtils.IDToString,此函数需要优化
|
|
/// e)日志打印Message消息json格式效率很低,在打消息的地方上层增加消息等级的判断
|
|
/// </summary>
|
|
public class TestPerformance
|
|
{
|
|
private Random m_rand = new Random();
|
|
|
|
IProtoPacker m_packer = ProtoPackerFactory.Instance.GetProtoPacker();
|
|
|
|
|
|
public TestPerformance()
|
|
{
|
|
ProtoRegister.Instance.RegisterAllPacket();
|
|
|
|
TraceLog.SetLogLevel(Sog.Log.LogLevel.Error);
|
|
|
|
}
|
|
|
|
|
|
private void TestLog()
|
|
{
|
|
long startTime = AppTime.GetNowSysMs();
|
|
|
|
int loopTime = 1000000;
|
|
|
|
//这里主要的性能消耗是ServerIDUtils.IDToString
|
|
for (int i = 0; i < loopTime; i++)
|
|
{
|
|
TraceLog.Debug("TestTea loop one index {0} loop {1}, idtostring {2}", i, loopTime, ServerIDUtils.IDToString((uint)(i%1000)));
|
|
}
|
|
|
|
long endTime = AppTime.GetNowSysMs();
|
|
|
|
long timeCost = endTime - startTime;
|
|
|
|
Console.WriteLine("TestLog ,loopTime {0:N0} cost time {1}", loopTime, timeCost);
|
|
}
|
|
|
|
private void TestXXTea()
|
|
{
|
|
long startTime = AppTime.GetNowSysMs();
|
|
|
|
byte[] teaKey = new byte[16];
|
|
|
|
m_rand.NextBytes(teaKey);
|
|
|
|
byte[] data = new byte[64];
|
|
m_rand.NextBytes(data);
|
|
|
|
byte[] result;
|
|
|
|
int loopTime = 100000;
|
|
|
|
for (int i = 0; i < loopTime; i++)
|
|
{
|
|
try
|
|
{
|
|
result = XXTea.Encrypt(data, teaKey);
|
|
byte[] data2 = XXTea.Decrypt(result, teaKey);
|
|
|
|
if (data2.Length != data.Length)
|
|
{
|
|
Console.WriteLine("TestXXTea decrypt failed!, length {0} != {1}", data.Length, data2.Length);
|
|
return;
|
|
}
|
|
|
|
for (int j = 0; j < data.Length; j++)
|
|
{
|
|
if (data[j] != data2[j])
|
|
{
|
|
Console.WriteLine("TestXXTea decrypt failed!, index {0}, value {1} != {2}", j, data[j], data2[j]);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
catch(Exception)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TraceLog.Debug("TestXXTea loop one index {0} length {1}", i, data.Length);
|
|
}
|
|
|
|
long endTime = AppTime.GetNowSysMs();
|
|
|
|
long timeCost = endTime - startTime;
|
|
|
|
Console.WriteLine("TestXXTea en&de 64 byte data ,loopTime {0:N0} cost time {1}", loopTime, timeCost);
|
|
}
|
|
|
|
private void TestSogXTea()
|
|
{
|
|
long startTime = AppTime.GetNowSysMs();
|
|
|
|
byte[] data = new byte[64];
|
|
m_rand.NextBytes(data);
|
|
byte[] data2 = new byte[64];
|
|
Buffer.BlockCopy(data, 0, data2, 0, data.Length);
|
|
|
|
SogFastXTEAKey sogteaKey = TeaKeyGenerator.Instance.GenerateFastXTEAKey();
|
|
|
|
int loopTime = 100000;
|
|
|
|
for (int i = 0; i < loopTime; i++)
|
|
{
|
|
SogFastXTEA.Encrypt(data, sogteaKey);
|
|
SogFastXTEA.Decrypt(data, sogteaKey);
|
|
|
|
if (data2.Length != data.Length)
|
|
{
|
|
Console.WriteLine("TestSogXTea decrypt failed!, length {0} != {1}", data.Length, data2.Length);
|
|
return;
|
|
}
|
|
|
|
for (int j = 0; j < data.Length; j++)
|
|
{
|
|
if (data[j] != data2[j])
|
|
{
|
|
Console.WriteLine("TestSogXTea decrypt failed!, index {0}, value {1} != {2}", j, data[j], data2[j]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
//TraceLog.Debug("TestSogXTea loop one index {0} length {1}", i, data.Length);
|
|
}
|
|
|
|
long endTime = AppTime.GetNowSysMs();
|
|
|
|
long timeCost = endTime - startTime;
|
|
|
|
Console.WriteLine("TestSogXTea en&de 64 byte data ,loopTime {0:N0} cost time {1}", loopTime, timeCost);
|
|
}
|
|
|
|
private void TestProtoBuf()
|
|
{
|
|
long startTime = AppTime.GetNowSysMs();
|
|
|
|
int loopTime = 100000;
|
|
|
|
long totalPacketedLength = 0;
|
|
|
|
for (int i = 0; i < loopTime; i++)
|
|
{
|
|
int iMsgID = (int)CSGameMsgID.LoginReq;
|
|
|
|
CSLoginReq req = new CSLoginReq();
|
|
req.Account = new AccountInfo();
|
|
req.Account.AccountID = i.ToString();
|
|
req.Account.PlatformType = i%2;
|
|
req.Account.AccountToken = "lasjdflkajldsjkflajksdlfjalsjkdgljsldfjkglsjdjoewiurtojsdl;fnlfdkgnlsknjdfg";
|
|
req.Account.AccountType = 0;
|
|
req.Uid = 9999999;
|
|
req.Version = new VersionInfo();
|
|
req.Version.AppVersion = "1.0.0";
|
|
req.Version.Language = "en";
|
|
req.Version.Os = "Windows";
|
|
|
|
RequestPacket packet = new RequestPacket(iMsgID, 0, 0);
|
|
|
|
packet.Message = req;
|
|
|
|
MessageData message;
|
|
message.Header.Type = packet.MsgID;
|
|
message.Header.Length = 0;
|
|
message.Header.ObjectID = 1;
|
|
message.Header.ServerID = 2;
|
|
message.Data = null;
|
|
|
|
m_packer.PackMessage(packet, ref message);
|
|
|
|
totalPacketedLength += message.Data.Length;
|
|
RequestPacket outPacket;
|
|
|
|
m_packer.UnpackMessage(message, out outPacket);
|
|
|
|
if(packet.MsgID != outPacket.MsgID)
|
|
{
|
|
Console.WriteLine("TestProtoBuf unpack message failed, msgid error");
|
|
return;
|
|
}
|
|
|
|
CSLoginReq outReq = (CSLoginReq)outPacket.Message;
|
|
|
|
if (outReq.Account.AccountID != req.Account.AccountID)
|
|
{
|
|
Console.WriteLine("TestProtoBuf unpack message failed, msg AccountID error");
|
|
return;
|
|
}
|
|
|
|
if (outReq.Account.AccountToken != req.Account.AccountToken)
|
|
{
|
|
Console.WriteLine("TestProtoBuf unpack message failed, msg AccountToken error");
|
|
return;
|
|
}
|
|
|
|
if (outReq.Version.Language != req.Version.Language)
|
|
{
|
|
Console.WriteLine("TestProtoBuf unpack message failed, msg Language error");
|
|
return;
|
|
}
|
|
|
|
if (outReq.Uid != req.Uid)
|
|
{
|
|
Console.WriteLine("TestProtoBuf unpack message failed, msg Uid error");
|
|
return;
|
|
}
|
|
|
|
if (outReq.Version.AppVersion != req.Version.AppVersion)
|
|
{
|
|
Console.WriteLine("TestProtoBuf unpack message failed, msg AppVersion error");
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
long endTime = AppTime.GetNowSysMs();
|
|
|
|
long timeCost = endTime - startTime;
|
|
|
|
Console.WriteLine("TestProtoBuf pack&unpack CSLoginReq,loopTime {0:N0} cost time {1}", loopTime, timeCost);
|
|
|
|
}
|
|
|
|
public void Test()
|
|
{
|
|
for(int i= 0; i< 10; i++)
|
|
{
|
|
TestLog();
|
|
}
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
TestXXTea();
|
|
}
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
TestSogXTea();
|
|
}
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
TestProtoBuf();
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|