玩家属性同步优化-脏数据标记(位运算、数组、stl之bitset)
把大神的帖子中一部分摘抄出来,结合自己写的位运算代码和循环代码(数组遍历)进行性能测试分析并给出结果。 摘自: https://www.gameres.com/827195.html
本文适用于所有脏标记遍历功能,提升性能几倍,本文以游戏中玩家的属性同步作为例子进行介绍。
先说性能分析结果:一般玩家属性列表也就120个够用了,其中常用的攻击,防御,血蓝等,不超过20个。每0.5秒同步一次,那么变化的常用属性更少。
当变化10个属性,位运算性能提升6倍,20个时4倍,如图所示:

总结:位运算效率高,并且把常用属性定义为低位效率更高。 其次是数组(原因是遍历),再其次是set(影响原因是hash函数、hash扩容、二叉树节点转换),最差是stl之bitset(原因:本质也是数组)
优化前的循环算法(数组):
const int N = ;
class BitSet
{
public:
BitSet()
{
memset(m_szBits,,sizeof(m_szBits));
m_bBitsDirty = false;
}
int Set(size_t i)
{
if(i >= && i < N)
{
++m_szBits[i]; m_bBitsDirty = true; }
return ;
}
int Get(size_t i) const
{
if(i >= && i < N)
{
return m_szBits[i] > ;
}
return ;
}
void Clean()
{
memset(m_szBits,,sizeof(m_szBits));
m_bBitsDirty = false;
}
bool IsDirty() const
{
return m_bBitsDirty;
}
private:
char * m_szBits[N];
bool m_bBitsDirty;
};
优化后的位运算:
const int nLLLeng = ;
class NewBitSet
{
public:
NewBitSet():llLow(0ull),llHight(0ull)
{
}
void Set(size_t i)
{
if(i > && i < nLLLeng)
{
llLow |= 1ull << i;
}
else if (i < nLLLeng * )
{
llHight |= 1ull << (i & 0x3F); // 0x3F 是64的16进制,这样做是相当于减64
}
}
void GetAllDirty(int * arrDirty, int & nMaxCount) const
{
unsigned long long nllLowTemp = llLow;
unsigned long long nllHightTemp = llHight;
nMaxCount = -;
while (nllLowTemp)
{
arrDirty[++nMaxCount] = __builtin_ffsll(nllLowTemp) - ;
nllLowTemp &= (nllLowTemp - );
}
while (nllHightTemp)
{
arrDirty[++nMaxCount] = __builtin_ffsll(nllHightTemp) - + nLLLeng;
nllHightTemp &= (nllHightTemp - );
}
}
void Clean()
{
llLow = llHight = 0ull;
} bool IsDirty() const
{
return llLow || llHight;
}
private:
unsigned long long int llLow;
unsigned long long int llHight;
};
测试用例:
#include <iostream>
#include <sys/time.h>
#include<stdlib.h>
#include <algorithm>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<map>
#include <string.h>
using namespace std;
const int N = ;
class BitSet
{
public:
BitSet()
{
memset(m_szBits,,sizeof(m_szBits));
m_bBitsDirty = false;
}
int Set(size_t i)
{
if(i >= && i < N)
{
++m_szBits[i]; m_bBitsDirty = true; }
return ;
}
int Get(size_t i) const
{
if(i >= && i < N)
{
return m_szBits[i] > ;
}
return ;
}
void Clean()
{
memset(m_szBits,,sizeof(m_szBits));
m_bBitsDirty = false;
}
bool IsDirty() const
{
return m_bBitsDirty;
}
private:
char * m_szBits[N];
bool m_bBitsDirty;
}; const int nLLLeng = ;
class NewBitSet
{
public:
NewBitSet():llLow(0ull),llHight(0ull)
{
}
void Set(size_t i)
{
if(i > && i < nLLLeng)
{
llLow |= 1ull << i;
}
else if (i < nLLLeng * )
{
llHight |= 1ull << (i & 0x3F); // 0x3F 是64的16进制,这样做是相当于减64
}
}
void GetAllDirty(int * arrDirty, int & nMaxCount) const
{
unsigned long long nllLowTemp = llLow;
unsigned long long nllHightTemp = llHight;
nMaxCount = -;
while (nllLowTemp)
{
arrDirty[++nMaxCount] = __builtin_ffsll(nllLowTemp) - ;
nllLowTemp &= (nllLowTemp - );
}
while (nllHightTemp)
{
arrDirty[++nMaxCount] = __builtin_ffsll(nllHightTemp) - + nLLLeng;
nllHightTemp &= (nllHightTemp - );
}
}
void Clean()
{
llLow = llHight = 0ull;
} bool IsDirty() const
{
return llLow || llHight;
}
private:
unsigned long long int llLow;
unsigned long long int llHight;
}; int nPrintCount = ; void DirtyBit(int nRandCount)
{
NewBitSet tDirty;
int nRand = ;
//srand((unsigned)time(0));
for (int i = ; i < nRandCount;i++)
{
// nRand = rand()%126 + 1;
tDirty.Set(i+);
}
if (!tDirty.IsDirty())
{
return;
}
int arrDirty[nLLLeng * ] = {};
//同步自己执行次数
int nMaxCount = ;
tDirty.GetAllDirty(arrDirty, nMaxCount);
nMaxCount = ;
//同步WS执行次数
tDirty.GetAllDirty(arrDirty, nMaxCount); int nNotPrint = ;
for (int i = ; i< nMaxCount; i++)
{
nNotPrint = arrDirty[i];
}
tDirty.Clean();
} void DirtyArr(int nRandCount)
{
BitSet tDirty;
int nRand = ;
// srand((unsigned)time(0));
for (int i = ; i < nRandCount;i++)
{
// nRand = rand()%126 + 1;
tDirty.Set(i+);
}
if (tDirty.IsDirty())
{
int arrDirty[N] = {};
int nMaxCount = -;
//同步自己执行次数
for (int i = ; i< N; ++i)
{
if (tDirty.Get(i))
{
arrDirty[++nMaxCount] = i;
}
}
//同步WS执行次数
nMaxCount = -;
for (int i = ; i< N; ++i)
{
if (tDirty.Get(i))
{
arrDirty[++nMaxCount] = i;
}
}
int nNotPrint = ;
for (int i = ; i< nMaxCount + ; i++)
{
nNotPrint = arrDirty[i];
}
} tDirty.Clean();
} int main()
{
float time_use=;
struct timeval start;
struct timeval end;
int nTestCount = ;
gettimeofday(&start,NULL); nPrintCount = ;
//处理过程--开始
for (int i = ; i< ; ++i)
{
DirtyBit(nTestCount);
}
//处理过程--结束 cout<<endl;
gettimeofday(&end,NULL);
time_use=(end.tv_sec-start.tv_sec)*+(end.tv_usec-start.tv_usec);//微秒
printf("time_use is %.10f\n",time_use); nPrintCount = ;
gettimeofday(&start,NULL);
//处理过程--开始
for (int i = ; i< ; ++i)
{
DirtyArr(nTestCount);
}
//处理过程--结束 cout<<endl;
gettimeofday(&end,NULL); time_use=(end.tv_sec-start.tv_sec)*+(end.tv_usec-start.tv_usec);//微秒
printf("time_use is %.10f\n",time_use);
return ;
}
玩家属性同步优化-脏数据标记(位运算、数组、stl之bitset)的更多相关文章
- C++基础-位运算
昨天笔试遇到一道题,让实现乘法的计算方法,设计方案并优化,后来总结位运算相关知识如下: 在计算机中,数据是以1010的二进制形式存储的,1bytes = 8 bits,bit就是位,所以位运算就是对每 ...
- C/C++中的位运算
位运算 位运算的运算分量只能是整型或字符型数据,位运算把运算对象看作是由二进位组成的位串信息,按位完成指定的运算,得到位串信息的结果. 位运算符有: &(按位与).|(按位或) ...
- P3613 睡觉困难综合征 LCT+贪心+位运算
\(\color{#0066ff}{ 题目描述 }\) 由乃这个问题越想越迷糊,已经达到了废寝忘食的地步.结果她发现--晚上睡不着了!只能把自己的一个神经元(我们可以抽象成一个树形结构)拿出来,交给D ...
- STL+位运算的文件
1.queue 队列 queue的头文件是<queue>. 定义queue对象的示例代码如: queue<int>q; 队列内存放的是int类型的数 queue<dou ...
- 一文了解有趣的位运算(&、|、^、~、>>、<<)
1.位运算概述 从现代计算机中所有的数据二进制的形式存储在设备中.即0.1两种状态,计算机对二进制数据进行的运算(+.-.*./)都是叫位运算,即将符号位共同参与运算的运算. 口说无凭,举一个简单的例 ...
- 位运算(&、|、^、~、>>、<<)
1.位运算概述 从现代计算机中所有的数据二进制的形式存储在设备中.即0.1两种状态,计算机对二进制数据进行的运算(+.-.*./)都是叫位运算,即将符号位共同参与运算的运算. 口说无凭,举一个简单的例 ...
- 原生Redis跨数据中心双向同步优化实践
一.背景 公司基于业务发展以及战略部署,需要实现在多个数据中心单元化部署,一方面可以实现多数据中心容灾,另外可以提升用户请求访问速度.需要保证多数据中心容灾或者实现用户就近访问的话,需要各个数据中心拥 ...
- Angular 1 深度解析:脏数据检查与 angular 性能优化
TL;DR 脏检查是一种模型到视图的数据映射机制,由 $apply 或 $digest 触发. 脏检查的范围是整个页面,不受区域或组件划分影响 使用尽量简单的绑定表达式提升脏检查执行速度 尽量减少页面 ...
- 关于位图数据和标记位-P3
文章目录 1 背景 1.1 问题 2 问题1探究 2.1 没有区的情况 2.2 一个区的情况 2.3 两个区的情况 2.4 三个区的情况 2.5 四个区的情况 2.6 五个区的情况 3 问题2探究 3 ...
随机推荐
- Udp客户端与服务通讯
使用UDP与服务端通讯时候,同样需要先启用udp服务端监控,当服务端启动成功,在启动客户端 首先UDP服务端类,代码如下: public class UdpServerTest { public vo ...
- C# vb .net实现旋转特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的旋转特效呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步 ...
- springmvc 注解二
@SessionAttributes @sessionattributes注解应用到Controller上面,可以将Model中的属性同步到session作用域当中. SessionAttribute ...
- 单词eschaunge交易所eschaunge交换
Exchange of one person or thing for another; reciprocal giving and receiving: (a) of prisoners of wa ...
- 精选SpringBoot八大开源项目:支付、秒杀、全文搜索等
前言 曾在自己的博客中写下这样一段话:有一种力量无人能抵挡,它永不言败生来倔强.有一种理想照亮了迷茫,在那写满荣耀的地方. 如今,虽然没有大理想抱负,但是却有自己的小计划.下面是这一年来,自己利用闲暇 ...
- 使用Blynk打造一款物联网产品
前言 一直以来想自己打造一款物联网产品. 围绕这个话题写过一些文章: 一辆树莓派可编程小车的问题 基于树莓派的积木化编程解决方案 物联网相关开源项目整理 物联网.开源硬件与开源社区 之前在一辆树莓派可 ...
- unity shader入门(三)逐像素光照,Blinn-Phong模型
与上篇逐顶点光照很像,只是改为在片元着色器中计算光照,下为逐像素光照shader Shader "study/Chapter6/PixelShader"{ Properties{ ...
- appium自动化webview时遇到的chromedriver问题
安卓app里面的网页,基本上都是使用手机系统上的webview 去显示的. 安卓 webview 可以看成是 手机上的 chrome 浏览器精简版. appium desktop 里面内置了 用于 w ...
- jQuery知识梳理20190818
目录 jQuery知识梳理20190818 1. 时间绑定和解绑 2. 区别mouseover与mouseenter 3. 时间委托(委派/代理) 4 . 多库共存 5.window.onload与$ ...
- MySQL-CentOS7上安装Mysql5.7
#安装 wget http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm .noarch.rpm yum instal ...