Python 用于持续时间计算的时间戳快速转换

Python 用于持续时间计算的时间戳快速转换,python,performance,python-2.7,Python,Performance,Python 2.7,我们有一个日志分析器,它可以解析100GBs左右的日志(我的测试文件约为2000万行,1.8GB)。它花费的时间比我们想要的要长(超过半天),所以我对cProfile运行了它,并且超过75%的时间是由strTime占用的: 1 0.253 0.253 560.629 560.629 <string>:1(<module>) 20000423 202.508 0.000 352.246 0.000 _strptime.py:29

我们有一个日志分析器,它可以解析100GBs左右的日志(我的测试文件约为2000万行,1.8GB)。它花费的时间比我们想要的要长(超过半天),所以我对cProfile运行了它,并且超过75%的时间是由strTime占用的:

       1    0.253    0.253  560.629  560.629 <string>:1(<module>)
20000423  202.508    0.000  352.246    0.000 _strptime.py:299(_strptime)
其中,
otime
是前一行的时间戳

日志文件的格式如下:

0000 | 774 | 475      | 2017-03-29 00:06:47 | M      |        63
0001 | 774 | 475      | 2017-03-29 01:09:03 | M      |        63
0000 | 774 | 475      | 2017-03-29 01:19:50 | M      |        63
0001 | 774 | 475      | 2017-03-29 09:42:57 | M      |        63
0000 | 775 | 475      | 2017-03-29 10:24:34 | M      |        63
0001 | 775 | 475      | 2017-03-29 10:33:46 | M      |        63    
对测试文件运行它几乎需要10分钟

strtime()
替换为此(从):

把时间缩短到3分钟多一点

cProfile再次报告:

       1    0.265    0.265  194.538  194.538 <string>:1(<module>)
20000423   62.688    0.000   62.688    0.000 analyzer.py:88(to_datetime)
10.2650.265194.538194.538:1()
20000423 62.688 0.000 62.688 0.000分析仪。py:88(截止日期时间)
整个分析器运行此转换仍需要大约三分之一的时间。In-Line将转换占用的空间减少了约20%,但我们仍在寻找处理这些行的25%的时间是将时间戳转换为
datetime
格式(其中
total_seconds()


我可能最终只是编写一个自定义时间戳到秒的转换,以完全绕过
日期时间
,除非有人有另一个好主意?

所以我一直在寻找,我发现一个模块做得非常好:

介绍:

其中,通过cProfile:

       1    0.254    0.254  123.795  123.795 <string>:1(<module>)
20000423    4.188    0.000    4.188    0.000 {ciso8601.parse_datetime}
10.254 0.254 123.795 123.795:1()
20000423 4.188 0.000 4.188 0.000{ciso8601.parse_datetime}

这比通过
datetime.strtime()
实现的简单方法快约84倍。。。考虑到它们,这并不奇怪。

您还可以做两件事(速度不快,但至少编码起来很方便):


您是否检查过这3分钟中有多少时间用于反复实例化
datetime
,而不是解析数据我不确定你是否可以在不改变方法的情况下进一步提高它。。。就像多处理或者只是不为每行创建一个
datetime
。你考虑过吗?@Art~25%的时间都花在解析和实例化
datetime
对象上,这就是问题所在。@PeterWood是的,我不太熟悉,但是如果你有一个解决方案可以为未初始化的人维护,我会感兴趣。这只会提高我们的处理时间。除了时间戳格式不同之外,我会将其作为的副本关闭。
因为它是作为C模块编写的,所以速度要快得多。
:显然,如果您的字符串表示是ISO,并且您可以在您的平台上编译该模块,这是一个很好的解决方案。并不是每个在这个问题上绊倒的人都会处于这种情况。不过,这是一个很好的发现,可能对大多数人都很有用。@JohnY考虑到性能的提升,如果它不能击败大多数其他方法,即使您必须先将字符串转换为ISO8601,我也会感到惊讶。对于一些人来说,您必须编译C模块的要求将成为阻止其使用的障碍。@JohnY您可以通过
pip install ciso8601
安装它。。。但如果你有其他选择的话,我还是愿意的。
       1    0.265    0.265  194.538  194.538 <string>:1(<module>)
20000423   62.688    0.000   62.688    0.000 analyzer.py:88(to_datetime)
from ciso8601 import parse_datetime
...
ltime = parse_datetime(sline[time_col].strip())
       1    0.254    0.254  123.795  123.795 <string>:1(<module>)
20000423    4.188    0.000    4.188    0.000 {ciso8601.parse_datetime}
from dateutil.parser import parse, isoparse

parse(s)  # quite slow, but more flexible
isoparse(s)  # faster, but requires iso format and not as fast as cisco8601