我目前正在开发一种动态类型的语言。
我在开发过程中遇到的主要问题之一是如何进行快速运行时符号查找。
对于一般的,自由的全局和局部符号,我只是将它们编入索引,并让每个范围(全局或局部)保留符号数组,并使用索引快速查找它们。我很满意这种方法。
但是,对于对象中的属性,问题要困难得多。我不能对它们使用相同的索引方案,因为我不知道我正在访问哪个对象,因此我不知道要使用哪个索引!
这是python中的一个例子,反映了我想用我的语言工作的内容:
class A:
def __init__(self):
self.a = 10
self.c = 30
class B:
def __init__(self):
self.c = 20
def test():
if random():
foo = A()
else:
foo = B()
# There could even be an eval here that sets foo
# to something different or removes attribute c from foo.
print foo.c
有没有人知道快速查找的任何聪明技巧?我知道哈希映射和splay树,所以我很有意思,如果有任何方法可以像我的其他查找一样高效。
答案 0 :(得分:3)
一旦你到达哈希表中查找属性的速度不够快,标准的下一步就是inline caching。你可以用JIT语言,甚至是字节码编译器或解释器来做到这一点,虽然它似乎不常见。
如果对象的形状随着时间的推移而改变(即你可以在运行时添加新的属性),你可能最终会做类似于V8 hidden classes的事情。
答案 1 :(得分:1)
称为maps的技术可以将每个属性的值存储在紧凑数组中。属性名称对应于哪个索引的知识在辅助数据结构(同名映射)中维护,因此您不会立即获得性能优势(尽管如果许多对象共享一组属性,它确实会更有效地使用内存)。使用JIT编译器,您可以使映射持久和常量折叠查找,因此最终的机器代码可以使用常量偏移到属性数组中(对于常量属性名称)。
在解释器中(我假设字节代码),事情要困难得多,因为你没有太多机会专门为特定对象编写代码。但是,我自己有一个想法,将属性名称转换为整数键。维护全局映射,为属性名称分配完整ID。向VM添加新字节代码(从磁盘加载或在内存中编译)时,扫描用作属性的字符串,并将其替换为关联的ID,如果之前未看到该字符串,则创建新ID。您可以使用稀疏数组,而不是在每个对象上或在地图中存储哈希表或类似映射,这些数组希望更紧凑,操作更快。
我没有改变实现和测试它,你仍然需要一个稀疏数组。除非您想使所有对象(或映射)占用尽可能多的内存字,因为整个程序中有不同的属性名称,即。至少你可以用整数哈希表替换字符串哈希表。 只需将ID的哈希表调整为键,就可以进行多项优化:不要调用哈希函数(使用ID作为哈希),删除一些间接,从而缓存未命中,节省处理病态错误哈希的复杂性功能等