首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Golang在Linux系统中实现微秒级延迟

Golang在Linux系统中实现微秒级延迟

作者头像
用户1422397
发布于 2021-12-08 09:24:46
发布于 2021-12-08 09:24:46
1270
举报
文章被收录于专栏:centosDaicentosDai

在程序中延迟或者等待一段时间一般可以使用Sleep函数实现,但是因为操作系统线程调度的消耗,往往只能做到十几或者数十毫秒的精度,很难达到微秒级,Golang的time.Sleep也是如此。

Sleep函数一般都会将当前线程从CPU让出,然后等待操作系统的重新调度,这样可以有效利用CPU资源,但也是Sleep时间精度不高的“罪魁祸首”。因为操作系统线程调度并不是实时的,它会先对线程排队,然后在合适的时机才进行真正的CPU切换,我们可以想象还会有队列优先级以及插队的情况存在。

那么如何才能降低到微秒级呢?本着有现成的就不造轮子的原则,我找遍了各个技术角落也没有找到,当然很可能有遗漏的地方。不过虽然没有Golang的实现,但是找到了一些C语言版本的延迟函数。参考它们,我实现了Golang的版本,代码如下:

1234567891011

func DelayMicroseconds(us int64) {    var tv syscall.Timeval    _ = syscall.Gettimeofday(&tv)     stratTick := int64(tv.Sec)*int64(1000000) + int64(tv.Usec) + us    endTick := int64(0)    for endTick < stratTick {        _ = syscall.Gettimeofday(&tv)        endTick = int64(tv.Sec)*int64(1000000) + int64(tv.Usec)    }}

你可能会说,这不就是一个死循环吗?!是的,这就是一个死循环,也因此它的名字是Delay,而不是Sleep。

这是目前找到的最好的实现方式了,虽然会导致CPU繁忙,但是也只是在短暂的微秒级别,有时候还是能接受的。

天空飘来五个字,那都不是事,是事也就烦一会,一会就没事。

这里边通过系统调用获取了精确到微秒级别的当前时间,然后通过循环不断获取当前时间,与deadline进行比较,在达到或超出deadline时跳出循环,最终实现了指定微秒的时间延迟。

经过实测这个函数在Linux上可以实现微秒级别的延迟,不过虽然Windows上也有Gettimeofday的系统调用,但是最低只能做到大概500us左右的延迟,通过看源码内部实现机制差别很大。

如果你有更好的方法,欢迎指正。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档