原文链接:A Simple Object Model 作者信息:Carl Friedrich Bolz


上一篇:《【500 Lines or Less】-【翻译练习】-【chapter 14】-【简单对象模型】-【第二部分】》 译者注:休息结束,我们继续

实例优化

虽然对象模型的在之前的几节中发生了很多行为变化,但在最后一节中,我们将在没有影响任何行为的情况下进行优化。这种优化被称为 maps,并在自编程语言的虚拟机中率先被使用。如今,它仍然是最重要的对象模型优化之一:它被用于 PyPy 和所有现代 JavaScript 虚拟机,如V8(其中优化被称为 hidden classes)。

目前的观察:在到目前为止实现的对象模型中,所有实例都使用完整的字典来存储它们的属性。字典是使用哈希映射来实现的,这消耗大量的内存。此外,同一个类的实例将会拥有同样的属性,比如,有一个类 Point,它所有的实例都包含同样的属性 xy

maps 优化利用了这一点。它有效地将每个实例的字典分成两部分。一部分存放所有实例共享的 keys。而实例只存储对共享映射的引用和列表中的属性值(比字典更消耗了更少的内存)。

做简单测试用例如下所示:

def test_maps():# white box test inspecting the implementationPoint = Class(name="Point", base_class=OBJECT, fields={}, metaclass=TYPE)p1 = Instance(Point)p1.write_attr("x", 1)p1.write_attr("y", 2)assert p1.storage == [1, 2]assert p1.map.attrs == {"x": 0, "y": 1}p2 = Instance(Point)p2.write_attr("x", 5)p2.write_attr("y", 6)assert p1.map is p2.mapassert p2.storage == [5, 6]p1.write_attr("x", -1)p1.write_attr("y", -2)assert p1.map is p2.mapassert p1.storage == [-1, -2]p3 = Instance(Point)p3.write_attr("x", 100)p3.write_attr("z", -343)assert p3.map is not p1.mapassert p3.map.attrs == {"x": 0, "z": 1}
复制代码

请注意,这个测试用例不同于我们之前写的测试用例。以前的所有测试都是通过已知的接口来测试类的功能。而此测试用例通过读取内部属性并将其与预定义值进行比较来检查 Instance 类的实现细节。

p1 包含 attrsmap 存放了 xy 两个属性,具体在 p1 中存放的值分别为 0 和 1。后创建的第二个实例 p2,同样在 map 中添加同样的属性。 换句话说,如果添加了不同的属性,其 map 是不通用的。

Map 类类似于下:

class Map(object):def __init__(self, attrs):self.attrs = attrsself.next_maps = {}def get_index(self, fieldname):return self.attrs.get(fieldname, -1)def next_map(self, fieldname):assert fieldname not in self.attrsif fieldname in self.next_maps:return self.next_maps[fieldname]attrs = self.attrs.copy()attrs[fieldname] = len(attrs)result = self.next_maps[fieldname] = Map(attrs)return resultEMPTY_MAP = Map({})
复制代码

Maps 类拥有两个方法,get_indexnext_map。前者用于查找对象存储中属性名称的索引。当一个新的属性被添加到一个对象时,后者被使用。 在这种情况下,对象需要使用 next_map 计算不同的 map。该方法使用 next_maps 字典来缓存已经创建的 map。这样,具有相同布局的对象也最终使用相同的 Map 对象。

使用 maps 的 Instance 实现如下所示:

class Instance(Base):"""Instance of a user-defined class. """def __init__(self, cls):assert isinstance(cls, Class)Base.__init__(self, cls, None)self.map = EMPTY_MAPself.storage = []def _read_dict(self, fieldname):index = self.map.get_index(fieldname)if index == -1:return MISSINGreturn self.storage[index]def _write_dict(self, fieldname, value):index = self.map.get_index(fieldname)if index != -1:self.storage[index] = valueelse:new_map = self.map.next_map(fieldname)self.storage.append(value)self.map = new_map
复制代码

目前 Instance 类将给 Base 类传递 None 作为字段字典,因为 Instance 将会以另一种方式构建存储字典。因此它需要重载 _read_dict_write_dict 。在实际操作中,我们将重构 Base类,使其不再负责存放属性字典。但目前,我们可以仅仅传递一个 None 作为参数。

在一个新的实例创建使用 EMPTY_MAP,其中没有存放任何对象。为了_read_dictInstance 的 map 要提供属性名称的索引,然后返回相应的条目。

写入属性字典有两种情况。第一种是现有属性值的修改,那么就简单的在 map 的列表中修改对应的值就好。而如果对应属性不存在,那么需要进行 map 变换(如上面的图所示一样),将会调用 next_map 方法,然后将新的值存放入储存列表中。

这个优化到底实现了什么?一般而言,在具有很多相似结构实例的情况下优化了内存的使用。但这不是一个通用的优化手段:有些时候代码中充斥着结构不同的实例之时,这样优化可能会耗费更大的空间。

在优化动态语言时,这是一个常见问题。一般而言,不太可能找到一种十分通用的方法去优化代码,既其更快,又节省空间。在实践中,所选择的优化适用于通常使用的语言,而对于使用极其动态的功能的程序而言,可能会有相反的作用。

maps 优化另一个有意思的点是,虽然这里只优化内存使用,但是在使用 JIT 技术 的 VM 中,也能提高程序的性能。为了实现这一点,JIT 技术使用 maps 来查找属性在存储空间中的偏移量。然后完全拜托字典查找的方式。

潜在扩展

扩展我们的对象模型和使用不同语言的设计选择是很容易的。这里给出一些可能的方向:

  • 最简单的是添加更多的特殊方法方法,比如一些 __init__, __getattribute__, __set__ 这样容易实现又有趣的方法。

  • 扩展模型支持多重继承。为了实现这一点,每一个类都需要一个父类列表。然后 Class.method_resolution_order 需要进行修改,以便支持方法查找。可以使用深度优先搜索和删除重复项来计算简单的方法解析顺序。更为复杂的可以采用 C3 算法, 这种算法拥有更好的处理菱形继承结构的能力,并且避免了不可感知的继承模式。

  • 一个更为疯狂的想法是切换到原型模式,这需要消除类和实例之间的差别。

总结

面向对象编程语言设计的核心是其对象模型的细节。编写一些简单的对象模型原型可以更好地理解现有语言的内部工作原理以及深入了解面向对象语言的设计理念。编写不同的对象模型验证不同对象的设计思路是一个很好的方式,你也必语言实现的更枯燥的部分,比如解析和执行代码。

编写对象模型在实践中也是非常有用的而不仅仅是用作实验。除了作为实验品以外,它们还可以在编写其他语言中所使用。例子有很多:用 C 语言编写的 GObject 模型,用于 GLib 和 其余 Gnome 库中,或者 JavaScript 各种类系统的实现。


有什么问题都可以在博文后面留言,或者微博上私信我,或者邮件我 coderfish@163.com。

博主是 iOS 妹子一枚。

希望大家一起进步。

我的微博:小鱼周凌宇

【500-Lines-or-Less】-【翻译练习】-【chapter-14】-【简单对象模型】-【第三部分】...相关推荐

  1. halcon算子盘点:Chapter 13:对象、Chapter 14 区域

    Chapter 13:Object 13.1 Information 1. count_obj  功能:统计一个元组中的对象. 2. get_channel_info  功能:一幅目标图像组成部分的信 ...

  2. 500 lines web craw 读书笔记

    500 lines web craw 读书笔记 网络io的几个阶段 本文三部分 1. 阻塞socket 2. 非阻塞socket /Async 3. selec.epoll.kqueue 轮询 4 回 ...

  3. Chapter 14 Greenplum PL/R Language Extension

    Chapter 14 Greenplum PL/RLanguage Extension This chaptercontains the following information: •    Abo ...

  4. 14版计算机专业英语,Chapter 14 Virtual Reality 《计算机专业英语》电子教案.ppt

    Chapter 14 Virtual Reality <计算机专业英语>电子教案 Computer English Chapter 14 Virtual Reality *计算机专业英语 ...

  5. 你知道同声翻译手机软件哪个好吗?三招教你实现同声翻译

    语言是连接人们的重要工具.当我们遇到语言障碍时,同声翻译软件成为了解决问题的有效方式.这种智能工具可以实时识别和翻译不同语言之间的交流,为人们提供无缝沟通的体验. 那你知道同声翻译手机软件哪个好吗?这 ...

  6. python对象模型映射_【500 Lines or Less】-【翻译练习】-【chapter 14】-【简单对象模型】-【第一部分】...

    date: 2017-10-08 15:31:46 Carl Friedrich Bolz是伦敦国王大学的研究员,对动态语言的实现及优化兴趣浓厚.他是 PyPy/RPython 的核心贡献者之一,并为 ...

  7. WRF用户手册翻译:Chapter 5: WRF Model

    目录 Chapter 5: WRF Model Physics and Dynamics Options Physics Options 1. Microphysics (mp_physics)微物理 ...

  8. ios android的中文翻译,苹果 iOS 14 Beta反向翻译,拒不承认iOS不如安卓

    原标题:苹果 iOS 14 Beta"反向翻译",拒不承认iOS不如安卓 在前不久,苹果就召开了一年一度的WWDC 2020,也就是苹果2020年的开发者大会,会上就对于苹果旗下的 ...

  9. 《Programming Windows Phone 7》翻译【Chapter 1 Hello, Windows Phone 7】

    所有翻译,一方面是自己初学,可以督促自己:另一方面,也希望能帮到和我一样的初学者(不想看英文的) 翻译说明: 1.每段英文后面的中文,是直接根据英文翻译的 2.根据原文翻译,难免拗口,所以[]里面为自 ...

最新文章

  1. 使用深度学习和树搜索进行从零开始的既快又慢的学习
  2. 1.4 以查询取代临时变量
  3. python入门基础代码图-Python Matplotlib绘图基础知识代码解析
  4. PHP中单引号和双引号的区别
  5. JavaScript从内容中筛选出手机号码集合
  6. [云炬商业计划书阅读分享] 体育器材
  7. Xcode error: conflicting types for 'XXXX'
  8. Mybatis传入多参问题
  9. 补习系列(16)-springboot mongodb 数据库应用技巧
  10. 常看网页表单数据_数据收集、整理低效繁琐?WPS表单帮你轻松解决
  11. 学以致用 知行合一 ——《产品管理与研发项目管理》课程有感
  12. 闲聊Framebuffer
  13. Protobuf 判断某个值是否在一个枚举值中
  14. android 画圆环进度条,Android自定义圆形进度条学习
  15. 暑假教师计算机培训总结,关于暑期教师信息技术培训总结范文
  16. 透过历史迷雾进行深入探究特斯拉线圈是如何工作的?
  17. 交叉熵损失函数以及softmax损失函数
  18. access自动自动累计余额_在Access2007数据库中如何使用查询来计算累计余额
  19. 路由器如何恢复出厂设置
  20. 阿里云 IaaS 基础设施能力拿下全球第一

热门文章

  1. canvas图形处理和进阶用法
  2. [转] Bound Service的三种方式(Binder、 Messenger、 AIDL)
  3. 【Uly】关于团队工作流程的反思
  4. AR+教育意义巨大,将对行业未来产生深远影响
  5. linux基础--awk文本分析工具详解
  6. Salesforce即将推出Einstein人工智能CRM平台
  7. 给力的网络 有道的性能——802.11n与WLAN
  8. Android各版本最新份额:果冻豆达62% 仍居首位
  9. Oracle中是用case...when语句进行判断
  10. 通过命令行创建MAVEN多模块项目