如何在Elixir中获取变量的内存位置?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Elixir中获取变量的内存位置?相关的知识,希望对你有一定的参考价值。

我们了解Elixir的事实是data structures that lives in memory are immutable, and variables are just pointers to those data structures

有没有办法让我们得到变量的内存地址指向,而不是该内存位置的内容(即变量的解引用值)?


对我来说,这样做的目的是我们可以了解Elixir / Erlang在处理重复值时如何管理内存,例如两个相同的字符列表,或者特别是在某些情况下tuples and lists may share their contents,并编写更有效的代码。

例如,当您更新元组时,除了已替换的条目之外,所有条目都在旧元组和新元组之间共享。换句话说,Elixir中的元组和列表能够共享其内容。

答案

TL;DR:

不,你无法获得变量的内存位置。

Discussion

原则上一切都是复制的。每个进程都有自己的堆。这就是事情的方式。

实际上有一些潜在的速度黑客。最值得注意的是

  • 编译时已知的文字从全局堆中引用(在某些情况下,这是一个巨大的性能增益)。
  • 从全局堆引用大于64字节的二进制文件(这也会导致二进制文件成为漏洞抽象,因此binary:copy/1,2)。
  • 对大多数结构的更新实际上并不需要复制整个结构(特别感兴趣的是what goes on inside maps) - 但是随着更多的效率工作进入运行时,需要多少以及何时需要复制。
  • 每个进程都会发生垃圾收集,这就是为什么Erlang似乎有一个神奇的高级增量GC方案,但实际上下面有相当无聊的世代堆集合(在一般情况下,这就是;方法是actually somewhat of a hybrid - 永远的一个部分 - 不断发展的EVM性能增强景观......)。

如果您要为EVM编写代码,无论使用何种语言,您都应该放弃这样的想法,即您将超越运行时。这与完全相同的原因是,试图超越大多数C(尤其是C ++)编译器优化几乎无处不在是一种禁止的做法。

每个主要版本都包含一些新实现的性能增强,不会破坏语言的假设。如果您开始编写对R20上某些特定底层内存方案“更有效”的代码,那么今天在这里或那里可能会获得一些微小的性能提升,但是当R21出现时,很可能会破坏所有代码并且你永远只会被R20困住。

试试the R20.0 release announcement。跟上这种变化会消耗大部分的开发时间。

有些项目试图以完整的目的回溯运行时。以Twisted为例。这些项目具体存在,以便所有(大的和非平凡的)努力不必在其下游的每个项目中重复。考虑到这一点,Erlang运行时,核心编译器,LFE项目,Elixir项目等本身就是这种速度攻击的地方,绝对不是下游客户端代码。这里要注意的是快乐的事情(是的!我的严肃故事有一个美好的结局!)就是这正是我们所看到的。

关于“效率”的说明

你追求什么样的效率?循环?巴士交通?缓存未命中?财务费用? I / O-ops消除/绕过/写入?更一般的选择性缓冲处理?等等

除非你在今年需要高效的已知硬件上编写超紧密游戏引擎的前端(因为明年硬件将使大多数速度硬件相形见绌),支付更多的CPU时间远远低于开发人员需要花时间来确定大规模并发运行时内发生的事情,数千个进程发送数百万条短暂的消息,所有进程都在不同时间进行自己的垃圾收集。

有人可能想要“知道发生了什么”的情况,我最常见的情况是人们试图将Elixir用作“更快的Ruby”而且编写的不是大规模并发系统,而是一个大规模的单线程在EVM之上的程序。在Erlang运行时编写“快速”程序的方法完全忽略了这一点。

如果您有一个非常特定的CPU密集型任务,绝对需要超快的速度调用其中一个

  • 用Rust或C编写的端口
  • 用Rust或C编写的NIF
  • 一个高性能计算节点,可以通过网络与主节点通信,以某种语言编写,完全适合您的计算任务(BERT在那里非常有帮助)
  • 等待一两年的时间让运行时采用更多的性能增强和硬件来加快速度 - 这种速度提升的速度对于并发系统来说是完全疯狂的,特别是如果你在自己的硬件上运行(如果你当然,这些改进正在“云”中运行,但这些改进对提供商有利,但不是你,即使这样,让自己为更多实例而不是试图欺骗运行时更便宜)

编写单独的程序(或NIF)允许处理特定问题的任何开发人员或团队在单个统一的统一问题空间中工作,只关心履行主项目所交付的任何协议合同。这比使Erlang或LFE或Elixir开发/团队在编写一些Erlang,然后是一些LangX,然后再一些Erlang,上下文切换作为理所当然(或者更糟糕的是,在他们之间的一种语言之间的上下文切换)之间的转换效率要高得多是专家,是一个缺乏经验和天真的人。

(请记住,NIF应该被视为最后的手段,只有在您了解实际情况时才会考虑。具体来说,您的处理工作很少,每次通话,可预测且有限,并且频繁的呼叫开销是您的NIF超过了NIF中的处理速度.NIF破坏了运行时的每一个安全保障。崩溃的NIF是一个崩溃的运行时 - 正是Erlang设计要避免的那种问题。任何在C语言中感到舒服的人都会轻率推荐C语言各地的NIF显然缺乏足够的C经验来编写那些NIF。)

在项目层面,效率问题主要是业务决策,而不是技术决策。这是一个糟糕的业务(或社区管理,在社区FOSS的情况下)决定尝试超越运行时。

以上是关于如何在Elixir中获取变量的内存位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

如何在不在 android 的 Activity 上添加地图片段的情况下获取我的位置?

如何使用 TabLayout 在 ViewPager 中的 Google 地图片段中获取当前位置

如何在 Elixir 中不按 Enter 键获取单个字符?

在选项卡式应用程序中的何处放置位置代码?

E1.获取Elixir/Erlang版本信息