用小数秒创建时间戳
Create timestamp with fractional seconds
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
但是与调用 strftime
相比,从 awk
中调用 date
的效率相对较低,而且我需要高性能,因为我正在使用 [=13] 处理许多大文件=] 并且需要在处理文件时生成许多时间戳。有没有一种方法 awk
可以有效地生成包含小数秒的时间戳(理想情况下是纳秒,但毫秒也是可以接受的)?
添加我正在尝试执行的示例:
awk -v logFile="$logFile" -v outputFile="$outputFile" '
BEGIN {
print "[" strftime("%Y%m%d %H%M%S") "] Starting to process " FILENAME "." >> logFile
}
{
data[] +=
}
END {
print "[" strftime("%Y%m%d %H%M%S") "] Processed " NR " records." >> logFile
for (id in data) {
print id ": " data[id] >> outputFile
}
}
' oneOfManyLargeFiles
如果你在 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, line) {
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
如果你真的需要亚秒级的计时,那么任何调用外部命令如date
或读取外部系统文件如/proc/uptime
或/proc/rct
都会打败亚秒级精度的目的。这两种情况都需要很多资源来检索请求的信息(即时间)
由于 OP 已经使用 GNU awk,您可以使用动态扩展。动态扩展是一种通过实现用 C 或 C++ 编写的新函数并用 gawk 动态加载它们来向 awk 添加新功能的方法。 GNU awk manual.
中详细记录了如何编写这些函数
幸运的是,GNU awk 4.2.1 自带一组默认的动态库,可以随意加载。这些库之一是具有两个简单函数的 time
库:
the_time = gettimeofday()
Return the time in seconds that has elapsed since 1970-01-01 UTC as a floating-point value. If the time is unavailable on this platform, return -1
and set ERRNO
. The returned time should have sub-second precision, but the actual precision may vary based on the platform. If the standard C gettimeofday()
system call is available on this platform, then it simply returns the value. Otherwise, if on MS-Windows, it tries to use GetSystemTimeAsFileTime()
.
result = sleep(seconds)
Attempt to sleep for seconds
seconds. If seconds
is negative, or the attempt to sleep fails, return -1
and set ERRNO
. Otherwise, return zero after sleeping for the indicated amount of time. Note that seconds may be a floating-point (nonintegral) value. Implementation details: depending on platform availability, this function tries to use nanosleep()
or select()
to implement the delay.
source: 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 7+%Y/%m/%d %H:%M:%S.%N7"
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/ 文件时速度快得惊人。
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
但是与调用 strftime
相比,从 awk
中调用 date
的效率相对较低,而且我需要高性能,因为我正在使用 [=13] 处理许多大文件=] 并且需要在处理文件时生成许多时间戳。有没有一种方法 awk
可以有效地生成包含小数秒的时间戳(理想情况下是纳秒,但毫秒也是可以接受的)?
添加我正在尝试执行的示例:
awk -v logFile="$logFile" -v outputFile="$outputFile" '
BEGIN {
print "[" strftime("%Y%m%d %H%M%S") "] Starting to process " FILENAME "." >> logFile
}
{
data[] +=
}
END {
print "[" strftime("%Y%m%d %H%M%S") "] Processed " NR " records." >> logFile
for (id in data) {
print id ": " data[id] >> outputFile
}
}
' oneOfManyLargeFiles
如果你在 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, line) {
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
如果你真的需要亚秒级的计时,那么任何调用外部命令如date
或读取外部系统文件如/proc/uptime
或/proc/rct
都会打败亚秒级精度的目的。这两种情况都需要很多资源来检索请求的信息(即时间)
由于 OP 已经使用 GNU awk,您可以使用动态扩展。动态扩展是一种通过实现用 C 或 C++ 编写的新函数并用 gawk 动态加载它们来向 awk 添加新功能的方法。 GNU awk manual.
中详细记录了如何编写这些函数幸运的是,GNU awk 4.2.1 自带一组默认的动态库,可以随意加载。这些库之一是具有两个简单函数的 time
库:
the_time = gettimeofday()
Return the time in seconds that has elapsed since 1970-01-01 UTC as a floating-point value. If the time is unavailable on this platform, return-1
and setERRNO
. The returned time should have sub-second precision, but the actual precision may vary based on the platform. If the standard Cgettimeofday()
system call is available on this platform, then it simply returns the value. Otherwise, if on MS-Windows, it tries to useGetSystemTimeAsFileTime()
.
result = sleep(seconds)
Attempt to sleep forseconds
seconds. Ifseconds
is negative, or the attempt to sleep fails, return-1
and setERRNO
. Otherwise, return zero after sleeping for the indicated amount of time. Note that seconds may be a floating-point (nonintegral) value. Implementation details: depending on platform availability, this function tries to usenanosleep()
orselect()
to implement the delay.source: GNU awk manual
现在可以以相当直接的方式调用此函数:
awk '@load "time"; BEGIN{printf "%.6f", gettimeofday()}'
1553637193.575861
为了证明此方法比更经典的实现更快,我使用 gettimeofday()
:
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 7+%Y/%m/%d %H:%M:%S.%N7"
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/ 文件时速度快得惊人。