编译器优化

什么时候汇编比C更快?

我与影子孤独终老i 提交于 2020-02-26 09:07:19
已知的了解汇编器的原因之一是,有时可以用它来编写比用高级语言(尤其是C)编写更高性能的代码。 但是,我也听到过很多次声明,尽管这并非完全错误,但 实际上 可将汇编程序用于生成更多性能代码的情况极为罕见,并且需要汇编方面的专业知识和经验。 这个问题甚至都没有涉及到汇编程序指令将是特定于机器且不可移植的,或者汇编程序的任何其他方面。 当然,除了汇编语言之外,还有很多了解汇编语言的充分理由,但这是一个特定的问题,需要征集示例和数据,而不是对汇编语言和高级语言的扩展论述。 谁能提供一些 特定的例子 , 说明 使用现代编译器进行汇编比编写良好的C代码要快得多,并且您可以提供带有分析依据的主张吗? 我对这些案例的存在很有信心,但是我真的想确切地知道这些案例有多深奥,因为这似乎有些争议。 #1楼 根据我的经验,有几个例子: 访问无法从C访问的指令。例如,许多体系结构(如x86-64,IA-64,DEC Alpha和64位MIPS或PowerPC)支持64位乘64位乘法,产生128位结果。 GCC最近添加了扩展名,以提供对此类说明的访问,但是在需要该程序集之前。 当实施RSA之类的东西时,访问此指令可能对64位CPU产生巨大的影响-有时性能会提高4倍。 访问特定于CPU的标志。 咬住我很多的是进位标志; 在进行多精度加法运算时,如果您无法访问CPU进位,则必须比较结果以查看其是否溢出

Golang之变量去哪儿

蹲街弑〆低调 提交于 2020-02-26 07:30:36
目录 什么是逃逸分析 为什么要逃逸分析 逃逸分析是怎么完成的 逃逸分析实例 总结 参考资料 写过C/C++的同学都知道,调用著名的malloc和new函数可以在堆上分配一块内存,这块内存的使用和销毁的责任都在程序员。一不小心,就会发生内存泄露,搞得胆战心惊。 切换到Golang后,基本不会担心内存泄露了。虽然也有new函数,但是使用new函数得到的内存不一定就在堆上。堆和栈的区别对程序员“模糊化”了,当然这一切都是Go编译器在背后帮我们完成的。 一个变量是在堆上分配,还是在栈上分配,是经过编译器的 逃逸分析 之后得出的结论。 这篇文章,就将带领大家一起去探索 逃逸分析 ——变量到底去哪儿,堆还是栈? 什么是逃逸分析 以前写C/C++代码时,为了提高效率,常常将 pass-by-value (传值)“升级”成 pass-by-reference ,企图避免构造函数的运行,并且直接返回一个指针。 你一定还记得,这里隐藏了一个很大的坑:在函数内部定义了一个局部变量,然后返回这个局部变量的地址(指针)。这些局部变量是在栈上分配的(静态内存分配),一旦函数执行完毕,变量占据的内存会被销毁,任何对这个返回值作的动作(如解引用),都将扰乱程序的运行,甚至导致程序直接崩溃。比如下面的这段代码: int *foo ( void ) { int t = 3; return &t; }

存储持续性、作用域和链接性

北城以北 提交于 2020-02-26 00:00:01
例子: 头文件:state.h 源文件:state.cpp 其它源文件:t1.cpp t2.cpp t3.cpp, 这些源文件都包含头文件state.h。 需要定义一个全局变量供这些源文件中使用:方法如下 1、在 state.h声明全局变量: extern inta; 2、在state.cpp中定义该全局变量:int a =10; 这样其它源文件就可以使用该变量啦 这里需要的是“声明”,不是“定义”!根据C++标准的规定,一个变量声明必须同时满足两个条件,否则就是定义: (1)声明必须使用extern关键字;(2)不能给变量赋初值 extern int a; //声明 int a; //定义 int a = 0; //定义 extern int a =0; //定义 头文件中应使用extern关键字声明全局变量(不定义),如果这个变量有多个文件用到,可以新建一个cpp,在其中定义,把这个cpp加入工程即可。 头文件请不要定义任何变量,那是非常业余的行为…… 一般在头文件中申明,用extern,在cpp中定义。 如果在头文件中定义,如果这个头文件被多个cpp引用,会造成重复定义的链接错误。 头文件只能申明全局变量(extern),不可定义(不推荐使用) .cpp里,在最外层定义即可(int gi),直接引用 如果在.cpp里使用static定义,则该变量只在当前cpp文件中有效

scala编程(八)——函数和闭包

江枫思渺然 提交于 2020-02-24 15:25:28
当程序变得庞大时,你需要一些方法把它们分割成更小的,更易管理的片段。为了分割控制流, Scala 提供了所有有经验的程序员都熟悉的方式:把代码分割成函数。实际上, Scala 提供了许多 Java 中没有的定义函数的方式。除了作为对象成员函数的方法之外,还有内嵌在函数中的函数, 函数文本和函数值。本章带你体会所有 Scala 中的这些函数的风味。 方法 定义函数最通用的方法是作为某个对象的成员。这种函数被称为方法:method。 作为例子,示例代码 展示了两个可以合作根据一个给定的文件名读文件并打印输出所有长度超过给定宽度的行的 方法。每个打印输出的行前缀它出现的文件名: object LongLines { def processFile(filename: String, width: Int) { val source = Source.fromFile(filename) for (line <- source.getLines) processLine(filename, width, line) } private def processLine(filename:String, width:Int, line:String) { if (line.length > width) println(filename+": "+line.trim) } def main

linux C 中的volatile使用

孤街醉人 提交于 2020-02-23 16:40:25
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1). 并行设备的硬件寄存器(如:状态寄存器) 2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 3). 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。 假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。 1). 一个参数既可以是const还可以是volatile吗?解释为什么。 2). 一个指针可以是volatile 吗?解释为什么。 3). 下面的函数有什么错误: int square(volatile int *ptr) { return *ptr * *ptr; } 下面是答案: 1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变

JVM复习总结

久未见 提交于 2020-02-22 19:49:45
JVM即Java虚拟机,主要用来编译,执行Java代码,并在执行过程中对内存进行管理. Java代码的执行流程 Java代码首先要通过javac前期编译器从.java文件编译为.class字节码文件(注解处理),然后将.class文件交由虚拟机的类加载器ClassLoader进行装载(采用 双亲委派机制 进行装载),将.class文件装入java虚拟机后,Hotspot虚拟机根据配置的模式( 混合模式,解释模式,编译模式 )来决定使用解释器直接 解释执行 还是使用 JIT即时编译器 进行 编译执行 ,亦或者是两者混用的混合模式进行执行.默认采用混合模式执行. Hotspot虚拟机内置了两个即时编译器,称为 client编译器 和 server编译器 (C1,C2编译器),前者进行一些稳定可靠的优化,后者还会进行一些激进不可靠的优化策略.后者编译出的机器码相对前者质量要高,而前者进行编译的速度要比后者快. 可靠的编译优化: 热点代码替换 , 栈上替换 .原理:基于采样的热点探测,方法调用计数器和回边计数器. 方法内联 基于逃逸分析的编译优化:栈上分配, 标量替换 , 同步消除 . java运行时数据区 程序运行后要对内存进行管理,Java虚拟机的运行时数据区分为 堆 , 虚拟机栈 , 本地方法栈 , 程序计数器 , 元空间 堆 中存放着对象(大小不固定), 虚拟机栈

值得学习的C语言开源项目

时光毁灭记忆、已成空白 提交于 2020-02-22 13:03:03
1.Webbench Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力。Webbench使用C语言编写, 代码实在太简洁,源码加起来不到600行。 下载链接: https://github.com/LippiOuYang/WebBenchl 2.Tinyhttpd tinyhttpd是一个超轻量型Http Server,使用C语言开发,全部代码只有502行(包括注释),附带一个简单的Client,可以通过阅读这段代码理解一个 Http Server 的本质。 下载链接: https://github.com/LippiOuYang/Tinyhttpd 3.cJSON cJSON是C语言中的一个JSON编解码器,非常轻量级,C文件只有500多行,速度也非常理想。 cJSON也存在几个弱点,虽然功能不是非常强大,但cJSON的小身板和速度是最值得赞赏的。其代码被非常好地维护着,结构也简单易懂,可以作为一个非常好的C语言项目进行学习。 项目主页: http://sourceforge.net/projects/cjson/ 4.CMockery cmockery是google发布的用于C单元测试的一个轻量级的框架。它很小巧

LLVM与Clang

╄→尐↘猪︶ㄣ 提交于 2020-02-21 10:31:40
随着 Android P 的逐步应用,越来越多的客户要求编译库时用 libc++ 来代替 libstdc++。libc++ 和 libstdc++ 这两个库有关系呢?它们两个都是 C++ 标准库,libc++ 是针对 Clang 编译器特别重写的 C++ 标准库,而 libstdc++ 则是 GCC 的对应 C++ 标准库了。从 Android 市场来说,Android NDK 已在具体应用中放弃了 GCC,全面转向 Clang。 Android NDK 从 r11 开始建议大家切换到 Clang,并且把 GCC 标记为 deprecated,将 GCC 版本锁定在 GCC 4.9 不再更新; Android NDK 从 r13 起,默认使用 Clang 进行编译,但是暂时也没有把 GCC 删掉,Google 会一直等到 libc++ 足够稳定后再删掉 GCC; Android NDK 在 r17 中宣称不再支持 GCC 并在后续的 r18 中删掉 GCC,具体可见 NDK 的版本历史。 接下来,简要的介绍一下 Clang。Clang 是一个 C、C++、Objective-C 和 Objective-C++ 编程语言的编译器前端,采用底层虚拟机(LLVM)作为后端。至于为什么有了 GCC 还要开发 Clang?Clang 相比 GCC 又有什么优势呢?网上有很多信息可以参考

0909 编译原理

£可爱£侵袭症+ 提交于 2020-02-21 04:18:50
网络上有许许多多的有关编译原理的叙述,这个科目的资源也十分的繁多。对我们的学习会产生很大的帮助,也可以让我们更多的了解编译原理这一门科目。 1.编译原理学的是介绍编译程序构造的一般原理和基本方法。内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成。是让学生理解编译过程中有涉及的原理。 2.编译原理及技术从本质上来讲就是一个算法问题而已,当然由于这个问题十分复杂,其解决算法也相对复杂。我们学的数据结构与算法分析也是讲算法的,不过讲的基础算法,换句话说讲的是算法导论,而编译原理这门课程讲的就是比较专注解决一种的算法了。在20世纪50年代,编译器的编写一直被认为是十分困难的事情,第一Fortran的编译器据说花了18年的时间才完成。在人们尝试编写编译器的同时,诞生了许多跟编译相关的理论和技术,而这些理论和技术比一个实际的编译器本身价值更大。 3.编译原理这门课我还没有很高的了解,所以我会认真听课,做好作业,课后花时间来了解这门课目。 4.对于编译器的原理我并不了解,所以暂时没有思路,等待老师解答。 来源: https://www.cnblogs.com/liezhihua/p/4795434.html

Qt高级编码约定

谁说胖子不能爱 提交于 2020-02-18 22:21:05
Qt高级编码约定 参考 https://wiki.qt.io/Coding_Conventions 来源 https://zhuanlan.zhihu.com/p/97723847 发布于 2019-12-16 这是我们在编写Qt代码时使用的高级编码约定的概述。有关Qt代码规范,请参见 Qt代码风格 一文。对于QML,请参阅 QML代码规范 一文。 C++特性 不要使用异常。 不要使用rtti(运行时类型信息:即typeinfo结构,dynamic_cast或typeid运算符,包括引发异常)。 谨慎明智地使用模板,不仅仅是因为可以使用。 提示:使用编译自动测试可以查看测试中的所有编译器是否支持C++功能。 Qt源代码中的约定 所有代码仅是ascii(仅7位字符,如果不确定,请运行 man ascii ). 因为我们内部的语言环境太多,而且UTF-8和latin1系统的组合不健康。通常,您甚至不知道通过单击您喜欢的编辑器中的"保存"就可以破坏字符超过127个字符的范围。 对于字符串:使用 \nnn (其中nnn是要在其中输入字符串的任何字符编码的八进制表示形式)或 \xnn (其中nn是十六进制)。示例: QString s = QString::fromUtf8("13\005"); 对于文档中的变音符号或其他非ASCII字符,请使用qdoc的命令或使用相关的宏。例如 \uuml