如何用Nim在栈上开发?

How to develop on the stack with Nim?

我想在软实时上下文中使用 Nim,其中内存分配和垃圾收集都表现出过多的延迟。因此,手动内存管理是可取的——或者更好的是,专门从堆栈内存中工作。

我可以使用 Nim 的哪个子集来实​​现仅堆栈内存分配?我猜我可以通过缓存的 C 代码中缺少 memset 或 memcpy 来判断它是否有效。

如果您真的不想进行垃圾回收,您需要使用 --gcnone 参数,如 Nim Compiler User Guide 中所述。 none 参数禁用垃圾收集器,让您自行处理。这通常意味着任何字符串操作都会产生警告,因为尽管分配了内存,但以后没有人释放它:

proc main() =
  let x = 5
  echo "Hello " & $x & " there"

main()

如果您使用 nim c --gc:none -r test.nim 编译这个小测试,您将收到 gc 警告:

test.nim(3, 19) Warning: '$ x' uses GC'ed memory [GcMem]
test.nim(3, 22) Warning: '&("Hello ", $ x, " there")' uses GC'ed memory [GcMem]

这可以帮助您了解 Nim 的哪些部分 安全 可以直接或间接地在 GC-less 环境中使用。但是请注意,某些操作可以移动到编译阶段。因此,以下生成相同输出的示例在没有 GC 的情况下可以安全使用,因为所有 const 表达式都是由生成的 C 代码静态分配的:

proc main() =
  const x = 5
  echo "Hello " & $x & " there"

main()

nimcache 目录中查看,您会发现源代码包含类似于以下的行:

  STRING_LITERAL(TM_ipcYmBC9bj9a1BW35ABoB1Kw_2, "Hello 5 there", 13);

仍然请注意,在上述文档中有一个 link 到 Nim's Garbage Collector 文档,其中包含一个非常具体的 Realtime support 部分,可能如果它提供的妥协满足您的要求,可能会有所帮助,并可能避免您手动处理内存的痛苦。

目前,字符串和 seq 类型都需要 GC 才能正常工作,即使它们具有值类型语义。然而,这计划要改变。我只是不能告诉你这是什么时候。如果没有这两种类型,Nim 就不是您真正想要使用的语言。除此之外,类型与 C++ 非常相似。因此,如果您不使用 ref 类型,则不会为 GC 进一步分配。

不是 Nim 的细节,也不是 GC 的细节,我也不会在这里提供合理的答案,而是提供与语言无关的编程建议。

Android 上的堆栈限制为 MiB 或 24KiB。您可以通过左右调整清单使其达到 8MiB。

如果您没有 OS,在实模式和非虚拟化内存中 space,也许您将拥有无限堆栈。

但是大多数现实世界的应用程序都必须使用分配器。在堆上保留一块内存,并保留一个您可以手动 increment/decrement 的自定义 "stack pointer",相比之下通常让编译器执行它。

这带来了 2 个优势:与调用堆栈和块作用域分离。和无限内存。

限制:linux 您的页面将按需填零。内核懒惰地提供页面,所以你会在关键时候遇到卡顿。为避免这种情况,请准备一次扫描,在整个 space 上写入 0xff。 这将具有与其他进程非常不合作的缺点,并可能破坏文件系统缓存。但对于通常被用户接受的实时应用程序。