首页 文章 精选 留言 我的

精选列表

搜索[日活数],共10000篇文章
优秀的个人博客,低调大师

数仓中长跳转问题复现及解决方案

摘要:本文将GaussDB(DWS)中长跳转引发的错误抽象为例子,讨论了C语言在长跳转下可能会出现的问题,最后简单给出了解决方法和验证。 本文分享自华为云社区《GaussDB(DWS)中长跳转可能出现的问题》,作者: 雷电与骤雨。 问题描述,在GaussDB(DWS)编码实践中,发现在debug未进行编译器优化的版本未发生问题,但是在release版本,发生了一些变量赋值后失效,仍为旧值的bug,本文将对此在两个角度下进行简单分析。 什么是长跳转? 在C语言中,goto语句常常实现程序执行中的近程跳转(local jump),longjmp()和setjmp()函数实现程序执行中的远程跳转(nonlocaljump,也叫farjump)。 主要相关的为两个函数的签名: int setjmp(jmp_buf env); void longjmp(jmp_buf env, int value); 一般理解为:setjmp 函数把执行这个函数时的各种上下文信息保存起来,储存到jmp_buf中,主要就是当前栈的位置,寄存器状态。longjmp 函数跳转到参数 env 缓冲区中保存的上下文(快照)中去。并且也有人提出会与实现方式 implementation有关。 我觉得下面这句还是比较可信的: The setjmp() function saves the contents of most of the general purpose registers, in the same way as they would be saved on any function entry. It also saves the stack pointer and the return address. All these are placed in the buffer. It then arranges for the function to return zero. 编译器优化问题 问题发生于debug版本和release版本出现了不同的结果,其中的差异主要是编译器在编译构建中的优化过程。一般编译器优化常用的方法有:将内存变量缓存到寄存器。 由于访问寄存器要比访问内存单元快的多,编译器在存取变量时,为提高存取速度,编译器优化有时会先把变量读取到一个寄存器中;以后再取变量值时就直接从寄存器中取值。但在很多情况下会读取到脏数据,严重影响程序的运行效果。 解决方法 C++ Volatile关键字 Volatile,词典上的解释为:易失的;易变的;易挥发的。个人理解就是在每次给该变量赋值后,需要将其放入内存,而非直接使用寄存器,此时可以避免因为jump和函数跳转带来的未写入内存导致赋值未成功(仍为旧值),或者编译器优化,将值直接放于寄存器(此值可能因为多次使用,避免从内存中来回多次读取)。 问题复现 实例未优化,debug未优化版本 #include <stdio.h> #include <stdlib.h> #include <setjmp.h> static jmp_buf env; static void doJump(int nvar, int rvar, int vvar) { printf("Inside doJump(): nvar=%d, rvar=%d, vvar=%d\n" , nvar,rvar, vvar); //死代码块 int nvar0 = nvar; int rvar0 = rvar; int vvar0 = vvar; longjmp(env, 1); } int main(int argc, char** argv) { int nvar; register int rvar; volatile int vvar; nvar = 111; rvar = 222; vvar = 333; if(setjmp(env) == 0) { nvar = 777; rvar = 888; vvar = 999; doJump(nvar, rvar, vvar); } else { int nvar1 = nvar; int rvar1 = rvar; int vvar1 = vvar; printf("After longjmp(): nvar =%d, rvar=%d, vvar=%d\n", nvar, rvar, vvar); } exit(EXIT_SUCCESS); } 程序运行结果 将程序通过gcc编译构建,其中不使用任何优化。将产生的二进制文件运行,可得到如下结果: 从中可以发现,寄存器变量rvar的值未受后面赋值的影响,仍为旧值222,与期望值不同,但是普通int型和volatile型值均正确。说明经过长跳转,寄存器变量在跳转之中重新赋值容易产生丢失的问题。 汇编角度观察 下图发现,在赋值的时候,rvar是直接放到了ESI寄存器中,而未覆盖掉之前内存中保存的222值,也就是888赋值到了寄存器,而内存中应该还为222,其余的777,999均进入内存中。 并且进入下个自定function函数时,三个变量均放入了寄存器中。进行传值。 下图可以看出来,就是jump回来时,rvar的真实值(寄存器中的值888)已经丢失,寄存器的值被jump buffer缓存中值所冲掉,后面在打印变量值时,从内存中读取到旧的值。 内存角度观察 上图是赋值完777,888,999,此时发现,这个888赋值给了寄存器(从汇编中可以看出),这里发现222未被覆盖。 最后通过jump返回,读取值,这时候读取是从内存中读取出来,发现读出了777,222,999,程序发生了意外情况。其中下图展示了内存地址中的值,222在-0x28 + 0x7fffffffe160地址位。 实例优化O2,release版本 程序运行结果 编译中加入O2编译器优化,并运行程序。此时结果发现,nvar和rvar的值均发生了变化,并未存入我们预想中的777和888,而是old值未被改变。 因为存在编译器的优化问题,变量nvar和rvar在跳转中,其改写值放入了寄存器中,jump之后,寄存器的值被冲刷,到致出现此类问题。而变量vvar的值放入了内存中,jump之后,仍可以通过寄存器指针调取。 下面就对程序运行过程进行检查和对结果进行分析。 汇编角度观察 通过objdump -d volatile_og可以查看编译后文件的反汇编代码。我们主要观察main函数,其从10c0开始,上图根据判断env是否等于0为界限,分为了3块,方便理解阅读。 发现汇编中不存在对函数Dojump的调用(callq指令后未出现Dojump),猜测是由于编译器优化为内联函数。同时此函数中变量nvar0,rvar0,vvar0的初始化为死代码块,在优化过程中也进行了移除。 下图可以说明,仅有使用关键字volatile的vvar其值再栈内存中可以找到,其余的变量均不为lvalue。 内存角度观察 可以通过查看jump前后的内存中的值,进行查看到底在jump中发生了什么: 下图一为在jump之前,寄存器中的值,只有333进入到内存中了。亦可以通过图二方式查询,发现rvar和nvar并非可以通过内存地址访问到。 在jump之后,内存e15c中的值改为999。 Jump之后,栈内存的空间如下图所示: 下图中,此时只有vvar可以取地址操作。 附录 参考资料 什么是内存屏障? Why Memory Barriers ? why-do-we-use-volatile-keyword intro.races-13 Linux 汇编语言开发指南 Intel 格式--AT&T 格式 setjmp()与longjmp()详细分析 利用C语言中的Setjmp和Longjmp,来实现异常捕获和协程 Exactly what “program state” does setjmp save? 可能涉及到的具体优化参数 l -fforce-mem:在做算术操作前,强制将内存数据copy到寄存器中以后再执行。这会使所有的内存引用潜在的共同表达式,进而产出更高效的代码,当没有共同的子表达式时,指令合并将排出个别的寄存器载入。这种优化对于只涉及单一指令的变量, 这样也许不会有很大的优化效果. 但是对于再很多指令(必须数学操作)中都涉及到的变量来说, 这会时很显著的优化, 因为和访问内存中的值相比 ,处理器访问寄存器中的值要快的多。 l -fregmove:编译器试图重新分配move指令或者其他类似操作数等简单指令的寄存器数目,以便最大化的捆绑寄存器的数目。这种优化尤其对双操作数指令的机器帮助较大。 l -fschedule-insns:编译器尝试重新排列指令,用以消除由于等待未准备好的数据而产生的延迟。这种优化将对慢浮点运算的机器以及需要load memory的指令的执行有所帮助,因为此时允许其他指令执行,直到load memory的指令完成,或浮点运算的指令再次需要cpu。其允许数据处理时先完成其他的指令。 总结: -fforce-mem有可能导致内存与寄存器之间的数据产生类似脏数据的不一致等。对于某些依赖内存操作顺序而进行的逻辑,需要做严格的处理后才能进行优化。例如,采用volatile关键字限制变量的操作方式,或者利用barrier迫使cpu严格按照指令序执行的。 内存屏障 Memory Barriers Cache 一致性问题的根源是因为存在多个处理器独占的 Cache,而不是多个处理器。它的限制条件比较多:多核,独占 Cache,Cache 写策略。 当其中任一个条件不满足时便不存在cache一致性问题。 针对CPU的多级Cache和存储读写一致性 : CPU中为提高指令执行,增加了两个缓冲区store buffer,invalidate queue。 Store Buffer: 好处:store是为了CPU0和1之间读写,不需要等待从另外一个CPU的Cache中调取数据。(提高速度)。 坏处(问题描述):CPU0修改值,但是其发送的“读使无效”晚于CPU1真正读的时间,导致晚了一步,数据错了。 冲突问题的解决: 硬件上:store forwarding。如果本地Store Buffer有数据,直接先读本队Store Buffer。 软件上:硬件设计者提供了memory barrier指令,让软件来告诉CPU这类关系。 失效队列: store buffer一般很小,所以CPU执行几个store操作就会填满, 这时候CPU必须等待invalidation ACK消息(得到invalidation ACK消息后会将storebuffer中的数据存储到cache中,然后将其从store buffer中移除),来释放store buffer缓冲区空间。 好处:CPU1可能在重负荷下,执行大量失效命令会有更重的复合。提高了速度; 坏处(问题描述):可能本身值已无效,但是队列未执行到。(又是晚了)。 解决:仍然是加屏障可以解决。 点击关注,第一时间了解华为云新鲜技术~

优秀的个人博客,低调大师

仅1年GitHub Star数翻倍,Flink 做了什么?

作者:王峰(莫问) Apache Flink 是公认的新一代开源大数据计算引擎,其流水线运行系统既可以执行批处理程序也可以执行流处理程序。目前,Flink 已成为 Apache 基金会和 GitHub 社区最为活跃的项目之一。在 Flink Forward Asia 2019 上,阿里巴巴资深技术专家,实时计算负责人王峰 (莫问)总结了 2019 年 Flink 在中国的发展和演进,阿里对 Flink 社区的贡献以及未来 Flink 的最新发展方向。 GitHub 地址: https://github.com/apache/flink 欢迎一起GitHub点Star~ Flink:最活跃 Apache 项目之一 首先,简单总结一下 Flink 社区的发展情况。自 2014 年 Flink 贡献给开源社区之后,其发展非常迅速。目前,Flink 可以称之为 Apache 基金会中最为活跃的项目之一,在 GitHub 上其访问量在 Apache 项目中位居前三。从 Star 数量上看,仅仅是 2019 年一年的时间,Flink 在 GitHub 上的 Star 数量就翻了一倍,Contributor 数量也呈现出持续增长的态势。通过相关数据可以看出,越来越多的企业和开发者正在不断地加入 Flink 社区,并为 Flink 的发展贡献力量。其中,中国开发者也做出了巨大的贡献。 Apache Flink 在中国的应用 随着 Flink 社区的快速发展,其技术也逐渐走向成熟。在 2019 年,国内已经有大量的本土互联网公司开始采用 Apache Flink 作为主流的实时计算解决方案。同时,在全球范围内,优步、网飞、微软和亚马逊等国际互联网公司也逐渐开始使用 Apache Flink。 Apache Flink 的未来 如今,Flink 的主要应用场景基本上还是数据分析,尤其是实时数据分析。Flink 本质上是一款流式数据处理引擎,覆盖的场景主要是实时数据分析、实时风控、实时 ETL 处理等。未来,社区希望 Flink 演化成为统一的数据引擎。 在离线数据处理方面,希望 Flink 能够在流数据处理的基础之上进一步实现批与流的统一,提供统一的数据处理和分析的解决方案。 另一方面,朝着在线数据分析处理的方向演进,即利用 Flink 的核心优势、Event-Driven Function 的能力以及 Flink 自带的状态管理等特性实现在线的函数计算。 近年来,AI 场景发展得如火如荼并且计算的规模也越来越大。因此,Flink 社区也希望能够主动拥抱 AI 场景,在 Flink 机器学习方面支持 AI 场景,甚至和 AI 原生的深度学习引擎比如 Flink + TensorFlow、Flink + PyTorch 等实现协同,提供大数据+AI 的全链路解决方案。 统一的数据分析解决方案 下图为 Apache Flink 批流一体的发展路线图。在 1.9 版本之前,Flink 的批和流还属于两条 Code Path,DataSet 和 DataStream 是两条独立的 API,具有两套不同的运行时环境,尚未实现批流一体的高度融合。所以在 2019 年发布的 Flink 1.9 版本和即将发布的 1.10 版本中,社区投入了大量精力去做 Flink 批流一体架构的整合。经过一年的努力,在 Flink 1.10 版本中已经实现了 Flink Task 的运行时环境、执行引擎层以及 SQL 和 Table 层面的批和流的高度统一。但是目前而言,Flink 在架构上还没有完全实现批流全部统一。未来,社区希望将 DataSet 和 DataStream 两套 API 做到批流高度融合。 统一 Flink SQL SQL 是在大数据处理中当之无愧的“王道”语言,同时也是最通用、最主流的语言。在 Flink 1.9 版本中发布了一部分统一的 SQL 功能,而未来在 1.10 版本中也会发布更多的新功能,比如采用了批流统一的 Query 处理器、支持完整的 DDL 功能。此外,Flink 还通过了 TPC-H 和 TPC-DS 的测试集验证,已达到生产级可用状态。Flink 1.10 版本还增强了对于 Python 的支持,目前 Flink SQL 能够非常方便地使用 Python UDF。除此之外,Flink 也积极地拥抱了 Hive 生态,使得 Flink SQL 能够兼容 Hive,这样用户能够以极低的成本尝试 Flink 的新技术。 统一 SQL 架构 下面将从技术层面分享 Flink Unified SQL 的架构是如何实现批流的融合,进而实现统一处理的。对于用户的一条 SQL 而言,无论是批处理还是流处理,可能读取数据的模式是相同的,只不过输出结果可能是一次性输出或者持续性输出。在 Flink 中,可以对于用户输入的 SQL 采用统一的处理器进行解析、编译、优化等动作,最终产生一个 Flink Job 提交到 Flink 集群中运行。 在查询处理的过程中,新版本的 Flink 增加了非常多的优化技术,比如执行计划策略的优化、执行算子的优化、二进制数据结构的优化、代码自动生成的优化以及 JVM 的优化等,使得 SQL 编译出来的 Job 执行效率更高。在 Runtime 方面,也对 Flink 执行引擎做了重构,对核心底层功能进行抽象,抽象出了可插拔的调度策略以及 Shuffle Service,这样一来 Runtime 非常灵活,能够自由适配流和批的 Job 模式,甚至能够实现同一 Job 中流算子和批算子的自由转换。 Flink 与 Hive 生态系统集成 让大家能够真正将 Flink SQL 用起来,不仅仅需要考虑优秀的内核技术或者完善的功能,也需要考虑到用户的迁移成本。最理想的情况就是让大家既能够享受到 Flink SQL 的新技术成果,同时又不用去修改已有的系统或者数据以及元数据等。因此,Flink SQL 在 2019 年的重大成果之一就是更好地对接了 Hive 生态。 在 Flink 1.10 版本中,批流一体的 SQL 将直接无缝对接 Hive 的 metastore,可以与 Hive 直接共享元数据,Flink Connector 能够直接读取 Hive 的分区表数据,并且不会产生任何影响。同时,Flink 还兼容 Hive 的 UDF,可以直接运行在 Hive 集群环境中,不需要定义额外的集群。整体的效果使得用户仅花费极低的成本就能够在 Hive SQL 和 Flink SQL 之间非常自由地实现切换。Flink SQL 的另外一个先天优势是可以支持流数据,也就是同一套业务逻辑在处理 Hive 数据的同时,也可以对接到 Kafka 等消息队列来处理实时数据。 TPC-DS Benchmark 测试效果 下图为 Flink 在 TPC-DS 的 Benchmark 测试的性能表现。这里的数据集规模为 10TB,数据格式为 Hive ORC,对比版本中,Hive 使用的是 3.0 版本,Flink 使用的 1.10 Pre-Release 版本。 结果表明,Flink 不仅能够跑通 99 个 TPC-DS 的查询,同时其性能还能够达到 Hive 的 7 倍。通过 Benchmark 就可以看到 Flink SQL 无论是在功能完善性、性能还是其他各个方面都已经达到了业界的高标准,达到了生产级可用。 Flink 拥抱 AI 2019 年,整个技术圈里最火的当属 AI 了。而 Flink 除了做数据处理之外,还希望能够更好地拥抱 AI 场景。2019 年,Flink 在 AI 方面首先铺垫了机器学习基础设施,这部分所做的第一件事情就是实现了 Flink ML Lib 的基础 API,称之为 ML Pipeline。 ML Pipeline 的核心是机器学习的流程,其中的核心概念包含 Transformer、Estimator、Model 等。Flink 机器学习算法的开发人员可以使用这套 API 去开发不同的 Transformer、Estimator、Model,去实现各种经典的机器学习算法,非常方便。基于 ML Pipeline 这套 API 还能够自由组合组件来构建机器学习的训练流程和预测流程。 对于 AI 算法的开发人员而言,他们最喜欢的往往并不是 SQL 而是 Python。因此,Flink 对于 Python 的支持也尤为重要。在 2019 年,Flink 社区也投入了大量的资源来完善 Flink 的 Python 生态,诞生了 PyFlink 项目。并且在 Flink 1.9 版本中实现了 Python 对于 Table API 的支持。但这是不够的,在 Flink 1.10 版本中还重点支持了 Python UDF 特性。为了实现这一目标一般有两种技术选择,一种是从无到有地实现从 Java 到 Python 的通信,另一种是直接使用成熟的框架。很幸运的是 Beam 社区在 Python 支持上非常强大,因此 Flink 社区与 Beam 社区之间开展了良好的合作,Flink 使用了 Beam 的 Python 资源,比如 SDK、Framework 以及数据通信格式等。在未来,Flink 会进一步完善对于 Python API 和 UDF 的支持,在 ML Pipeline 上更多地支持 Python,同时也希望引入更多成熟的 Python 库。 Alibaba Alink 众所周知,阿里巴巴在 2018 年重磅推出了 Blink,也就是阿里内部的 Flink 版本。而 Alink 则是阿里巴巴内部的基于 Flink 的机器学习算法库,由阿里云机器学习 PAI 团队开发。Alink 是一套分布式、批流一体的机器学习算法库,它既非常好地利用了 Flink 批流一体的计算能力以及在机器学习基础设施上的一些优势,还结合了阿里巴巴的业务场景。目前,Alink 的上百个机器学习算法也正在向 Flink 社区贡献,希望能够成为新一代的 Flink ML。为了尽快让大家享受到 Alink 的技术红利,阿里巴巴也决定同时开源 Alink 项目。 将 Alink 与主流的机器学习算法库进行对比,可以发现其最大的优势就是不仅能够支持批式训练的机器学习场景,也能够支持在线的机器学习场景。Alink 在离线的机器学习场景下与主流的 Spark ML 做了对比,在功能集合上所有算法基本一致,此外还做了性能对比,Alink 和 Spark ML 在离线训练场景下的性能基本在一个水平线上,旗鼓相当。但是 Alink 的优势在于一些算法能够以流式方法进行计算,更好地实现在线机器学习。 AI Flow 另外,AI 部分的新项目——AI Flow 也值得关注。AI Flow 是大数据及 AI 的处理流程平台,在 AI Flow 中定义不同数据之间的关系以及元数据格式等就能够非常方便地搭建一套大数据及 AI 处理的流程。整个 Workflow 并不绑定某一引擎或者平台,但是用户可以借助 Flink 批流一体的能力去搭建自己的大数据及 AI 解决方案。目前,AI Flow 项目正在准备中,预计将于明年的第一季度以与 Alink 相同的模式进行开源。 云原生 (Cloud Native) Flink 与 Kubernetes 生态系统集成 Flink 1.10 版本将会发布 Flink 与 Kubernetes 生态系统的集成功能,使得 Flink 能够原生地运行在 Kubernetes 管理平台之上。之所以要将 Flink 放在 Kubernetes 之上,是因为这样做有以下几点优势: 第一,Kubernetes 能够在多租户场景下为 Flink 带来更好的体验。 第二,目前各大公司都在逐步采用 Kubernetes 做 IT 设施的管理,如果 Flink 能够运行在 Kubernetes 之上,对于用户而言就能够实现更大规模的资源共享和统一管理,降低成本的同时能够提高效率。 第三,Kubernetes 云原生生态发展非常迅速,如果 Flink 能够与 Kubernetes 生态实现很好的整合,就能够让 Flink 享受到 Kubernetes 生态的技术红利,使得 Flink 能够在生产环境下提供运维保障。 阿里巴巴 Blink 贡献给 Apache Flink 社区 2019 年 3 月,Blink 正式开源。与此同时,阿里巴巴也希望将 Blink 的能力贡献回 Flink,共建一套 Flink 社区。而 Flink 通过 1.9 和即将发布的 1.10 两个大版本的迭代基本完成了这项工作。在这 10 个月的工作中,阿里巴巴向 Flink 社区贡献了超过一百万行代码,将 Blink 中积累的大量架构优化工作都推回给了 Flink 社区,不仅包括 Runtime、SQL、PyFlink,还包括新的 ML 等。 阿里云实时计算-Ververica Platform on Alibaba Cloud 在将 Blink 逐步贡献到 Flink 之后,阿里巴巴决定在 2020 年将两套内核逐渐合并为一套内核,将 Blink 内核合并到 Flink 内核中,全面支持开源社区的发展。未来,阿里云的产品和内部服务都会基于开源的 Flink 内核来实现。此外,阿里巴巴的技术团队和 Flink 创始团队 一起合作,联合打造了 Flink 企业版:Ververica Platform。这套全新的企业版将会支持阿里巴巴内部业务和云上业务。阿里巴巴也将投入更多力量到开源 Flink 的发展和社区的建设当中,也希望和广大业界同仁一起助力 Flink 中文社区的发展。 福利来了 2019 Flink Forward Asia 大会 37+ 演讲 PDF 合辑,不容错过! Flink Forward Asia 2019 在北京举行,2000 人次的开发者参与。我们收录了 5 大专场,38 篇大咖演讲资料的 FFA 2019 资料合辑,精彩内容一次性打包给你!

优秀的个人博客,低调大师

【拾贝】hive unoin all map数爆增

遇到个hive语句用unoinall暴增的情况, 特征: 1.两条语句查询的数据实际都是0 2.unoinall上下有同样的表 查看打印信息做了mapjoin,估计是mapjoin的一个bug,尝试加上条件 sethive.auto.convert.join.noconditionaltask=false; sethive.optimize.mapjoin.mapreduce=false;--这条貌似可以不加 恢复正常。 本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/yjplxq/1358934,如需转载请自行联系原作者

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册