swoole / rfc

Swoole 提案
116 stars 3 forks source link

能否提供缓存时间戳功能并暴露对应的API给PHP侧,以减少当前获取时间戳时的系统调用 #72

Closed Appla closed 4 years ago

Appla commented 4 years ago

背景

  1. 有大量的需求获取精度要求不高的时间戳
  2. PHP内提供的获取时间的函数time,microtime,gettimeofday都是通过系统调用获取时间的, 系统调用相对纯用户态取数据来说代价稍微昂贵

需求

  1. 提供时间缓存功能, 提供类似nginx的设定,可以设置时间的解析间隔,缓存的时间仅在特定事件或者特定时间后更新
  2. 提供获取缓存时间戳的函数,提供更新相关数据的函数

参考

  1. http://nginx.org/en/docs/ngx_core_module.html#timer_resolution
  2. https://github.com/openresty/lua-nginx-module#ngxnow
oraoto commented 4 years ago

Linux 下, gettimeofday 系统调用是通过 vDSO 提供的,是不需要进入内核态的。

简单测试:https://3v4l.org/HEXFF ,时间缓存(近似 gc_enabled())能比 microtime 减少 70% 时间,但是 microtime 本身就很快了,感觉收益不大。

twose commented 4 years ago

Swoole4底层正好移除了定时器时间缓存, 改为直接使用系统调用获取(理由同上), 性能方面没有太大差异(大到不可接受), 并且缓存的时间精度很差

matyhtf commented 4 years ago

在 Linux 系统下,time、microtime、gettimeofday 都已经被优化过了,没有系统调用,是直接读取内存的。

使用 C 代码进行测试,直接使用 time 函数和使用内存缓存,性能上没有任何差别。

test1

#include <time.h>

int main() {
    for (int i=0; i< 10000000; i++) {
        time_t t = time(NULL);
    }
    return 0;
}

test2

#include <time.h>

time_t g_time;

time_t get_time(void *ptr) {
    if (ptr) {
        return time(ptr);
    }
    return g_time;
}

int main() {
    g_time = time(NULL);
    for (int i=0; i< 10000000; i++) {
        time_t t = get_time(NULL);
    }
    return 0;
}

测试

swoole@LAPTOP-0K15EFQI:~/swoole/examples/debug$ gcc -O0 -o test2 t2.c
swoole@LAPTOP-0K15EFQI:~/swoole/examples/debug$ gcc -O0 -o test1 t1.c
swoole@LAPTOP-0K15EFQI:~/swoole/examples/debug$ time ./test1

real    0m0.050s
user    0m0.031s
sys     0m0.011s
swoole@LAPTOP-0K15EFQI:~/swoole/examples/debug$ time ./test2

real    0m0.053s
user    0m0.044s
sys     0m0.001s
swoole@LAPTOP-0K15EFQI:~/swoole/examples/debug$