lifan's blog

  • 首页

  • 分类

  • 归档

  • 关于

高效Timer-时间轮算法

发表于 2020-01-10 | 分类于 algorithm

定时器在游戏服务器中使用得非常普遍,它的效率直接影响了服务器的性能。对于服务器程序来说只有理解定时器的原理和细节才能更好的使用定时器,做到心中有数。在前面的文章中已经介绍过一种定时器算法-时间堆,本文介绍另一种定时器算法-时间轮。

一、时间轮(Timing-Wheel)算法原理
阅读全文 »

Golang Sync.Map 源码分析

发表于 2019-12-11 | 分类于 golang

Golang中存在2种map, 一种是常规的非线程安全map,另一种是线程安全的sync.map。在golang1.9以前,我们在项目中是通过数组、map、sync.RWMutex来实现普通map的并发读写(采用map数组,把key hash到相应的map,每个map单独加锁以降低锁的粒度),那么golang sync.map是如何实现线程安全的呢?

一、原理

通过2个map(read、dirty)来实现读写分离,read、dirty 指向同一个entity。

阅读全文 »

TCP/IP学习笔记

发表于 2019-11-20 | 分类于 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 源码探索及常见问题

发表于 2019-10-30 | 分类于 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 源码分析

发表于 2019-10-30 | 分类于 golang

slice是golang使用频率最高的结构之一,如果不知道它的实现原理,很容易出现”莫名其妙”的bug。

一、定义

slice是一个结构体, 定义如下

1
2
3
4
5
type slice struct {
array unsafe.Pointer //数组首地址指针
len int //长度
cap int //容量
}

slice可以看成是对数组的封装,底层数据结构是数组。slice结构体成员的含义分别为:
array:指向数组首地址的指针

阅读全文 »

Mesh寻路

发表于 2019-10-12 | 分类于 algorithm

一、几何知识

1.1 判断点与直线的关系
  • 向量叉乘
    已知直线上两点p1(x1,y1), p2(x2,y2),测试点t(x,y),设p1,p2所在的向量为v1, p1t所在的向量为v2。则可以通过v1 x v2来判断点t与直线p1、p2的关系。当:
    v1 x v2 > 0 :v2在v1逆时针方向(左侧)
    v1 x v2 < 0 :v2在v1顺时针方向(右侧)
    v1 x v2 = 0 :v2与v1平行(由于起点相同,v1、v2共线)

  • 解直线方程
    已知直线上的两点p1(x1,y1) p2(x2,y2), p1 p2两点不重合。则直线的一般式方程AX+BY+C=0,结合两点式可得出,其中A B C分别为:

    阅读全文 »

Golang内存分配

发表于 2019-09-25 | 分类于 golang

最近项目做上线前的压力测试,遇到一个”诡异”的问题,GameServer进程持有内存,即使在所有机器人下线后一段时间,内存依然没有归还OS。

问题描述

服务器启动后,内存占用大概600M,此时机器人开始陆续上线,服务器的内存使用逐渐增加,最高达到11GB。 大概持续1个小时后,机器人开始陆续下线,机器人全部下线后GameServer进程的RSS竟丝毫没有下降。当时有些困惑,Golang GC最迟2分钟就会触发1次,是程序BUG? 还是垃圾回收没触发?

内存采样

  1. top命令查看, RSS(RES)为11GB
  2. pprof对内存heap和allocs数据采样,发现inuse_space不到1GB
  3. 输出进程运行时信息, HeapSys(从OS分配的堆内存), HeapAlloc(进程已用内存), HeapIdle(未使用的内存), 分别为11GB, 0.8GB, 10.2GB

从内存采样结果来看,基本可以排除程序Bug和GC没触发这两种情况。

阅读全文 »
12

17 日志
4 分类
© 2022
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Gemini v7.1.2