为什么条件(三元)运算符看起来明显更快?

2024-04-24

EDIT

如果我使用Stopwatch正确地将迭代次数增加两个数量级,我得到

三进制耗时 22404ms

正常耗时21403ms

这些结果更接近我的预期,让我觉得世界一切都好(如果不是我的代码)。

事实上,三元/条件运算符稍微慢一些。


继从这个问题 https://stackoverflow.com/q/12457432/659190,我有部分answered https://stackoverflow.com/a/12458395/659190.

我在 x64 发布模式下编译此控制台应用程序并启用优化,然后从命令行运行它,而无需附加调试器。

using System; 
using System.Diagnostics;

class Program
{
    static void Main()
    {
        var stopwatch = new Stopwatch();

        var ternary = Looper(10, Ternary);
        var normal = Looper(10, Normal);

        if (ternary != normal)            {
            throw new Exception();
        }

        stopwatch.Start();
        ternary = Looper(10000000, Ternary);
        stopWatch.Stop();
        Console.WriteLine(
            "Ternary took {0}ms", 
            stopwatch.ElapsedMilliseconds);

        stopwatch.Start();
        normal = Looper(10000000, Normal);
        stopWatch.Stop();
        Console.WriteLine(
            "Normal took {0}ms", 
            stopwatch.ElapsedMilliseconds);

        if (ternary != normal)            {
            throw new Exception();
        }

        Console.ReadKey();
    }

    static int Looper(int iterations, Func<bool, int, int> operation)
    {
        var result = 0;
        for (int i = 0; i < iterations; i++)
        {
            var condition = result % 11 == 4;
            var value = ((i * 11) / 3) % 5;
            result = operation(condition, value);
        }

        return result;
    }

    static int Ternary(bool condition, in value)
    {
        return value + (condition ? 2 : 1);
    }

    static int Normal(int iterations)
    {
        if (condition)
        {
            return = 2 + value;
        }
        
        return = 1 + value;
    }
}

我没有遇到任何异常,并且控制台的输出接近于,

三进制耗时 107ms

正常耗时230ms

当我将 CIL 分解为两个逻辑函数时,我得到了这个,

... Ternary ...
{
     : ldarg.1      // push second arg
     : ldarg.0      // push first arg
     : brtrue.s T   // if first arg is true jump to T
     : ldc.i4.1     // push int32(1)
     : br.s F       // jump to F
    T: ldc.i4.2     // push int32(2)
    F: add          // add either 1 or 2 to second arg
     : ret          // return result
}

... Normal ...
{
     : ldarg.0      // push first arg
     : brfalse.s F  // if first arg is false jump to F
     : ldc.i4.2     // push int32(2)
     : ldarg.1      // push second arg
     : add          // add second arg to 2
     : ret          // return result
    F: ldc.i4.1     // push int32(1)
     : ldarg.1      // push second arg
     : add          // add second arg to 1
     : ret          // return result
}

虽然TernaryCIL 有点短,在我看来,任一函数通过 CIL 的执行路径都需要 3 次加载和 1 或 2 次跳转以及返回。为什么Ternary功能似乎快了一倍。

我知道,在实践中,它们都非常快,而且确实足够快,但是,我想了解其中的差异。


两者花费的时间几乎完全相同。

您的结果不正确是因为您根本没有使用Stopwatch正确。 “正常”的测量包括所花费的时间both弯针。

如果你改变第二个

stopwatch.Start();

to

stopwatch.Restart();

然后你就会得到正确的结果。


顺便说一句,为了获得更公平的比较,您可能应该执行

    return (condition ? value + 2 : value + 1);

代替

    return value + (condition ? 2 : 1);

因此它与另一个函数完全相同。否则你正在测量not only条件运算符。

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

为什么条件(三元)运算符看起来明显更快? 的相关文章

  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new

随机推荐

  • Knockout.js、映射插件和 moment.js - 格式化/映射 json 日期

    我将 Knockout js 与映射插件一起使用 我正在获取一些 json 数据并使用映射插件将其映射到我的 html 中 json 数据中是 json 格式的日期 我需要使用映射插件将其映射到 html 中 是否可以使用 moment j
  • iOS - 异步图像下载

    我正在编写一个应用程序 它将在 UIImageView 中显示在我的服务器上找到的图像 我需要一些能够异步下载图像并缓存它的东西 同时将其放入 UIImageView 中 当我按下按钮时 下载也需要能够取消 谁能指出我可以做到这一点的方向吗
  • 为什么 JVM 同时具有“invokespecial”和“invokestatic”操作码?

    两条指令都使用静态而不是动态调度 似乎唯一的实质性区别是invokespecial始终将一个对象作为其第一个参数 该对象是分派方法所属类的实例 然而 invokespecial实际上并没有把物体放在那里 编译器负责通过在发出之前发出适当的堆
  • 视图“~/Views/Login/Login.aspx”必须派生自 ViewPage、ViewPage、ViewUserControl 或 ViewUserControl

    因此 我在 ASP NET mvc2 解决方案上遇到此错误 该解决方案曾经工作正常 我必须安装 Visual Studio 2012 但磁盘空间不足 因此必须手动卸载一些 Visual Studio 2010 功能 但目前看来并非完全必要
  • 嵌套的可分割对象不读取

    我正在尝试打包一个包含一些 string int 变量和一个对象变量的对象 字符串和整数可以工作 但嵌套对象不行 我知道我也必须将其打包 但我显然做错了 在我的嵌套类中 writeToParcel方法被调用 我检查Log d 调用 但是cr
  • Javascript:如何实现异步函数队列(无需库)

    我一直在搜索谷歌和SO 但由于某种原因我很难解决这个问题 只是强调一下 我不想加载像 JQuery 这样的库 因为我不需要它的大部分内容 当我could使用动画库 我已经构建了我自己需要的几个函数 其中一些甚至不是您在库中找到的标准动画 所
  • 用于 SQL 更新语句的 Java 单工作线程

    我正在开发一个基于 Java 的服务器 其中有多个线程 每个连接的用户一个线程 一些额外的线程 会涉及到一些数据库连接 所以我在想服务器每次创建一个SELECT查询数据库时 它将为此启动一个新线程 以防止当前线程阻塞 我计划为此使用连接池
  • 当我尝试打开我的网络应用程序(在本地主机上运行)时,Heroku 给出了 503

    我正在尝试部署到heroku 但即使它在本地主机上运行 也会得到503 我很好奇我的服务器是否设置正确 因为我是编程新手 我希望任何人都可以为我指出正确的方向 即在哪里查找或提供建议 因为我在谷歌上花费了无数个小时 跨越了几周的时间 我的主
  • 如何在C中访问正确的全局变量?

    假设我在 main c 中有一些全局变量 GLOBAL 但我的 main c 有一个 include other h 但 other h 也有全局变量 GLOBAL 当我在 main c 中写 GLOBAL 时 如何让编译器知道我的意思是哪
  • 附加不同 Promise 链时 JavaScript Promise 的执行顺序

    我想检查一下promise对象通过创建一个promise并传递给其他人并让其他人附上then到它 输出与我的预期相去甚远 我不明白它是如何执行的 const wait time gt return new Promise res rej g
  • 如何禁用 jQuery 日期选择器中的月份选择?

    我正在尝试禁用允许用户更改月份的左 右按钮 我已经删除了月份的下拉列表 但无法删除按钮 date datepicker changeMonth false changeYear false dateFormat dd mm yy durat
  • 适合所有人的 vsixmanifest:VS 2010、2012 和 2013

    我在 VS2013 下使用 VSIX 清单设计器 我已经添加微软VisualStudio专业版产品标识符和 10 0 13 0 安装目标的版本范围 尽管如此 我仍然没有将 VS2010 Professional 视为可用的安装目标 sour
  • 如何正确阅读EcmaScript规范

    我对 JavaScript 二进制逻辑运算的 它是如何工作的 知识感兴趣 但我陷入了步骤解释 这就是规格的描述 12 13 3 https www ecma international org ecma 262 8 0 index html
  • 使用 Dask 处理大型压缩 csv 文件

    设置是我有八个大的 csv 文件 每个 32GB 每个文件都用 Zip 压缩为 8GB 文件 我无法使用未压缩的数据 因为我想节省磁盘空间 但没有剩余 32 8GB 空间 我无法加载一个文件 例如pandas因为它不适合内存 我认为 Das
  • Java 泛型值。

    我进行了一次面试测试 看到了以下代码 EDIT public class TestValue private Value
  • 获取前 5 个频繁值及其总数 Linq-to-Sql

    我正在使用这个 Linq to sql 来获取最多出现的记录 List
  • R 中 NA 的累积回报

    我有以下数据框 df lt data frame Return1 c NA NA 03 04 05 Return2 c 25 33 NA 045 90 Return3 c 04 073 08 04 01 Return1 Return2 Re
  • React Native:-如何在所有页面上使用公共抽屉和工具栏并进行控制

    我是 React Native 的新手 我想为 android 和 ios 制作一个抽屉和工具栏 我在我有导航器的主页上编写了抽屉和工具栏的代码 就像例如
  • Eclipse 总是突然关闭

    最近我的 Eclipse 遇到了很多问题 它不断崩溃 突然关闭 根本无法正常工作 这种情况发生的次数太多了 比如每 10 15 分钟一次 发生这种情况时 CPU 和 RAM 可用 50 这是eclipse ini file startup
  • 为什么条件(三元)运算符看起来明显更快?

    EDIT 如果我使用Stopwatch正确地将迭代次数增加两个数量级 我得到 三进制耗时 22404ms 正常耗时21403ms 这些结果更接近我的预期 让我觉得世界一切都好 如果不是我的代码 事实上 三元 条件运算符稍微慢一些 继从这个问