Pypy中islower()和isupper()的性能
我有一个程序,其中调用了 str.isupper()
方法,这个调用在一个非常紧凑的循环中进行,结果占用了我运行时间的约25%。
我发现 isupper
和 islower
这两个方法比其他的 isX
方法,比如 isalnum
、isalpha
和 isdigit
等要慢得多。(注意:在 cpython 中,所有这些方法的速度都是一样的。)
$ pypy -mtimeit "'a'.islower()" - 0.0158 usec per loop
$ pypy -mtimeit "'a'.isalpha()" - 0.00251 usec per loop
$ pypy -mtimeit "'a'.isupper()" - 0.0164 usec per loop
$ pypy -mtimeit "'a'.isdigit()" - 0.00236 usec per loop
我自己可以做一个更快的 isupper
方法,方法是
isupper = lambda c: 'A' <= c <= 'Z'
这个方法每次循环的运行时间大约是 0.00393 微秒
。当然,这个版本对 unicode 字符串不适用,但我的字符串肯定都是 8 位的 ASCII 字符。
我的问题是,有没有办法让 Python 跳过那些复杂的 unicode 检测,直接处理简单的 'a-z' 字符呢?
1 个回答
0
我不知道为什么会有这样的差别,但我知道这些基准测试有问题。像 "a".islower()
这样的表达式在循环中会被优化掉,完全消失了……你不如直接测量 pass
的时间。
我们可以确认 "a".isalpha()
和 pass
的执行速度是完全一样的:就是一个空循环的速度。至于 "a".islower()
,我不太明白为什么,有时候它的速度也会比我预期的慢,有时候又不会——尽管我们可以确认它总是在测量一个空循环的速度(如果你感兴趣,可以看看“jitviewer”)。这真是CPU的奥秘吗?
(注意,这些是在一个非常新的pypy上测量的;之前,islower() 和 isupper() 没有进行优化,所以没有被优化掉。)