用小数秒创建时间戳

时间:2019-03-26 13:58:51

标签: awk timestamp strftime

awk可以生成带有strftime函数的时间戳,例如

$ awk 'BEGIN {print strftime("%Y/%m/%d %H:%M:%S")}'
2019/03/26 08:50:42

但是我需要一个带有小数秒的时间戳,理想情况下可以降至纳秒。 gnu date可以使用%N元素:

$ date "+%Y/%m/%d %H:%M:%S.%N"
2019/03/26 08:52:32.753019800

但是与调用date相比,从awk内调用strftime效率相对较低,并且我需要高性能,因为我正在使用awk处理许多大文件并且在处理文件时需要生成许多时间戳。 awk是否可以有效地生成包括小数秒(理想情况下为纳秒,但可以接受毫秒)的时间戳?

添加我要执行的操作的示例:

awk -v logFile="$logFile" -v outputFile="$outputFile" '
BEGIN {
   print "[" strftime("%Y%m%d %H%M%S") "] Starting to process " FILENAME "." >> logFile
}
{
    data[$1] += $2
}
END {
    print "[" strftime("%Y%m%d %H%M%S") "] Processed " NR " records." >> logFile
    for (id in data) {
        print id ": " data[id] >> outputFile
    }
}
' oneOfManyLargeFiles

2 个答案:

答案 0 :(得分:2)

如果您确实需要亚秒级的计时,那么对外部命令(如date的任何调用或读取外部系统文件(如/proc/uptime/proc/rct的调用都将无法达到目的)亚秒精度。两种情况都需要大量资源来检索所请求的信息(即时间)

由于OP已经使用GNU awk,因此可以使用动态扩展。动态扩展是一种通过实现用C或C ++编写的新函数并使用gawk动态加载它们来向awk添加新功能的方法。 GNU awk manual中广泛记录了如何编写这些功能。

幸运的是,GNU awk 4.2.1附带了一组默认动态库,可以随意加载它们。这些库之一是time库,它具有两个简单的功能:

  

the_time = gettimeofday()   以秒为单位返回自1970-01-01 UTC以来经过的时间(以秒为单位)。如果时间在该平台上不可用,请返回-1并设置ERRNO返回的时间应具有亚秒精度,但实际精度可能会因平台而异。如果标准C gettimeofday()系统调用在此平台上可用,则它仅返回该值。否则,如果在MS-Windows上,它将尝试使用GetSystemTimeAsFileTime()

     

result = sleep(seconds)   尝试睡眠seconds秒。如果seconds为负,或尝试睡眠失败,请返回-1并设置ERRNO。否则,在指定的时间内睡眠后返回零。请注意,秒可能是浮点(非整数)值。实现细节:根据平台的可用性,此函数尝试使用nanosleep()select()来实现延迟。

     

来源:GNU awk manual

现在可以以相当简单的方式调用此函数:

awk '@load "time"; BEGIN{printf "%.6f", gettimeofday()}'
1553637193.575861

为了证明该方法比更经典的实现更快,我使用gettimeofday()对所有3个实现进行了计时:

awk '@load "time"
     function get_uptime(   a) {
        if((getline line < "/proc/uptime") > 0)
        split(line,a," ")
        close("/proc/uptime")
        return a[1]
     }
     function curtime(    cmd, line, time) {
        cmd = "date \047+%Y/%m/%d %H:%M:%S.%N\047"
        if ( (cmd | getline line) > 0 ) {
           time = line
        }
        else {
           print "Error: " cmd " failed" | "cat>&2"
        }
        close(cmd)
        return time
      }
      BEGIN{
        t1=getimeofday(); curtime(); t2=gettimeofday();
        print "curtime()",t2-t1
        t1=getimeofday(); get_uptime(); t2=gettimeofday();
        print "get_uptime()",t2-t1
        t1=getimeofday(); gettimeofday(); t2=gettimeofday();
        print "gettimeofday()",t2-t1
      }'

输出:

curtime() 0.00519109
get_uptime() 7.98702e-05
gettimeofday() 9.53674e-07

虽然curtime()在加载外部二进制文件时最慢,但令人惊讶的是看到awk在处理额外的外部/ proc /文件方面速度飞快。

答案 1 :(得分:1)

如果您使用的是Linux,则可以使用/proc/uptime

$ cat /proc/uptime 
123970.49 354146.84

得到一些厘秒(第一个值是正常运行时间),并计算开始时间与发生任何事情之间的时间差:

$ while true ; do echo ping ; sleep 0.989 ; done |        # yes | awk got confusing
awk '
function get_uptime(   a) {
    if((getline line < "/proc/uptime") > 0)
        split(line,a," ")
    close("/proc/uptime")
    return a[1]
}
BEGIN {
    basetime=get_uptime()                    
}
{
    if(!wut)                                 # define here the cause
        print get_uptime()-basetime          # calculate time difference
}'

输出:

0
0.99
1.98
2.97
3.97