从映射连接字符串时的性能
Posted
技术标签:
【中文标题】从映射连接字符串时的性能【英文标题】:Performance while joining strings from mapping 【发布时间】:2020-09-08 10:36:32 【问题描述】:我在从映射 (Mapping[str, str]
) 连接字符串时查看性能。
我有这两个简单的功能:
def nested(sequence, mapping):
string = ""
for x in sequence:
string += mapping[x]
return string
和
def flat(sequence, mapping):
return "".join(mapping[x] for x in sequence)
在我的项目中,我发现使用“平面”解决方案时性能明显下降。最初,我选择该解决方案是因为:“平面比嵌套更好。”,但很快就转向了“嵌套”解决方案。
我用更简单的序列和映射进行了 timeit 测试:
letters = (
"a","b","c","d","e","f","g","h","i","j","k","l","m",
"n","o","p","q","r","s","t","u","v","w","x","y","z"
)
mymapping = x: x for x in letters
mysequence = "mysequence"
print(timeit.timeit("nested(mysequence, mymapping)", globals=globals()))
print(timeit.timeit("flat(mysequence, mymapping)", globals=globals()))
并获得:
In [683]: 0.675819274969399
0.965234256349504
“嵌套”解决方案的速度提高了 43%。 在我的项目中,我观察到速度快了好几倍的情况。
在文档中,我们可以读到:“连接字符串序列的首选快速方法是调用''.join(sequence)”。但我清楚地看到“+
”运算符在此配置中更快。
虽然我没有问题继续使用“嵌套”解决方案:
我是否缺少另一个“平面”解决方案? (没有sum()
可能带有字符串)
你对这种行为有解释吗?
谢谢。
【问题讨论】:
这在很大程度上取决于您要加入的什么。例如,仅 10 个字符的字符串就可以轻松放入各种缓存中,从而抵消大部分成本。比较例如mymapping = x: x*1024 for x in letters
.
@MisterMiyagi 我发现与您的 mymapping 以及在我的项目中字符串是复杂的正则表达式的性能观察结果相当。我认为它与每个函数在内部的工作方式更相关(参见其他答案中提出的 flat_list 和 remap 函数)。
【参考方案1】:
当你使用列表推导时,我的加入速度更快:
def flat_list(sequence, mapping):
return "".join([mapping[x] for x in sequence])
2.5292927 # nested
2.3440613999999997 # flat_list
6.530926599999999 # flat
我的猜测是它与this 有关。生成器表达式似乎有一些小的开销,并且重复了 10000 次,这种差异变得可见。
【讨论】:
非常感谢关于生成器表达式的有趣信息!【参考方案2】:我是否缺少另一个“平面”解决方案? (字符串不能使用 sum())
Josef 的回答看起来不错,所以我只是回应这部分。有一种更优雅的方式(在我看来),它似乎也比其他方法更快。
def remap(sequence, mapping):
return ''.join(map(mapping.get, sequence))
# mysequence
1.098659 # nested
1.1296278 # flat_list
1.4904282 # flat
0.9128849 # remap
# mysequence * 10
8.5377648 # nested
8.814077 # flat_list
6.1268931 # flat
5.555387 # remap
【讨论】:
有趣,看起来内置类型与map
配合得很好。
这确实是一个优雅的平面解决方案。更有趣的是速度表现!即使我对字节码没有特别的了解,我也查看了所有 4 个函数(@Josef 中的嵌套、平面、平面列表和你的重映射)的字节码(如 @Josef 提供的链接),重映射更简单,其中应该解释一下速度。谢谢!以上是关于从映射连接字符串时的性能的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Key Vault 自动映射 Azure Functions 机密
使用 Database.Create 的对象名称“dbo.__MigrationHistory”无效;传入连接字符串时的EF6.02