轻量级 C++ 脚本库
Posted
技术标签:
【中文标题】轻量级 C++ 脚本库【英文标题】:lightweight C++ scripting library 【发布时间】:2009-05-27 13:41:51 【问题描述】:我目前在我的 C++ 应用程序中使用 QtScript 来编写脚本功能,但它在 cpu 上相当“重”。当一个线程在一个循环中评估所有脚本时,cpu 使用率增加到 90%-100%。即使我每 5 个脚本让它休眠 1 毫秒,它的 CPU 使用率也保持在 75% 以上。
还有其他比 QScript 更轻量的易于实现的脚本框架吗?
编辑:
我现在意识到这是正常行为,而不是 QtScript 中的一些严重错误。听听有哪些类型的(轻量级)脚本库可用仍然很有趣。
【问题讨论】:
你确定你没有做傻事吗?您是否尝试过一个简单的脚本作为测试。 @mgb:阿门——还要记得查看你的中间表示(字节码、反汇编、解析树等)——即使你不明白到底发生了什么,也有一些问题可以非常明显! Alloc/dealloc 列表或其他内存使用统计信息也可以提供帮助。 (任何有 QScript 经验的人愿意提供更多信息吗?) 【参考方案1】:看看Lua,在游戏中经常使用,所以性能肯定不错。
【讨论】:
啊,是的,我以前听说过 Lua。明天我会进行一些测试。 不会执行不会阻塞使用 100% CPU 的 Lua 脚本?我希望如此,否则我会认为它坏了。 我猜会的,但他问了一个快速的脚本库,所以我提出了建议。【参考方案2】:嗯,你期待什么?除非脚本必须等待磁盘或用户 I/O,否则 CPU应该以 100% 运行。
您的问题是运行时间过长吗?
或者您的应用程序没有响应?
在这种情况下,问题在于您的脚本阻塞了运行所有 UI 交互的线程。一般的解决方案是阻止所有 UI 输入(“取消脚本”按钮 :) 除外),并将实际处理移至单独的线程。
[编辑] 稍微不同的问题:没有脚本可处理时,CPU 是否处于 100%?
100% CPU 良好且健康,如果您正在处理某事。
CPU 总是很忙,当前线程总是消耗 100% 的内核。 “0% CPU 活动”实际上意味着所有周期都花在系统空闲线程中(属于您在任务管理器中看到的“系统空闲进程”)。
举个简单的例子:如果您有一个应用程序线程处于活动状态,并且 CPU 使用率为 40%,并且您的任务管理器更新间隔为 1 秒,那么在应用程序上花费了 400 毫秒的 CPU 时间,在空闲线程上花费了 600 毫秒。
【讨论】:
不,它没有阻塞任何东西或运行缓慢。我有很多线程,其中 1 个处理 qscripts。大多数线程使用大约 1-2% 的 cpu,但 qscript 线程使用大约 90%。当然,脚本应该运行得很快,但它不应该对 CPU 造成很大的负载。也许我对此错了,但大多数应用程序不使用 100% cpu,即使他们很忙。这应该与脚本不同吧? 根据操作系统的处理方式,很可能会看到线程长时间运行 90%-100% CPU 利用率,尤其是在没有其他进程需要 CPU 时间的情况下。如果您真的想限制这一点,请尝试使用运行脚本的线程的优先级。 我想你是对的,我意识到我应该更多地了解线程。但是因为这不是我问题的真正答案,所以我会支持你:) 没关系,我会克服的 ;) 很高兴您也更新了您的问题,以免对 QScript 造成不良影响。【参考方案3】:Lua 很好,因为它使用堆栈在解释器和 C++ 之间进行通信。这很好,因为它不涉及任何对您可见的引用计数,从而简化了事情。
这里有一个有趣的比较,作为某些 iolanguage 的背景:iolanguage。
【讨论】:
【参考方案4】:我听说过关于TinyScheme 的好消息。话虽如此,我们在这里使用 Lua(在游戏开发工作室,针对嵌入式和手持系统)。
需要注意的是——特别是 Lua,但我认为这些适用于其中许多语言:
自定义的轻量级小对象分配器可以获得很多性能;许多这些语言都是重分配的。使用池化或基于帧的分配器可能值得您花点时间,这取决于您可以摆脱什么。 根据所使用的 GC 策略(因为这些语言中的大多数都是垃圾回收的),您需要保持 GC 扫描区域较小——例如总体上较小的 lua 堆大小。花一些时间重新组织数据以使其脱离 GC 的域(例如,将其保留在 C++ 端,以某种方式对其进行标记以便 GC 知道要避免它等)会有所帮助。 类似地,增量垃圾收集也可以是一个巨大的胜利。我建议尝试一下——在某些情况下(小堆),我发现完全 GC 比增量 GC 更快。【讨论】:
【参考方案5】:我个人会推荐 Lua 在我们的嵌入式平台中广泛使用它。如果你在 Windows 上运行,你也许可以使用 LuaJIT 之类的东西来让你的 Lua 更快
但是,由于没有人提到它,您可能还想看看 Squirrel (http://squirrel-lang.org/)。我没有任何经验,但我认为它看起来很有希望。
至于您当前的问题,如果没有任何会阻塞它的代码,任何代码都将占用 100% 的 CPU。
类似(伪代码):
对于(i=1,10000000000000) n=n+i 结束
将占用 100% 的 CPU,直到它以(几乎)任何语言完成,因为没有什么可以阻止它执行。
【讨论】:
【参考方案6】:Lua 是您的language of choice。还有一些bindings for Qt。
【讨论】:
【参考方案7】:这实际上取决于几个因素:
脚本会在您的应用程序中大量使用吗? 脚本会很复杂吗? 您是否向脚本引擎公开了很多功能? 您是否关心与 Qt 的良好集成?我也推荐 Lua,但是,你应该记住以下几点:Lua 是用纯 ANSI C 实现的。这使得它具有超级便携性,但是如果你在 C++ 环境中开发,它会导致很多“包装”类。尤其是当您想公开 Qt 功能时(全部是 SIGNAL
s、SLOT
s 和 PROPERTY
s),会导致大量重复代码。
【讨论】:
不需要包装任何东西,尽管您可以选择。标准 Lua 发行版可以像 C++ 一样编译。我在混合 C/C++ 环境中使用 Lua,所以我们在没有包装器的情况下使用它。必须将 lua_State* 传递给 C 世界中的每个函数,这有点烦人(对于 C++ 程序员),但这是完全可行的,而且没什么大不了的。 是的,这是可行的。但我的观点是,C++ 的所有优秀特性——尤其是与 Qt 结合使用——可能会导致大量的包装。在脚本中,您想调用宿主应用程序的方法,因此需要公开它们。因为 Lua 不支持 C++ 仿函数,所以实现它可能很乏味。【参考方案8】:您还可以使用spidermonkey 嵌入javascript 我认为 javascript 比 lua 更普遍。
【讨论】:
【参考方案9】:到目前为止,我所知道的 QtScript 没有任何问题(仅从 4.6 开始使用它,所以对它来说还是新的,但到目前为止很喜欢它)。取决于你如何使用它,就像lua或python一样。如果您尽可能多地保留应用程序的核心功能(从 c/c++ 编译)并且只向脚本引擎公开最小的 API,那么一般来说,您可以保持快速。
使用 QtScript,以合理的线程安全方式(QT 的槽和信号对象模型)公开对象及其方法相对容易,并且可以轻松地将脚本创建的对象传递给本机函数......但您最终可以紧密集成使用 QT 环境(有时这可能正是您想要的)。
如果您想任意将本机 c++ 对象公开给其他嵌入式脚本环境,请查看 SWIG。 SWIG 类似于 toLua 工具,但适用于许多可嵌入语言,例如 lua、c#、tcl、java 和 python 等等。根据经验,toLua 使绑定对象和方法到脚本的过程变得不那么痛苦,而且我也没有听说过很多关于 SWIG 的坏事。
【讨论】:
以上是关于轻量级 C++ 脚本库的主要内容,如果未能解决你的问题,请参考以下文章
轻量级 Delaunay 三角函数库(用于 C++)[关闭]