MicroPython核心:字符串驻留(String interning)

MicroPython使用字符串驻留可以同时保存在RAM和ROM,这就避免了存储相同字符串的重复副本,这主要适用于代码中的标识符,因为函数或变量名很可能会在代码中的多个地方出现。在MicroPython中,内部字符串被称为QSTR(uniQue STRing唯一字符串)。

QSTR值(类型为qstr)是QSTR池链接表的索引。QSTR会存储其长度及其内容的哈希值,以便在去重过程中进行快速比较。所有处理字符串的字节码操作都使用QSTR参数。

编译时生成QSTR

在 MicroPython C 代码中,任何应在最终固件中内嵌的字符串都被写成 MP_QSTR_Foo。在编译时,这将评估指向QSTR池中"Foo"索引的qstr值。

Makefile 中的一个多步骤过程实现了这一功能。总的来说,这个过程包括三个部分:

  1. 查找代码中的所有MP_QSTR_Foo标记。
  2. 生成一个静态QSTR池,其中包含所有字符串数据(包括长度和哈希值)。
  3. 用相应的索引替换所有MP_QSTR_Foo(通过预处理器)。

MP_QSTR_Foo标记从两个来源中搜索:

  1. $(SRC_QSTR) 中引用的所有文件。这是所有的C代码(即pyextmodports/stm32)但不包括第三方代码,如 lib

  2. 附加的 $(QSTR_GLOBAL_DEPENDENCIES)(包括mpconfig*.h)。

注意:frozen_mpy.c(由mpy-tool.py生成)有自己的

### 字符串池的概念及其作用 字符串池是一种优化机制,主要用于减少内存占用并提升性能。它通过存储唯一的字符串实例来避免重复创建相同的内容。在 Java 和 C# 等编程语言中,字符串池的具体实现有所不同,但基本原理一致。 #### 1. **字符串池的作用** 字符串池的主要功能在于节省内存资源和加速字符串比较操作。具体来说: - 当多个变量指向同一个字符串内容时,如果这些字符串来自常量池,则它们会共享同一份内存地址[^1]。 - 这种设计减少了不必要的对象创建,从而降低了垃圾回收的压力[^2]。 例如,在 Java 中,直接使用双引号定义的字符串会被自动加入字符串常量池[^3]。这意味着即使多次声明相同的字符串字面量,实际上也只会存在一个对应的 `String` 对象。 ```java String s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2); // 输出 true,因为两者引用的是同一个对象 ``` 而在 C# 中也有类似的机制,称为“字符串驻留”(string interning),它可以显式地将字符串添加到全局字符串表中[^5]。 --- #### 2. **字符串池的实现** ##### (a) **Java 的字符串常量池** 在 Java 中,字符串常量池由 JVM 维护,默认位于堆内存的一个特殊区域(如 Metaspace 或 PermGen 区域)。以下是其实现的关键点: - 所有通过字面量形式创建的字符串都会被存放到字符串常量池中[^4]。 - 如果需要手动将某个字符串放入池中,可以调用 `intern()` 方法[^2]: ```java String str1 = new String("world"); String str2 = str1.intern(); // 将 str1 放入字符串常量池 String str3 = "world"; System.out.println(str1 == str3); // false,str1 是新创建的对象 System.out.println(str2 == str3); // true,str2 来自字符串常量池 ``` ##### (b) **C# 的字符串驻留** C# 提供了内置支持以管理字符串驻留。开发者可以通过 `String.Intern` 方法查询某字符串是否已经存在于运行时维护的字符串池中;或者利用 `String.IsInterned` 判断特定字符串是否已被驻留[^5]。 示例代码如下所示: ```csharp string str1 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); string str2 = "hello"; // 显示未驻留前的状态 Console.WriteLine(Object.ReferenceEquals(str1, str2)); // False // 驻留 str1 并重新获取引用 string internedStr1 = String.Intern(str1); Console.WriteLine(Object.ReferenceEquals(internedStr1, str2)); // True ``` --- ### 总结 无论是 Java 还是 C#,字符串池都旨在优化程序运行效率的同时降低系统开销。合理运用这一特性能够显著改善应用程序的表现,尤其是在频繁涉及大量字符串操作的情况下。 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

原子星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值