LLVM的ThinLTO编译优化技术在Postgresql中的应用

部分内容引用:https://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html

LTO是什么?

链接时优化(Link-time optimization,简称LTO)是编译器在链接时对程序进行的一种优化。它适用于以文件为单位编译程序,然后将这些文件链接在一起的编程语言(如C和Fortran),而不是一次性编译(如Java的即时编译(JIT))。

传统上,编译器将所有文件分别编译成目标文件,然后将这些目标文件链接成一个单独的可执行文件。然而,在GNU编译器集合(GCC)和LLVM中实现的LTO中,编译器能够转储其中间表示(IR),即GIMPLE字节码或LLVM字节码,以便在最终链接时将组成单个可执行文件的所有不同编译单元作为单个模块进行优化。这扩大了跨过程优化的范围,涵盖了整个程序(或者更准确地说,链接时可见的所有内容)。通过链接时优化,编译器可以对整个程序应用各种形式的跨过程优化,进行更深入的分析、更多的优化,从而实现更好的程序性能。

实际上,LTO并不总是对整个程序进行优化,特别是动态链接的共享对象等库函数会被有意排除在外,以避免过多的重复和允许更新。静态链接自然适用于LTO的概念,但它只适用于包含IR对象而不是仅包含机器码的库存档文件。由于性能问题,甚至不总是直接使用整个单元,可以将程序分割成类似GCC的WHOPR的分而治之的LTO形式。当构建的程序本身是一个库时,优化会保留每个外部可用(导出的)符号,而不会过于努力地将它们作为DCE的一部分删除。

即使没有LTO,仍然可以使用一种更有限的WPO形式,例如GCC的-fwhole-program开关。这种模式使GCC假设正在编译的模块包含整个程序的入口点,因此其中的其他函数不会被外部使用,可以安全地进行优化。由于它仅适用于单个模块,因此无法真正涵盖整个程序。它可以与LTO结合使用,以一大模块的方式,这在链接器不会向GCC反馈外部使用的入口点或符号时非常有用。

LLVM提供的lto独立工具:

$ llvm-lto --help
OVERVIEW: llvm LTO linkerUSAGE: llvm-lto [options] <input bitcode files>OPTIONS:Color Options:--color                                 - Use colors in output (default=autodetect)Generic Options:--help                                  - Display available options (--help-hidden for more)--help-list                             - Display list of available options (--help-list-hidden for more)--version                               - Display the version of this programLTO Options:-O <char>                               - Optimization level. [-O0, -O1, -O2, or -O3] (default = '-O2')--check-for-objc                        - Only check if the module has objective-C defined in it--disable-verify                        - Do not run the verifier during the optimization pipeline--dso-symbol=<string>                   - Symbol to put in the symtab in the resulting dso--exported-symbol=<string>              - List of symbols to export from the resulting object file-j <uint>                               - Number of backend threads--list-dependent-libraries-only         - Instead of running LTO, list the dependent libraries in each IR file--list-symbols-only                     - Instead of running LTO, list the symbols in each IR file--lto-freestanding                      - Enable Freestanding (disable builtins / TLI) during LTO-o <filename>                           - Override output filename--print-macho-cpu-only                  - Instead of running LTO, print the mach-o cpu in each IR file--restore-linkage                       - Restore original linkage of globals prior to CodeGen--save-linked-module                    - Write linked LTO module to file before optimize--save-merged-module                    - Write merged LTO module to file before CodeGen--set-merged-module                     - Use the first input module as the merged module--thinlto                               - Only write combined global index for ThinLTO backends--thinlto-action=<value>                - Perform a single ThinLTO stage:=thinlink                             -   ThinLink: produces the index by linking only the summaries.=distributedindexes                   -   Produces individual indexes for distributed backends.=emitimports                          -   Emit imports files for distributed backends.=promote                              -   Perform pre-import promotion (requires -thinlto-index).=import                               -   Perform both promotion and cross-module importing (requires -thinlto-index).=internalize                          -   Perform internalization driven by -exported-symbol (requires -thinlto-index).=optimize                             -   Perform ThinLTO optimizations.=codegen                              -   CodeGen (expected to match llc)=run                                  -   Perform ThinLTO end-to-end--thinlto-cache-dir=<string>            - Enable ThinLTO caching.--thinlto-cache-entry-expiration=<uint> - Set ThinLTO cache entry expiration time.--thinlto-cache-max-size-bytes=<ulong>  - Set ThinLTO cache pruning directory maximum size in bytes.--thinlto-cache-max-size-files=<int>    - Set ThinLTO cache pruning directory maximum number of files.--thinlto-cache-pruning-interval=<int>  - Set ThinLTO cache pruning interval.--thinlto-index=<string>                - Provide the index produced by a ThinLink, required to perform the promotion and/or importing.--thinlto-index-stats                   - Print statistic for the index in every input files--thinlto-module-id=<string>            - For the module ID for the file to process, useful to match what is in the index.--thinlto-prefix-replace=<string>       - Control where files for distributed backends are created. Expects 'oldprefix;newprefix' and if path prefix of output file is oldprefix it will be replaced with newprefix.--thinlto-save-objects=<string>         - Save ThinLTO generated object files using filenames created in the given directory.--thinlto-save-temps=<string>           - Save ThinLTO temp files using filenames created by adding suffixes to the given file path prefix.--use-diagnostic-handler                - Use a diagnostic handler to test the handler interface

那么thinlto是什么?

LTO背景和动机

LTO(Link Time Optimization)是通过整个程序分析和跨模块优化来实现更好的运行时性能的一种方法。在编译阶段,clang会生成LLVM字节码而不是目标文件。链接器识别这些字节码文件,并在链接过程中调用LLVM来生成构成可执行文件的最终对象。LLVM实现会加载所有输入的字节码文件,并将它们合并成一个单独的模块。在这个庞大的模块上,进行了跨过程的分析(IPA)和跨过程的优化(IPO),这些优化是串行进行的。

在这里插入图片描述
在实践中,这意味着LTO通常需要大量的内存(一次性保存所有IR)并且非常慢。而且,如果通过-g启用了调试信息,IR的大小和所需的内存要求会显著增加。即使没有调试信息,这对于非常大的应用程序或在内存受限的机器上进行编译也是不可行的。这也使得增量构建变得不太有效,因为当任何输入源发生变化时,从LTO步骤开始的所有内容都必须重新执行。

ThinLTO是什么?

ThinLTO是一种新的方法,旨在像非LTO构建一样具有可扩展性,同时保留了完整LTO的大部分性能优势。

在ThinLTO中,串行步骤非常轻量且快速。这是因为它不是加载bitcode并合并单个庞大模块来执行这些分析,而是在串行链接步骤中利用每个模块的摘要进行全局分析,以及用于后续跨模块导入的函数位置索引。函数导入和其他IPO转换是在模块在完全并行的后端进行优化时执行的。

ThinLTO全局分析所启用的关键转换是函数导入,只有可能进行内联的函数被导入到每个模块中。这最大程度地减少了每个ThinLTO后端的内存开销,同时最大化了最有影响力的跨模块优化机会。因此,IPO转换是在每个扩展了其导入函数的模块上执行的。

ThinLTO过程分为3个阶段:

  1. 编译:生成带有模块摘要的IR,与完整LTO模式相同,
  2. Thin链接:thin链接器插件层,用于合并摘要并执行全局分析
  3. ThinLTO后端:基于摘要的导入和优化的并行后端(默认情况下,支持ThinLTO的链接器被设置为在线程中启动ThinLTO后端。因此,第二阶段和第三阶段之间的区别对用户来说是透明的)
    在这里插入图片描述

这个过程的关键是在第一阶段发出的摘要。

这些摘要使用位码格式发出,但设计得可以单独加载,而不涉及LLVMContext或任何其他昂贵的构造。每个全局变量和函数在模块摘要中都有一个条目。条目包含抽象描述该符号的元数据。例如,函数使用其链接类型、包含的指令数量和可选的分析信息(PGO)进行抽象化。此外,还记录了对其他全局变量的每个引用(地址引用、直接调用)。这些信息在Thin链接阶段期间构建了完整的引用图,并使用全局摘要信息进行快速分析。

总结:

ThinLTO的核心思想是将程序分为多个模块,每个模块都可以独立地进行编译和优化。然后,通过使用一个索引文件(称为"summary")来跟踪每个模块的信息,以便在链接阶段进行全局的优化。这种方式可以减少编译时间和内存消耗,同时仍能够实现类似于WPO的优化效果。

Postgresql中使用thinlto技术生成带有模块摘要的IR

PG根目录下的Makefile.golbal.in中增加了对LLVM的支持,位置:

# Install LLVM bitcode module (for JITing).
#
# The arguments are:
# $(1) name of the module (e.g. an extension's name or postgres for core code)
# $(2) source objects, with .o suffix
#
# The many INSTALL_DATA invocations aren't particularly fast, it'd be
# good if we could coalesce them, but I didn't find a good way.
#
# Note: blank line at end of macro is necessary to let it be used in foreach
define install_llvm_module
$(MKDIR_P) '$(DESTDIR)${bitcodedir}/$(1)'
$(MKDIR_P) $(sort $(dir $(addprefix '$(DESTDIR)${bitcodedir}'/$(1)/, $(2))))
$(foreach obj, ${2}, $(INSTALL_DATA) $(patsubst %.o,%.bc, $(obj)) '$(DESTDIR)${bitcodedir}'/$(1)/$(dir $(obj))
)
cd '$(DESTDIR)${bitcodedir}' && $(LLVM_BINPATH)/llvm-lto -thinlto -thinlto-action=thinlink -o $(1).index.bc $(addprefix $(1)/,$(patsubst %.o,%.bc, $(2)))endef

install_llvm_module函数中调用了llvm-lto -thinlto -thinlto-action=thinlink生成摘要文件:postgres.index.bc
在这里插入图片描述
postgres.index.bc只有2.7MB显然没有保存所有bitcode。通过llvm-dis反解成ll看下里面保存了什么:
在这里插入图片描述
在这里插入图片描述

  • 索引文件前半部分中保存了文件的bc路径、bc的moduleid。
  • 索引文件后半部分保存了全局变量、函数的信息,包括自身的全局guid、所属bc的moduleid、函数的连接类型、可见性、能否内联、能否抛出异常等等信息。

Postgresql如何加载使用postgres.index.bc

在llvm_load_summary中使用getModuleSummaryIndex加载postgres.index.bc,最后读取到defaultSearchPath中使用。

static std::unique_ptr<llvm::ModuleSummaryIndex>
llvm_load_summary(llvm::StringRef path)
{llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer> > MBOrErr =llvm::MemoryBuffer::getFile(path);if (std::error_code EC = MBOrErr.getError()){ilog(DEBUG1, "failed to open %s: %s", path.data(),EC.message().c_str());}else{llvm::MemoryBufferRef ref(*MBOrErr.get().get());llvm::Expected<std::unique_ptr<llvm::ModuleSummaryIndex> > IndexOrErr =llvm::getModuleSummaryIndex(ref);if (IndexOrErr)return std::move(IndexOrErr.get());elog(FATAL, "failed to load summary \"%s\": %s",path.data(),toString(IndexOrErr.takeError()).c_str());}return nullptr;
}

代码流程:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/320536.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么ai自动答题?方法揭晓!

怎么ai自动答题&#xff1f;在数字化和信息化的浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;技术日新月异&#xff0c;逐渐渗透到我们生活的方方面面。其中&#xff0c;AI自动答题软件作为辅助学习的工具&#xff0c;受到了越来越多学生和考生的青睐。它们不仅能够帮…

欢乐钓鱼大师脚本,游戏托管一键操作!

欢迎来到《钓鱼大师乐趣无穷》&#xff01;这里是一片充满了乐趣和挑战的钓鱼天地。不论你是刚刚入门的小白&#xff0c;还是已经成为老手的大神&#xff0c;本攻略将为你揭示如何在游戏中获得成功&#xff0c;并针对稀有鱼类的钓鱼技巧进行详细介绍。 一、初探钓鱼的乐趣 在《…

Bookends for Mac:文献管理工具

Bookends for Mac&#xff0c;一款专为学术、研究和写作领域设计的文献管理工具&#xff0c;以其强大而高效的功能深受用户喜爱。这款软件支持多种文件格式&#xff0c;如PDF、DOC、RTF等&#xff0c;能够自动提取文献的关键信息&#xff0c;如作者、标题、出版社等&#xff0c…

0506_IO1

思维导图&#xff1a; 练习&#xff1a; 有如下结构体 struct Student{ char name[16]; int age; double math_score; double chinese_score; double english_score; double physics_score; double chemistry_score; double bio_score; }; 申请该结构体数组&#xff0c;容量为…

【简单介绍下7-Zip】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

【春招特供】Unity面试题总结 | Unity基础篇

物体发生碰撞的必要条件&#xff1f; 两个物体都必须带有碰撞器&#xff08;Collider&#xff09;&#xff0c;其中一个物体还必须带有Rigidbody刚体&#xff0c;而且必须是运动的物体带有Rigidbody脚本才能检测到碰撞。 2. Unity3d中的碰撞器和触发器的区别&#xff1f; 碰…

Spring Security + JWT 实现登录认证和权限控制

Spring Security JWT 实现登录认证和权限控制 准备步骤 准备好一些常用的工具类&#xff0c;比如jwtUtil&#xff0c;redisUtil等。引入数据库&#xff0c;mybatis等&#xff0c;配置好controller&#xff0c;service&#xff0c;mapper&#xff0c;保证能够正常的数据请求。…

Debian是什么?有哪些常用命令

目录 一、Debian是什么&#xff1f; 二、Debian常用命令 三、Debian和CentOS的区别 四、Debian和CentOS的优缺点 五、Debian和CentOS的运用场景 一、Debian是什么&#xff1f; Debian是一种流行的开源Linux操作系统。 Debian是一个以Linux内核为基础的操…

数据结构十一:数组相关经典面试题

本篇博客详细介绍分析数组/顺序表常见的面试题&#xff0c;对于前面所学知识进行一个巩固&#xff0c;同时介绍一些力扣刷题中的一些概念&#xff1a;如&#xff1a;输出型参数等&#xff0c;在刷题中培养自己的编程思维&#xff0c;掌握常见的编程套路&#xff0c;形成题感&am…

php基础知识快速入门

一、PHP基本知识 1、php介绍&#xff1a; php是一种创建动态交互性的强有力的服务器脚本语言&#xff0c;PHP是开源免费的&#xff0c;并且使用广泛。PHP是解释性语言&#xff0c;按顺序从上往下执行&#xff0c;无需编译&#xff0c;直接运行。PHP脚本在服务器上运行。 2、ph…

瑞_23种设计模式_解释器模式

文章目录 1 解释器模式&#xff08;Interpreter Pattern&#xff09;1.1 介绍1.2 概述1.2.1 文法&#xff08;语法&#xff09;规则1.2.2 抽象语法树 1.3 解释器模式的结构1.4 解释器模式的优缺点1.5 解释器模式的使用场景 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代…

基于JSP的酒店客房管理系统(三)

目录 第四章 系统各模块的实现 4.1客房管理系统首页的实现 4.1.1 客房管理系统首页概述 4.2客房管理系统前台的实现 4.2.1 客房管理系统前台概述 4.2.2 客房管理系统前台实现过程 4.2.3 预定客房信息及客房信息的查询 4.3客房管理系统后台的实现 4.3.1 客房管理系统后…

基于springboot+vue+Mysql的在线动漫信息平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

[蓝桥杯2024]-PWN:ezheap解析(堆glibc2.31,glibc2.31下的double free)

查看保护 查看ida 大致就是只能创建0x60大小的堆块&#xff0c;并且uaf只能利用一次 完整exp&#xff1a; from pwn import* #context(log_leveldebug) pprocess(./ezheap2.31)def alloc(content):p.sendlineafter(b4.exit,b1)p.send(content) def free(index):p.sendlineaft…

LeetCode 226.翻转二叉树(全网最多的解法)

LeetCode 226.翻转二叉树 1、题目 题目链接&#xff1a;226. 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#…

怎么通过Java语言实现远程控制无人售货柜

怎么通过Java语言实现远程控制无人售货柜呢&#xff1f; 本文描述了使用Java语言调用HTTP接口&#xff0c;实现控制无人售货柜&#xff0c;独立控制售货柜、格子柜的柜门。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格 序号设备名称厂商1智能WiFi控…

52. 【Android教程】网页视图:WebView

在前面的章节我们所围绕的全部都是纯客户端开发&#xff0c;我们叫 Native 开发。这样的好处就是体验和性能会非常好&#xff0c;但是在实际的使用中我们会发现存在大量的 H5 页面。这样就可以结合 Native / H5 双端的优势完成一个混合开发&#xff0c;而在这种开发模式中首当其…

[HNOI2003]激光炸弹

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 二维前缀和板题。 注意从&#xff08;1,1&#xff09;开始存即可&#xff0c;所以每次输入x,y之后&#xff0c;要x,y。 因为m的范围最大为…

微搭低代码入门05文件的上传和下载

目录 1 创建数据源2 创建应用3 创建页面4 设置导航功能5 文件上传6 文件下载总结 小程序中&#xff0c;我们通常会有文件的上传和下载的需&#xff0c;在微搭中&#xff0c;文件是存放在云存储中&#xff0c;每一个文件都会有一个唯一的fileid&#xff0c;我们本篇就介绍如何通…

农药生产厂污废水如何处理达标

农药生产厂的污废水处理是确保该行业对环境的负面影响最小化的重要环节。下面是一些常见的处理方法和步骤&#xff0c;可以帮助农药生产厂的污废水达到排放标准&#xff1a; 预处理&#xff1a;将废水进行初步处理&#xff0c;去除大颗粒悬浮物和固体残渣。这可以通过筛网、沉淀…