• 玩家属性同步优化-脏数据标记(位运算、数组、stl之bitset)


    把大神的帖子中一部分摘抄出来,结合自己写的位运算代码和循环代码(数组遍历)进行性能测试分析并给出结果。 摘自: https://www.gameres.com/827195.html

    本文适用于所有脏标记遍历功能,提升性能几倍,本文以游戏中玩家的属性同步作为例子进行介绍。

    先说性能分析结果:一般玩家属性列表也就120个够用了,其中常用的攻击,防御,血蓝等,不超过20个。每0.5秒同步一次,那么变化的常用属性更少。

    当变化10个属性,位运算性能提升6倍,20个时4倍,如图所示:

    总结:位运算效率高,并且把常用属性定义为低位效率更高。 其次是数组(原因是遍历),再其次是set(影响原因是hash函数、hash扩容、二叉树节点转换),最差是stl之bitset(原因:本质也是数组)

    优化前的循环算法(数组):

     1 const int N = 128;
     2 class BitSet
     3 {
     4     public:
     5         BitSet()
     6         {
     7             memset(m_szBits,0,sizeof(m_szBits));
     8             m_bBitsDirty = false;
     9         }
    10         int Set(size_t i)
    11         {
    12             if(i >= 0 && i < N)
    13             {
    14                 ++m_szBits[i];
    15 
    16                 m_bBitsDirty = true;
    17 
    18             }
    19             return 0;
    20         }
    21         int Get(size_t i) const
    22         {
    23             if(i >= 0 && i < N)
    24             {
    25                 return m_szBits[i] > 0;
    26             }
    27             return 0;
    28         }
    29         void Clean()
    30         {
    31             memset(m_szBits,0,sizeof(m_szBits));
    32             m_bBitsDirty = false;
    33         }
    34         bool IsDirty() const
    35         {
    36             return m_bBitsDirty;
    37         }
    38     private:
    39         char * m_szBits[N];
    40         bool m_bBitsDirty;
    41 };
    View Code

    优化后的位运算:

     1 const int nLLLeng = 64;
     2 class NewBitSet
     3 {
     4     public:
     5         NewBitSet():llLow(0ull),llHight(0ull)
     6     {
     7     }
     8         void Set(size_t i)
     9         {
    10             if(i > 0 && i < nLLLeng)
    11             {
    12                 llLow |= 1ull << i;
    13             }
    14             else if (i < nLLLeng * 2)
    15             {
    16                 llHight |= 1ull << (i & 0x3F);    // 0x3F 是64的16进制,这样做是相当于减64
    17             }
    18         }
    19         void GetAllDirty(int * arrDirty, int & nMaxCount) const
    20         {
    21             unsigned long long nllLowTemp = llLow;
    22             unsigned long long nllHightTemp = llHight;
    23             nMaxCount = -1;
    24             while (nllLowTemp)
    25             {
    26                 arrDirty[++nMaxCount] = __builtin_ffsll(nllLowTemp) - 1;
    27                 nllLowTemp &= (nllLowTemp - 1);
    28             }
    29             while (nllHightTemp)
    30             {
    31                 arrDirty[++nMaxCount] = __builtin_ffsll(nllHightTemp) - 1 + nLLLeng;
    32                 nllHightTemp &= (nllHightTemp - 1);
    33             }
    34         }
    35         void Clean()
    36         {
    37             llLow = llHight = 0ull;
    38         }
    39 
    40         bool IsDirty() const
    41         {
    42             return llLow || llHight;
    43         }
    44     private:
    45         unsigned long long int llLow;
    46         unsigned long long int llHight;
    47 };
    View Code

    测试用例:

      1 #include <iostream>
      2 #include <sys/time.h>
      3 #include<stdlib.h>
      4 #include <algorithm>
      5 #include <math.h>
      6 #include <stdio.h>
      7 #include<vector>
      8 #include<map>
      9 #include <string.h>
     10 using namespace std;
     11 const int N = 128;
     12 class BitSet
     13 {
     14     public:
     15         BitSet()
     16         {
     17             memset(m_szBits,0,sizeof(m_szBits));
     18             m_bBitsDirty = false;
     19         }
     20         int Set(size_t i)
     21         {
     22             if(i >= 0 && i < N)
     23             {
     24                 ++m_szBits[i];
     25 
     26                 m_bBitsDirty = true;
     27 
     28             }
     29             return 0;
     30         }
     31         int Get(size_t i) const
     32         {
     33             if(i >= 0 && i < N)
     34             {
     35                 return m_szBits[i] > 0;
     36             }
     37             return 0;
     38         }
     39         void Clean()
     40         {
     41             memset(m_szBits,0,sizeof(m_szBits));
     42             m_bBitsDirty = false;
     43         }
     44         bool IsDirty() const
     45         {
     46             return m_bBitsDirty;
     47         }
     48     private:
     49         char * m_szBits[N];
     50         bool m_bBitsDirty;
     51 };
     52 
     53 
     54 const int nLLLeng = 64;
     55 class NewBitSet
     56 {
     57     public:
     58         NewBitSet():llLow(0ull),llHight(0ull)
     59     {
     60     }
     61         void Set(size_t i)
     62         {
     63             if(i > 0 && i < nLLLeng)
     64             {
     65                 llLow |= 1ull << i;
     66             }
     67             else if (i < nLLLeng * 2)
     68             {
     69                 llHight |= 1ull << (i & 0x3F);    // 0x3F 是64的16进制,这样做是相当于减64
     70             }
     71         }
     72         void GetAllDirty(int * arrDirty, int & nMaxCount) const
     73         {
     74             unsigned long long nllLowTemp = llLow;
     75             unsigned long long nllHightTemp = llHight;
     76             nMaxCount = -1;
     77             while (nllLowTemp)
     78             {
     79                 arrDirty[++nMaxCount] = __builtin_ffsll(nllLowTemp) - 1;
     80                 nllLowTemp &= (nllLowTemp - 1);
     81             }
     82             while (nllHightTemp)
     83             {
     84                 arrDirty[++nMaxCount] = __builtin_ffsll(nllHightTemp) - 1 + nLLLeng;
     85                 nllHightTemp &= (nllHightTemp - 1);
     86             }
     87         }
     88         void Clean()
     89         {
     90             llLow = llHight = 0ull;
     91         }
     92 
     93         bool IsDirty() const
     94         {
     95             return llLow || llHight;
     96         }
     97     private:
     98         unsigned long long int llLow;
     99         unsigned long long int llHight;
    100 };
    101 
    102 int nPrintCount = 1;
    103 
    104 void DirtyBit(int nRandCount)
    105 {
    106     NewBitSet tDirty;
    107     int nRand = 0;
    108     //srand((unsigned)time(0));
    109     for (int i = 0; i < nRandCount;i++)
    110     {
    111     //    nRand = rand()%126 + 1;
    112         tDirty.Set(i+1);
    113     }
    114     if (!tDirty.IsDirty())
    115     {
    116         return;
    117     }
    118     int arrDirty[nLLLeng * 2] = {0};
    119     //同步自己执行次数
    120     int nMaxCount = 0;
    121     tDirty.GetAllDirty(arrDirty, nMaxCount);
    122     nMaxCount = 0;
    123     //同步WS执行次数
    124     tDirty.GetAllDirty(arrDirty, nMaxCount);
    125 
    126     int nNotPrint = 0;
    127     for (int i = 0; i< nMaxCount; i++)
    128     {
    129         nNotPrint = arrDirty[i];
    130     }
    131     tDirty.Clean();
    132 }
    133 
    134 void DirtyArr(int nRandCount)
    135 {
    136     BitSet tDirty;
    137     int nRand = 0;
    138 //    srand((unsigned)time(0));
    139     for (int i = 0; i < nRandCount;i++)
    140     {
    141 //        nRand = rand()%126 + 1;
    142         tDirty.Set(i+1);
    143     }
    144     if (tDirty.IsDirty())
    145     {
    146         int arrDirty[N] = {0};
    147         int nMaxCount = -1;
    148         //同步自己执行次数
    149         for (int i = 0; i< N; ++i)
    150         {
    151             if (tDirty.Get(i))
    152             {
    153                 arrDirty[++nMaxCount] = i;
    154             }
    155         }
    156         //同步WS执行次数
    157         nMaxCount = -1;
    158         for (int i = 0; i< N; ++i)
    159         {
    160             if (tDirty.Get(i))
    161             {
    162                 arrDirty[++nMaxCount] = i;
    163             }
    164         }
    165         int nNotPrint = 0;
    166         for (int i = 0; i< nMaxCount + 1; i++)
    167         {
    168             nNotPrint = arrDirty[i];
    169         }
    170     }
    171 
    172     tDirty.Clean();
    173 }
    174 
    175 int main()
    176 {
    177     float time_use=0;
    178     struct timeval start;
    179     struct timeval end;
    180     int nTestCount =100 ;
    181     gettimeofday(&start,NULL);
    182 
    183     nPrintCount = 1;
    184     //处理过程--开始
    185     for (int i = 0; i< 10000; ++i)
    186     {
    187         DirtyBit(nTestCount);
    188     }
    189     //处理过程--结束
    190 
    191     cout<<endl;
    192     gettimeofday(&end,NULL);
    193     time_use=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);//微秒
    194     printf("time_use is %.10f
    ",time_use);
    195 
    196     nPrintCount = 1;
    197     gettimeofday(&start,NULL);
    198     //处理过程--开始
    199     for (int i = 0; i< 10000; ++i)
    200     {
    201         DirtyArr(nTestCount);
    202     }
    203     //处理过程--结束
    204 
    205     cout<<endl;
    206     gettimeofday(&end,NULL);
    207 
    208     time_use=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);//微秒
    209     printf("time_use is %.10f
    ",time_use);
    210     return 0;
    211 }
    View Code
  • 相关阅读:
    达梦数据库学习(二、管理数据库实例)
    达梦数据库学习(一、linux操作系统安装及数据库安装)
    SQL Server 数据库还原进度查看
    关于索引的学习(主要是聚集索引与非聚集索引)
    SQL Server批量向表中插入多行数据语句
    最大流-前置push-relabel算法实现
    调度算法(二)
    调度算法(一)
    软件工程:提问回顾
    软件工程:个人阅读作业与总结
  • 原文地址:https://www.cnblogs.com/workharder/p/11526200.html
Copyright © 2020-2023  润新知