Pypy中islower()和isupper()的性能

1 投票
1 回答
770 浏览
提问于 2025-04-17 21:36

我有一个程序,其中调用了 str.isupper() 方法,这个调用在一个非常紧凑的循环中进行,结果占用了我运行时间的约25%。

我发现 isupperislower 这两个方法比其他的 isX 方法,比如 isalnumisalphaisdigit 等要慢得多。(注意:在 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() 没有进行优化,所以没有被优化掉。)

撰写回答