gf框架之并发安全容器 – gmap,以及与sync.Map的性能比较

gf框架提供了几个非常实用的并发安全容器,其中gmap就是项目开发中最常用的一个。

gmap具体的方法请参考godoc:https://godoc.org/github.com/johng-cn/gf/g/container/gmap

gmap内部有多个类型结构体定义,包括:IntBoolMapIntIntMapIntInterfaceMapIntStringMapInterfaceInterfaceMapStringBoolMapStringIntMapStringInterfaceMapStringStringMapUintInterfaceMap

从执行效率上考虑,基于不同的需求场景,选择合适的类型结构体,其执行效率是不一样的,以下使用基准测试来对比各个类型的写入性能(测试代码):

Continue reading “gf框架之并发安全容器 – gmap,以及与sync.Map的性能比较”

gkvdb v2.0发布,性能改进及高可用版本

项目地址:https://gitee.com/johng/gkvdb

距离在开源中国发布的gkvdb v1.81已经过去了近3个月,在这三个月中gkvdb也变得越来越成熟稳定,本次发布最大的两点在于gkvdb的性能改进以及高可用特性。

其中,性能改进主要是针对于gf框架改进的一些对应的协调改进工作,以及将同步机制从定时同步调整为使用golang的channel实现的实时同步,提高了同步的效率。

高可用特性保证了在任何的情况下,只要API调用成功,那么这条数据即是成功,处理结果在任何异常情况下也不会发生改变,该特性使得gkvdb可以被推广使用到更复杂的生产环境中,保证写入数据的稳定可靠。特别是,gkvdb经过了严格的并发安全测试,在高并发的环境下也表现得非常出色。

自己的博客,本次发布信息也就这些吧。

gf框架之gparser – 强大灵活的数据格式编码/解析包

gf框架针对常用的数据格式编码解析,提供了异常强大灵活的功能,由gparser包提供,支持Go变量(interface{})、Struct、JSON、XML、YAML/YML、TOML数据格式之间的相互转换,支持按照层级进行数据检索访问、支持运行时动态新增/修改/删除层级变量(并发安全)等特性。gparser包使得对于未知数据结构、多维数组结构的访问、操作变得异常的简便。
Continue reading “gf框架之gparser – 强大灵活的数据格式编码/解析包”

gf框架之gvalid – 强大灵活的数据校验/表单校验模块

gf提供了非常强大易用的数据校验功能,通过gvalid包提供,封装了40种常用的校验规则,支持单数据多规则校验、多数据多规则批量校验、自定义错误信息、自定义正则校验等特性。由于gf是模块化、低耦合设计,gvalid包也可以在项目中单独引入使用。

使用方式:

Continue reading “gf框架之gvalid – 强大灵活的数据校验/表单校验模块”

gf框架之grpool – 高性能的goroutine池

Go语言中的goroutine虽然相对于系统线程来说比较轻量级,但是在高并发量下的goroutine频繁创建和销毁对于性能损耗以及GC来说压力也不小。充分将goroutine复用,减少goroutine的创建/销毁的性能损耗,这便是grpool对goroutine进行池化封装的目的。例如,针对于100W个执行任务,使用goroutine的话需要不停创建并销毁100W个goroutine,而使用grpool也许底层只需要几千个goroutine便能充分复用地执行完成所有任务。经测试,在高并发下grpool的性能比原生的goroutine高出几倍到数百倍!并且随之也极大地降低了内存使用率。

性能测试报告:http://johng.cn/grpool-performance/ Continue reading “gf框架之grpool – 高性能的goroutine池”

grpool协程池(goroutine池)性能测试

Go语言中的goroutine虽然相对于系统线程来说比较轻量级,但是在高并发量下的goroutine频繁创建和销毁对于性能损耗以及GC来说压力也不小。充分将goroutine复用,减少goroutine的创建/销毁的性能损耗,这便是grpool对goroutine进行池化封装的目的。例如,针对于100W个执行任务,使用goroutine的话需要不停创建并销毁100W个goroutine,而使用grpool也许底层只需要几千个goroutine便能充分复用地执行完成所有任务。经测试,在高并发下grpool的性能比原生的goroutine高出几倍到数百倍!并且随之也极大地降低了内存使用率。 Continue reading “grpool协程池(goroutine池)性能测试”

Go学习整理笔记

最近整理一下Go学习中的一些要点,包括Go性能优化及底层源码要点,作此笔记,巩固基础。

一、并发

1、Go语言的goroutine类似于线程和协程的综合体,能最大限度提升执行效率,发挥多核处理能力;

2、通常情况下,用多进程来实现分布式负载均衡,减轻单进程垃圾回收压力;用多线程(LWP)抢夺更多的处理器资源;用协程来提高处理器时间片利用率;

3、相比较系统默认MB级别的线程栈,goroutine自定义栈初始仅需2KB,所以才能创建成千上万的并发任务。自定义栈采用按需分配策略,在需要时进行扩容,最大能到GB规模;

4、Go在运行时可能会创建很多线程,但任何时候仅有限的几个线程参与并发任务执行。该量默认与处理器核数相等,可用runtime.GOMAXPROCS函数或者环境变量修改;

5、通道:

         1)、通道(channel)相当于一个并发安全的队列;

         2)、goroutine leak是指goroutine处于发送或者接受阻塞状态,但一直未被唤醒,垃圾回收器并不收集此类资源,导致它们会在队列里长期休眠,形成资源泄露;

6、同步:

         1)、通道并不是用来取代锁的,它们有各自不同的使用场景。通道倾向于解决逻辑层次的并发处理架构,而锁则用来保护局部范围的数据安全;

         2)、将Mutex作为匿名字段时,相关方法必须实现为pointer-receiver模式,否则会因为复制导致锁机制失效;

         3)、应将Mutex锁粒度控制在最小范围内,及早释放;

7、建议:

         1)、对性能要求较高时,应避免使用defer Unlock;

         2)、读写并发时,用RWMutex性能会更好一些;

         3)、对单个数据读写保护,可尝试用原子操作;

         4)、执行严格测试,尽可能打开数据竞争检查;

Continue reading “Go学习整理笔记”

GO性能优化小结

1 内存优化

1.1 小对象合并成结构体一次分配,减少内存分配次数

做过C/C++的同学可能知道,小对象在堆上频繁地申请释放,会造成内存碎片(有的叫空洞),导致分配大的对象时无法申请到连续的内存空间,一般建议是采用内存池。Go runtime底层也采用内存池,但每个span大小为4k,同时维护一个cache。cache有一个0到n的list数组,list数组的每个单元挂载的是一个链表,链表的每个节点就是一块可用的内存,同一链表中的所有节点内存块都是大小相等的;但是不同链表的内存大小是不等的,也就是说list数组的一个单元存储的是一类固定大小的内存块,不同单元里存储的内存块大小是不等的。这就说明cache缓存的是不同类大小的内存对象,当然想申请的内存大小最接近于哪类缓存内存块时,就分配哪类内存块。当cache不够再向spanalloc中分配。

建议:小对象合并成结构体一次分配,示意如下:

替换为:

Continue reading “GO性能优化小结”

Go测试之性能监控与代码覆盖率

1、测试运行记录

在硬件环境方面,主要考察计算机的负载状况,比如CPU使用率内存使用率磁盘使用情况等。
在软件系统方面,主要包括内存分配并发处理数量死锁等情况

(1).收集资源使用情况

与收集资源使用情况有关的标记

标记名称 标记描述
-cpuprofile cpu.out 记录CPU使用情况,并写到指定的文件中,直到测试退出。
cpu.out作为指定文件的文件名可以被其他任何名称代替
-memprofile mem.out 记录内存使用情况,并在所有测试通过后将内存使用概要写到指定的文件中。
mem.out作为指定文件的文件名可以被其他任何名称代替
-memprofilerate n 此标记控制着记录内存分配操作的行为,这些记录将会被写到内存使用概要文件中。
N代表着分析器的取样间隔,单位为字节。每当有n个字节的内存被分配时,分析器就会取样一次

Continue reading “Go测试之性能监控与代码覆盖率”

Go性能优化:接口性能

接口的用途无需多言。但这并不意味着可在任何场合使用接口,要知道通过接口调用和普通调用存在很大差别。首先,相比静态绑定,动态绑定性能要差很多;其次,运行期需额外开销,比如接口会复制对象,哪怕仅是个指针,也会在堆上增加一个需 GC 处理的目标。




Continue reading “Go性能优化:接口性能”