基于哈希表的dict / map结构提供O(1)
查找时间。然而,我一直看到Elixir中的含义,找到匹配的函数头比在地图中查找某些内容要快。
例如,Elixir的String.Unicode
compiles a list of unicode characters into many function heads因此,通过找到期望“é”的upcase
的函数头来回答“é的最佳版本是什么”。
我不知道为什么这比在地图中查找“é”的单个upcase
函数头更快或内存效率更高。
同样,在展示如何在“Metaprogramming Elixir”中构建I18n库时,Chris McCord为每个翻译键提供了自己的功能头,并说:
“通过为每个转换映射生成函数头,我们再次让虚拟机接管以进行快速查找。”
Elixir中的地图不提供O(1)查找吗?找到匹配的函数头O(1)?为什么选择将静态列表编译为多个函数头而不是仅将其存储在映射中?
答案 0 :(得分:16)
Elixir地图不是 flat 基于哈希表的数据结构。小地图是有序列表,其中地图具有< = 31个条目。当地图获得32个条目时,它将更改为查找O(log n)
的哈希trie。毕竟,不可变的基于哈希表的数据结构的更新成本非常高,这是构建"的主要方法。其中一个数据结构。更改一个值将要求您仅使用一个项目更新新地图。它们基于Rich Hickey的持久性哈希映射,这是一种散列的哈希数组映射。
函数头匹配复杂度为O(n)
最坏情况,但可以由编译器以我不完全理解的方式进行优化。在某些情况下,它可以将一些功能头模式转换为树。但是因为函数头匹配没有总订单,并且必须按照它们的定义顺序匹配,所以优化量非常有限。您可能只是幸运地使用功能头部匹配的非常低的部分以及功能头匹配顺序的树。
头部匹配的每个步骤都非常轻量级且高度优化,其中地图仍然很新,并且有一些性能优化。例如,如果密钥是复杂/嵌套的(例如,简单整数具有非常快的散列函数),则散列函数的复杂性并不简单。但是在你的unicode示例中,我打赌unicode标准,就其命令id的方式而言,将尽可能多的常用字符放在前面。这可能使VM非常容易优化,并且您可以获得非常良好的查找时间。我敢肯定,如果你查找一个不起眼的字母表,你的复杂性就会发生变化。
但是,人们不能动态生成具有函数匹配的模块作为查找数据的方式的原因是你会破坏全局状态,特别是code_server模块。一些查找可能会更快,但随着数据结构变大,加速可能会减慢。