【问题标题】:Which programming language allows to update any class on-the-fly?哪种编程语言允许即时更新任何类?
【发布时间】:2011-07-14 03:20:39
【问题描述】:

我想知道,是否有任何语言允许您在不重新加载整个应用程序的情况下即时添加/删除/更新任何类? (前提是我可以接受一些不便,例如确保当前没有任何方法在运行 + 一些额外的努力来“迁移”类数据成员)。

您替换 1 个文件并在下一个客户端请求中使用它的 Web 应用程序不是我需要的(如 Perl、PHP)。应用程序必须持续运行,并且有一些内部状态。

其他要求是

  1. 没有阻止使用 SMP 的 GIL 或类似问题
  2. 最好 - 存在类似 JIT 的 VM(即性能接近本机代码的地方)。理想的解决方案是能够以 CLang 或任何其他基于 LLVM 的语言重新加载模块。这将是完美的。

关于已经做出的答案:

  • .NET/Java 不适合 - 它们都有过于庞大的 VM,并且应用程序的很大一部分将在 Linux 上运行。
  • Erlang - 看起来有可能,但对我的肉眼来说太可怕了,我无法平静地看着它的 if's、case's 和 strings。另外,我宁愿避免将裸源传输给客户端,编译后的字节码会好得多。

【问题讨论】:

  • 除了那些讨厌的性能问题,现代 Ruby 可能会满足您的需求。
  • 我假设您需要 JIT 编译器,而不是兼作 DVCS 的 VM?
  • JIT 很好,但不是严格要求。
  • 您对庞大虚拟机的评论似乎不合适。从 96 GB 的服务器内存中取出 100 MB 左右似乎并不过分。
  • 是的,这不是服务器上的问题,而是客户端上的问题——尤其是当他们必须下载这些 100Mb 时。

标签: programming-languages language-features


【解决方案1】:

Erlang 旨在支持热代码交换作为其高可用性功能之一。

【讨论】:

  • Erlang 确实是这个问题的一个很好的答案。它甚至与最初的询问者知识相反,编译为您可以发送的字节码,因此源不在客户端机器上。
【解决方案2】:

Objective-C 可能符合要求。您可以使用here 记录的函数在运行时添加新类和交换方法实现,如果需要额外的实现,您可以在现有类上加载带有额外类或类别的新 NSBundle。 GNUStep 虽然没有实现 Apple 最近对该语言的所有新增功能,但确实声称实现了这些功能(请参阅 [1][2])。

【讨论】:

  • 并非如此。您不能添加实例变量。 Pieter Schoenmakers 在其 1999 年的论文中对此进行了解释。见gerbil.org/tom
  • 当然可以通过创建子类来添加实例变量。对于现有课程,您可以使用objc_setAssociatedObject 轻松“伪造”它。
【解决方案3】:

以下通常被认为是动态语言:

  1. ActionScript
  2. BeanShell
  3. Common Lisp 和其他一些 Lisps
  4. Groovy
  5. JavaScript
  6. VBScript
  7. Matlab
  8. Lua
  9. Objective-C
  10. Perl
  11. PHP
  12. Python
  13. Ruby
  14. Smalltalk
  15. Tcl
  16. ...

Microsoft Dynamic Language Runtime.NET Framework 支持其中一些语言。

【讨论】:

    【解决方案4】:

    您要编写什么类型的应用程序?在什么平台上?

    GUI 与服务器的问题可能会像 linux 与 windows 一样排除一切。

    以下语言是动态的:

    • 闲聊
    • Perl
    • JavaScript
    • VBScript
    • 红宝石

    现代 JavaScript 目前正处于尽可能快的军备竞赛中,因此在任何平台上都应该很快。

    【讨论】:

    • JS 没有类,所以从字面上讲......这并不是说基于原型的 OOP 不是很整洁。
    • 动态只是问题的 10%。我不知道在这些语言中即时更新类的好方法,以便已经创建的实例可以照常工作。平台是 Win/Linux。它是分布式服务器-客户端应用程序,没有 gui。
    • 我不清楚你写的内容:你是希望类的所有实例在类更新时都发生变化,还是只希望新实例发生变化。不要说“两者”.... :-) 另外为什么客户端不能定期重启以升级?那不是解决了客户端的问题吗?
    • Both ;-) 客户端重启是一种廉价的解决方案(或类似'序列化所有内容并重启,然后反序列化'),但我确实希望即时进行透明更新。
    • 嘿,选择便宜的解决方案!为什么要付出更多?记住“可能可行的最愚蠢的事情”...
    【解决方案5】:

    Python 可以做到这一点。请注意以下几点:

    • multiprocessing 模块。
    • GIL 特定于 CPython,它不是 Python 固有的。
    • GIL 不是你think 的问题。它不会影响大量 IO 使用,以及 doesn't apply to C code 或 C 库(如果 wrapped correctly)。如果您正在做任何计算密集型的事情,那么它无论如何都应该在 C 中(无论如何都是那些部分)。

    【讨论】:

    • 我真的需要线程,我需要它们之间共享的所有数据,而进程要困难得多。此外,不能安全地启动 1000 个进程。由于 IronPyton 和 JPython 不适合我,我检查了 PyPy 并发现它也受到 GIL 的影响,以免破坏与现有 C 库的兼容性。
    • @BarsMonster:在不知道您遇到什么问题的情况下,我会补充一点,您的观点仅代表 CPU 密集型、与算法相关的数据共享,例如繁重的并行计算,或者您是在 Windows 上。如果是这种情况,您应该考虑 C,并将您的计算包装在一个模块中以供高级语言使用。所有其他情况都只是乞求基于进程的并行化:stackoverflow.com/questions/3609469/…
    • @BarsMonster:我的正确意见所说的是完全正确的。请记住,在大多数 Unix 调度程序中进程和线程是可以互换的。使用相同代码段的 1000 个进程将得到操作系统更好的处理,并且无需过多的并发原语。
    【解决方案6】:

    我最近对零停机服务迁移进行了一些研究。而且我的解决方案不是与语言相关的解决方案。思路是这样的,我们可以转储当前服务的状态,创建另一个进程,将连接状态描述传递给新进程,最后终止旧进程。如下图所示:

    通过定义良好的抽象服务描述格式和迁移协议,您可以将任何类型的服务从一个进程迁移到另一个进程,也就是说,您可以用 C++ 编写一个服务器,并将服务迁移到用 Python 编写的新进程没有任何断开。当然,您可以将您的服务从旧版本迁移到新版本。添加/删除/更新类不会有问题。更详细的可以参考我的文章

    Zero-downtime service migration

    这种技术的难点在于您必须转储正在运行的服务的所有状态并将它们加载到另一个进程上。对于您可以找到的大多数库,很难获得这些类的内部状态,这意味着您可能必须对它们进行一些修改,或者编写自己的库。为复杂的服务转移服务状态将是一场噩梦,但对于简单的服务来说,这没什么大不了的。

    【讨论】:

      【解决方案7】:

      我们通过在 Gemstone 的免费版本上运行的 Seaside smalltalk Web 应用程序来做到这一点。 Gemstone 在过去 20 年左右一直在这样做,因此他们拥有您需要的一切。一些高可用性功能不是免费的。

      开源 smalltalks 没有广泛的类版本/迁移宝石。简单的“加载新版本并迁移所有实例”适用于所有 smalltalks。

      【讨论】:

        【解决方案8】:

        看看Scheme。您可以使用非常简单的扩展在 Scheme 中进行面向对象编程,例如Berkeley extensions。只需扩展代码以允许替换方法(应该很容易),您可以随心所欲地热交换它们——语法仍然很简单,因为,嗯......它是Scheme。 :)

        现在,该类的代码如下所示:

        (define-class (person name)
          (method (greet) (print `Hello!))
          ...)
        

        person 是一个 lambda。例如,更改define-class 宏以使person 成为一个列表应该很容易,这样您就可以动态地添加或删除它。

        【讨论】:

          【解决方案9】:

          Dart VM 具有出色的热代码重载支持 大大提升了 Flutter 的开发体验。

          https://github.com/dart-lang/sdk/wiki/Hot-reload

          【讨论】:

            【解决方案10】:

            【讨论】:

            • 这看起来非常多汁,唯一的问题是个人与庞大的 JVM 不兼容:-)
            • 使用 3rd 方实用程序 zeroturnaround.com/jrebel 可以进行更多的热插拔/重新部署
            【解决方案11】:

            取决于您的项目的具体情况 - Javascript 可能是通过 Node.js (nodejs.com) 的答案,它允许您使用由 V8 引擎解释的 javascript 对基于事件的服务器进行编程。

            与传统的网络服务器相比,这种方法在一次有许多连接的情况下非常有效,尤其是在服务器有很多空闲的情况下。这是由于 Javascript 的基于事件的特性,空闲成本非常低。

            有几种使用 node.js 热交换代码的方法 - 这应该可以帮助您入门:Node.Js in Erlang style?https://github.com/kriszyp/nodules

            【讨论】:

            • SMP 可能由于 node.js 的无共享构造而成为问题。
            【解决方案12】:

            Smalltalk 可以很自然地做到这一点,Common Lisp (CLOS) 有几个技巧。

            【讨论】:

              【解决方案13】:

              您可以查看http://en.wikipedia.org/wiki/List_of_programming_languages_by_category#Reflective_languages 的列表。我还没有看到这里提到的一个是 Lua,与其他动态语言相比,它以速度快而著称。

              另一种策略可能是查看学术研究。一个可能的起点是http://scholar.google.com/scholar?q=ksplice,它是关于修补正在运行的 linux 内核。

              我不确定您正在寻找何种程度的自动化。显然,用 A' 无缝替换程序 A 的运行实例的一般情况是困难的,即使对允许在 A' 中更改的内容有一些保证。

              根据需要更新的程序片段如何分组和隔离,您可以将它们放在共享库中,并在运行时(重新)加载共享库(使用例如 dlopen 系列如果您使用的是 unix,则可以使用函数)。

              【讨论】:

                【解决方案14】:

                你应该为此使用 php,我也有一个 linux 服务器,它非常好,可以更改文件,比如我有这个 php 代码来打开一个带有可编辑站点文件的文本框,

                <?php 
                $fn = "test.txt"; //the path to any file
                
                if (isset($_POST['content'])) 
                { 
                    $content = stripslashes($_POST['content']); 
                    $fp = fopen($fn,"w") or die ("Error opening file in write mode!"); 
                    fputs($fp,$content); 
                    fclose($fp) or die ("Error closing file!"); 
                } 
                ?> 
                <h4>You are editing <?php echo $fn ?> </h4>
                <form action="<?php echo $_SERVER["PHP_SELF"] ?>" method="post"> 
                    <textarea rows="25" cols="40" name="content"><?php readfile($fn); ?></textarea>
                    <br/>
                    <input type="submit" value="Save">  
                </form>
                

                【讨论】:

                  【解决方案15】:

                  Objective-C 允许您热交换代码,并且有一个插件允许这样做。我回答了关于Objective-C的类似问题here

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-04-06
                    • 1970-01-01
                    • 2010-09-16
                    • 1970-01-01
                    • 2011-03-05
                    • 2011-03-30
                    • 2016-10-16
                    相关资源
                    最近更新 更多