定时器在游戏服务器中使用得非常普遍,它的效率直接影响了服务器的性能。对于服务器程序来说只有理解定时器的原理和细节才能更好的使用定时器,做到心中有数。在前面的文章中已经介绍过一种定时器算法-时间堆,本文介绍另一种定时器算法-时间轮。
Golang Sync.Map 源码分析
发表于
|
分类于
golang
TCP/IP学习笔记
发表于
|
分类于
protocal
TCP/IP采用分层设计,从下到上分别为物理层、数据链路层、网络层、传输层、应用层。发送数据时,应用层把数据交给传输层,传输层加上自己的包头,再交给网层每层加上自己的包头后,把数据发送到网络中,当数据到达目的后,再一层层的拆包,最终交给接收缓冲区,并通知应用层读取。下面简要介绍TCP从建立连接到传输数据的流程。
一、名词解释
- MTU(Maximum Transmission Unit,最大传输单元):在RFC894中规定MTU的最大值为1500字节。MTU = IP包头 + TCP包头 + MSS,一般建议MSS<1400字节(1500-IP包头20-TCP包头20-可选项),如果超过1400字节,就可能产生ip分片。
- MSS(TCP Maximum Segment Size,TCP最大报文段长度):表示TCP一次性可往另一端发送数据的最大数据长度(不包含包头)。如果单次发送数据超过MSS,且没有设置DF(Dont’t Frament)标志,就会产生IP分片。
Golang Timer 源码探索及常见问题
发表于
|
分类于
golang
最近使用golang timer时写出了bug, 为了避免再出现类似问题以及对goalng timer实现细节的好奇,阅读了一遍timer的源码。golang timer使用的是时间堆算法。
一、 时间堆算法原理
时间堆算法的底层数据结构是基于数组的小顶堆,任意一个节点的值比其孩子节点值小,堆中最小元素总是位于根节点。用于定时器的堆一般为2叉堆或4叉堆。Golang Timer使用的是桶(Bucket)+4叉堆,每个桶包含1个4叉小顶堆。
- 节点访问
- 堆是一棵完全二叉树(N叉树),因此可以很方便的用二维数组来表示,在数组起始位置为0的4叉堆中:
- 任意节点i的父节点为:
p := (i - 1) / 4
- 任意节点i的左孩子点为:
lc := i*4 + 1
Golang Slice 源码分析
发表于
|
分类于
golang
Mesh寻路
发表于
|
分类于
algorithm
Golang内存分配
发表于
|
分类于
golang
最近项目做上线前的压力测试,遇到一个”诡异”的问题,GameServer进程持有内存,即使在所有机器人下线后一段时间,内存依然没有归还OS。
问题描述
服务器启动后,内存占用大概600M,此时机器人开始陆续上线,服务器的内存使用逐渐增加,最高达到11GB。 大概持续1个小时后,机器人开始陆续下线,机器人全部下线后GameServer进程的RSS竟丝毫没有下降。当时有些困惑,Golang GC最迟2分钟就会触发1次,是程序BUG? 还是垃圾回收没触发?
内存采样
- top命令查看, RSS(RES)为11GB
- pprof对内存heap和allocs数据采样,发现inuse_space不到1GB
- 输出进程运行时信息, HeapSys(从OS分配的堆内存), HeapAlloc(进程已用内存), HeapIdle(未使用的内存), 分别为11GB, 0.8GB, 10.2GB
从内存采样结果来看,基本可以排除程序Bug和GC没触发这两种情况。