VM/解释器的性能改进策略?

2024-04-03

我用 C 语言编写了一个简单的 VM,使用简单的指令切换,没有任何指令解码,但性能很糟糕。

对于简单的算术运算,对于相同的运算,VM 比本机 C 代码慢大约 4000 倍。我测试了一组长度为1000万的数组,第一个数组由程序指令、随机+ - * /操作组成,2个数组保存随机整数,第三个数组作为操作目标存储。

我原本预计算术性能会下降 3-4 倍,所以“4000x”确实让我大吃一惊。即使是最慢的解释语言似乎也能提供更高的性能。那么我的方法哪里出了问题?如何在不诉诸机器代码的 JIT 编译的情况下提高性能?

实现是......基本上是我能想到的最简单的:

begin:
    {
        switch (*(op+(c++)))
        {
        case 0:
            add(in1+c, in2+c, out+c); goto begin;

        case 1:
            sub(in1+c, in2+c, out+c); goto begin;

        case 2:
            mul(in1+c, in2+c, out+c); goto begin;

        case 3:
            div(in1+c, in2+c, out+c); goto begin;

        case 4:
            cout << "end of program" << endl;
            goto end;

        default:
            cout << "ERROR!!!" << endl;

        }
    }

end:

更新: 当我注意到我用来分析的 QElapsedTimer 实际上已经损坏时,我正在摆弄程序的长度。现在我正在使用来自的 Clock() 函数,根据它,计算出的 goto 实际上与本机代码运行相同,可能稍微低一些。这个结果合法吗???这是完整的源代码(我知道它很难看,毕竟它只是用于测试):

#include <QtGlobal>
#include <iostream>
#include <stdio.h>
#include <ctime>

using namespace std;

#define LENGTH 70000000

void add(int & a, int & b, int & r) {r = a * b;}
void sub(int & a, int & b, int & r) {r = a - b;}
void mul(int & a, int & b, int & r) {r = a * b;}
void div(int & a, int & b, int & r) {r = a / b;}

int main()
{
    char * op = new char[LENGTH];
    int * in1 = new int[LENGTH];
    int * in2 = new int[LENGTH];
    int * out = new int[LENGTH];

    for (int i = 0; i < LENGTH; ++i)
    {
        *(op+i) = i % 4;
        *(in1+i) = qrand();
        *(in2+i) = qrand()+1;
    }

    *(op+LENGTH-1) = 4; // end of program


    long long  sClock, fClock;


    unsigned int c = 0;
    sClock = clock();

    cout << "Program begins" << endl;

    static void* table[] = {
        &&do_add,
        &&do_sub,
        &&do_mul,
        &&do_div,
        &&do_end,
        &&do_err,
        &&do_fin};

#define jump() goto *table[op[c++]]

    jump();
do_add:
    add(in1[c], in2[c], out[c]); jump();
do_sub:
    sub(in1[c], in2[c], out[c]); jump();
do_mul:
    mul(in1[c], in2[c], out[c]); jump();
do_div:
    div(in1[c], in2[c], out[c]); jump();
do_end:
    cout << "end of program" << endl; goto *table[6];
do_err:
    cout << "ERROR!!!" << endl; goto *table[6];
do_fin:

    fClock = clock();
    cout << fClock - sClock << endl;

    delete [] op;
    delete [] in1;
    delete [] in2;
    delete [] out;

    in1 = new int[LENGTH];
    in2 = new int[LENGTH];
    out = new int[LENGTH];

    for (int i = 0; i < LENGTH; ++i)
    {
        *(in1+i) = qrand();
        *(in2+i) = qrand()+1;
    }

    cout << "Native begins" << endl;

    sClock = clock();

    for (int i = 0; i < LENGTH; i += 4)
    {

        *(out+i) = *(in1+i) + *(in2+i);
        *(out+i+1) = *(in1+i+1) - *(in2+i+1);
        *(out+i+2) = *(in1+i+2) * *(in2+i+2);
        *(out+i+3) = *(in1+i+3) / *(in2+i+3);
    }

    fClock = clock();
    cout << fClock - sClock << endl;

    delete [] in1;
    delete [] in2;
    delete [] out;

    return 0;
}

Darek Mihocka 有一篇关于在可移植 C 中创建快速解释器的精彩而深入的文章:http://www.emulators.com/docs/nx25_nostradamus.htm http://www.emulators.com/docs/nx25_nostradamus.htm

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VM/解释器的性能改进策略? 的相关文章

  • 在c#中执行Redis控制台命令

    我需要从 Redis 控制台获取 客户端列表 输出以在我的 C 应用程序中使用 有没有办法使用 ConnectionMultiplexer 执行该命令 或者是否有内置方法可以查找该信息 CLIENT LIST是 服务器 命令 而不是 数据库
  • 为什么pow函数比简单运算慢?

    从我的一个朋友那里 我听说 pow 函数比简单地将底数乘以它的指数的等价函数要慢 例如 据他介绍 include
  • ComboBox DataBinding 导致 ArgumentException

    我的几个类对象 class Person public string Name get set public string Sex get set public int Age get set public override string
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • 从同一个类中的另一个构造函数调用构造函数

    我有一个带有两个构造函数的类 C 这是代码片段 public class FooBar public FooBar string s constructor 1 some functionality public FooBar int i
  • File.AppendText 尝试写入错误的位置

    我有一个 C 控制台应用程序 它作为 Windows 任务计划程序中的计划任务运行 此控制台应用程序写入日志文件 该日志文件在调试模式下运行时会创建并写入应用程序文件夹本身内的文件 但是 当它在任务计划程序中运行时 它会抛出一个错误 指出访
  • 使用 LINQ to SQL 时避免连接超时的最佳实践

    我需要知道在 net 应用程序中使用 LINQ to SQL 时避免连接超时的最佳实践 特别是在返回时IQueryable
  • 在Linux中,找不到框架“.NETFramework,Version=v4.5”的参考程序集

    我已经设置了 Visual studio 来在我的 Ubuntu 机器上编译 C 代码 我将工作区 我的代码加载到 VS 我可以看到以下错误 The reference assemblies for framework NETFramewo
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 启动时的 Excel 加载项

    我正在使用 Visual C 创建 Microsoft Excel 的加载项 当我第一次创建解决方案时 它包含一个名为 ThisAddIn Startup 的函数 我在这个函数中添加了以下代码 private void ThisAddIn
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • WPF DataGridTemplateColumn 组合框更新所有行

    我有这个 XAML 它从 ItemSource 是枚举的组合框中选择一个值 我使用的教程是 http www c sharpcorner com uploadfile dpatra combobox in datagrid in wpf h
  • 使 Guid 属性成为线程安全的

    我的一个类有一个 Guid 类型的属性 该属性可以由多个线程同时读写 我的印象是对 Guid 的读取和写入不是原子的 因此我应该锁定它们 我选择这样做 public Guid TestKey get lock testKeyLock ret
  • Unity:通过拦截将两个接口注册为一个单例

    我有一个实现两个接口的类 我想对该类的方法应用拦截 我正在遵循中的建议Unity 将两个接口注册为一个单例 https stackoverflow com questions 1394650 unity register two inter
  • 将数组作为参数传递

    如果我们修改作为方法内参数传递的数组的内容 则修改是在参数的副本而不是原始参数上完成的 因此结果不可见 当我们调用具有引用类型参数的方法时 会发生什么过程 这是我想问的代码示例 using System namespace Value Re
  • 在 Windows Phone silverlight 8.1 上接收 WNS 推送通知

    我有 Windows Phone 8 1 silverlight 应用程序 我想使用新框架 WNS 接收通知 我在 package appxmanifest 中有
  • 使用 C 在 OS X 中获取其他进程的 argv

    我想获得其他进程的argv 例如ps 我使用的是在 Intel 或 PowerPC 上运行的 Mac OS X 10 4 11 首先 我阅读了 ps 和 man kvm 的代码 然后编写了一些 C 代码 include
  • 如何使用 C++11 using 语法键入定义函数指针?

    我想写这个 typedef void FunctionPtr using using 我该怎么做呢 它具有类似的语法 只不过您从指针中删除了标识符 using FunctionPtr void 这是一个Example http ideone
  • 如何将十六进制字符串转换为无符号长整型?

    我有以下十六进制值 CString str str T FFF000 如何将其转换为unsigned long 您可以使用strtol作用于常规 C 字符串的函数 它使用指定的基数将字符串转换为 long long l strtol str
  • OpenCV SIFT 描述符关键点半径

    我正在深入研究OpenCV的SIFT描述符提取的实现 https github com Itseez opencv blob master modules nonfree src sift cpp 我发现了一些令人费解的代码来获取兴趣点邻域

随机推荐

  • 如何延迟连接流?

    我正在尝试实现一个在其实现中使用其自身的另一个实例的流 该流前面有一些常量元素 使用 IntStream concat 因此只要串联流惰性地创建非常量部分 这应该就可以工作 我认为使用StreamSupport intStream 重载采用
  • 使用 ThreadPool Python 时的最大池大小

    我正在使用 ThreadPool 来实现多处理 使用多处理时 池大小限制应等于 CPU 核心数 我的问题 使用 ThreadPool 时 池大小限制应该是 CPU 核心数吗 这是我的代码 from multiprocessing pool
  • 外键为空 - 性能下降

    我有一个表文件夹 其中列parent id 引用id 如果该文件夹有父级 如果没有 则parent id 为空 这是好的解决方案还是我需要额外的表来进行此连接或其他解决方案 外键是否可以为空 如果可以 这个解决方案将有更长的执行时间 tab
  • 无法访问 Axios 拦截器内的 Vuex 存储突变

    EDIT 这个问题非常混乱 所以我基本上用相同的代码示例和相同的场景重写它 当服务器发送 401 错误响应时 我试图 commit从拦截器到我的 vuex 存储 import axios from axios import store fr
  • 用于查看特定端口的命令行

    有没有办法从 Windows 命令行检查特定端口的状态 我知道我可以使用 netstat 检查所有端口 但 netstat 很慢 并且查看特定端口可能不会 这里是简单的解决方案端口查找 In cmd netstat na find 8080
  • 在 Visual Studio 2015 中哪里可以找到 Microsoft.TeamFoundation.Build.Client?

    我有一个干净的 Windows 安装 仅安装了 Visual Studio 2015 并且我正在寻找 Microsoft TeamFoundation Build Client 程序集 我想知道它现在是否已随着即将推出的 vNext Bui
  • 如何将Python数据类转换为字符串文字字典?

    给定一个如下所示的数据类 class MessageHeader BaseModel message id uuid UUID def dict self kwargs return json loads self json 我想在调用时获
  • 每个进程的最大线程数 - sysconf(_SC_THREAD_THREADS_MAX) 失败

    我试图找到 UNIX 机器上每个进程的最大线程数 并编写下面的代码来使用 sysconf include
  • 如何追踪“libc++abi.dylib:调用了纯虚函数!”在Xcode中

    我有一个混合使用 C Objective C 和 Swift 的多线程 OS X 应用程序 当我的应用程序关闭时 我在 Xcode 调试器窗口中看到以下内容 libc abi dylib Pure virtual function call
  • python/pandas/一维数据框

    创建二维数据框效果很好 y np array 1 2 3 4 df pd DataFrame y index 1 2 columns a b print df 但是如果我尝试创建一维数据框 我会收到一条错误消息 z np array 5 6
  • 如何检查ngIf是否生效

    我在做什么我有一个隐藏 显示的组件 ngIf基于简单的布尔值 当组件变得可见时 我想将焦点应用于其模板中的子元素 问题如果我翻转布尔值 组件会正确显示 但如果我尝试使用以下命令获取对子元素的引用this elRef nativeElemen
  • 为什么“plain_dictionary”编码的字典页偏移量为 0?

    parquet由Spark v2 4 Parquet mr v1 10生成 n 10000 x 1 0 2 0 3 0 4 0 5 0 5 0 None n y u u u u u a None u a n z np random rand
  • Github 和 heroku 上的应用程序:忽略其中一个上的文件,但不忽略另一个上的文件

    我有一个应用程序 其代码位于 github 上 但托管在 heroku 上 我在 Github 上有一个我不想要的配置文件 但在 heroku 上我需要 有人有聪明的解决方案吗 Use 配置变量 http devcenter heroku
  • pandas 系列中列表的高效串联

    我有以下系列 s pd Series a b c d f g gt gt gt s 0 a b 1 c d 2 f g dtype object 连接系列中所有列表的最简单的方法 最好是矢量化的方法 是什么 以便我得到 l a b c d
  • 如何使用 Prolog 查找二叉树的深度

    我正在学习 Prolog 并试图找到一个深度二叉树使用 Prolog 我代表一棵树是这样的 nil is a tree tree 1 nil nil this is a leaf tree 1 tree 1 nil nil nil this
  • Rails 4 热切负载限制子查询

    有没有办法避免急切加载时的 n 1 问题并对子查询应用限制 我想避免大量这样的 sql 查询 Category all each do category category posts limit 10 end 但我也希望每个类别只获取 10
  • 在 PHP 中将值数组转换为单个浮点值?

    我有一个包含这些值的数组 当数组打印为print r Array 0 gt 66 1 gt 233 2 gt 204 3 gt 205 十六进制值是 Array 0 gt 0x42 1 gt 0xE9 2 gt 0xCC 3 gt 0xCD
  • R 闪亮盒子中可移动多个项目 - 类似于所附屏幕截图

    我正在尝试构建一个闪亮的应用程序 我正在尝试构建类似于下面的屏幕截图的功能 我已经使用 Shinyjqui sortable 构建了类似的东西 但我想在移动项目之前允许多重选择 请告诉我是否有人构建 从事过类似的事情 下面是我使用 shin
  • 由于图像太多,应用程序尺寸太大

    我正在创建一个通用应用程序 对于一个屏幕 我使用以下命令在网格中显示 6 个图像 png 格式 this https github com gmoledina GMGridView控制 此外 该屏幕支持纵向和横向 我为所有 iDevice
  • VM/解释器的性能改进策略?

    我用 C 语言编写了一个简单的 VM 使用简单的指令切换 没有任何指令解码 但性能很糟糕 对于简单的算术运算 对于相同的运算 VM 比本机 C 代码慢大约 4000 倍 我测试了一组长度为1000万的数组 第一个数组由程序指令 随机 操作组