浅谈注册表读取所需要付出的性能代价

系统 其他OS
如果调用 RegNotifyChangeKeyValue 函数的线程退出,则会引发通知。这意味着你不应该从线程池线程调用该函数,因为当工作列表空闲并且不再需要它们存在时,系统将销毁线程池中的线程。

Windows 系统的特色功能,注册表,是一个十分方便有用的工具。它可以用来以一种统一和多线程安全的方式来永久性的保存数据。如果你将数据保存在 HKEY_CURRENT_USER 键下,则数据可以随着用户一起漫游,并且可以保护单个键值 (即使是在使用了 FAT 文件系统的操作系统也是如此)。

但这并不意味着这是一份免费的午餐。

据我所知,从打开注册表键开始,读取键值并关闭它,整个过程将花费大约 60000 到 100000 个 CPU 周期,这还是假定要查找的键值已经缓存在内存中的情况。如果你打开注册表键并保持打开状态,那么读取值的行为大约需要 15000 到 20000 个 CPU 周期(这些测算数据是 Windows XP 下的估计值,在真实情况下数据可能会有所不同)。

因此,我们不应在一个内部循环中读取注册表项。它不仅会在查询时花费 CPU 时间,而且注册表的不断查询意味着,注册表用于查找和存储键(包括注册表缓存中的条目)的数据结构将始终保存在系统工作集中。

另外,也不要在每次鼠标移动时读取注册表项,应该仅读取该值一次并缓存结果。

如果你担心用户在程序运行时修改了键值,则可以考虑建立一个规则,供人们在想要更改设置时遵循。
例如,Windows 使用诸如 SystemParametersInfo 之类的函数,在通常情况下,会首先读写缓存中的数据,而不是每次都从注册表中读取。调用 update 函数会更新注册表和内存中缓存。

如果无法建立协调设置更改的机制,则可以通过 RegNotifyChangeKeyValue 函数设置更改通知,以便在值更改时收到通知。一般原则是,应该尽可能针对常见情况进行优化,而不是针对罕见情况进行优化。常见情况是注册表值未更改。通过使用通知机制,可以将“但是如果值更改了怎么办?”的成本从内部循环中移出,并转移到大多数时间不执行的代码中。(请记住,最快的代码是永远不会运行的代码。)

当然,你不想在一个线程上等待多个通知事件。我的方法是:使用线程池。
RegisterWaitForSingleObject 函数可以用来告诉线程池,”嘿,当这个对象发出信号时,请通知我。” 然后,线程池会将其与要求等待的所有其他句柄组合成一个巨大的 WaitForMultipleObjects 调用。这样,一个线程可以处理多个等待对象。

需要注意的一个地方是,RegNotifyChangeKeyValue 函数所发出的通知具有线程亲缘性。
如果调用 RegNotifyChangeKeyValue 函数的线程退出,则会引发通知。这意味着你不应该从线程池线程调用该函数,因为当工作列表空闲并且不再需要它们存在时,系统将销毁线程池中的线程。

如果你不小心搞砸了并从线程池线程调用它,你会发现当线程池清理代码运行时,事件不断虚假触发,这可不是一件好事。

相反,你应该从持久线程(例如,实际关心值的线程) 创建等待,并在那里注册等待。当事件在线程池上触发时,处理更改,然后要求持久线程启动 RegNotifyChangeKeyValue 的新周期。这样,事件始终与持久线程相关联,而不是与暂时性线程池线程相关联。

总结

一般我们会将应用程序的设置数据保存到注册表,这很方便,但是记得读取的时候,尽量只读一次并缓存结果,而不是每次都从注册表里读取,这对运行时性能是有伤害的。

责任编辑:武晓燕 来源: 今日头条
相关推荐

2019-04-15 13:32:53

5G机器人物联网

2013-09-29 13:52:31

2011-04-21 09:10:16

2019-04-18 10:42:21

网络安全网络安全技术周刊

2011-08-09 17:15:45

注册表注册表编辑器

2011-08-04 16:37:09

注册表编辑器注册表

2009-08-19 13:25:53

C#操作注册表

2009-08-19 13:49:14

C#操作注册表

2011-06-28 10:11:05

Qt Qt 4.1.0 注册表

2009-08-21 09:43:49

C#编辑注册表

2011-08-04 16:49:33

注册表注册表编辑器

2012-09-13 10:40:30

技术债务管理项目管理

2011-03-17 11:24:15

2009-07-07 12:09:04

注册表开发.NET Compac

2010-10-20 17:14:03

SQL Server管

2009-08-31 14:45:13

C#注册表

2009-02-18 08:42:40

手动备份注册表

2020-09-29 09:26:36

Nexus

2011-08-04 18:49:50

注册表注册表编辑器

2009-06-18 10:41:03

RuntimeVers.NET组件
点赞
收藏

51CTO技术栈公众号