Antlr4学习笔记

背景

在阅读shardingjdbc-4.1.1代码时,发现一段sql解析的逻辑,好奇它的实现,查阅相关资料发现解析引擎基于Antlr4实现,便有了此文

官方文档中也描述了解析引擎的迭代过程

SQL解析作为分库分表类产品的核心,其性能和兼容性是最重要的衡量指标。 ShardingSphere的SQL解析器经历了3代产品的更新迭代。


第一代SQL解析器为了追求性能与快速实现,在1.4.x之前的版本使用Druid作为SQL解析器。经实际测试,它的性能远超其它解析器。
第二代SQL解析器从1.5.x版本开始,ShardingSphere采用完全自研的SQL解析引擎。 由于目的不同,ShardingSphere并不需要将SQL转为一颗完全的抽象语法树,也无需通过访问器模式进行二次遍历。它采用对SQL半理解的方式,仅提炼数据分片需要关注的上下文,因此SQL解析的性能和兼容性得到了进一步的提高。
第三代SQL解析器则从3.0.x版本开始,ShardingSphere尝试使用ANTLR作为SQL解析的引擎,并计划根据DDL -> TCL -> DAL –> DCL -> DML –>DQL这个顺序,依次替换原有的解析引擎,目前仍处于替换迭代中。 使用ANTLR的原因是希望ShardingSphere的解析引擎能够更好的对SQL进行兼容。对于复杂的表达式、递归、子查询等语句,虽然ShardingSphere的分片核心并不关注,但是会影响对于SQL理解的友好度。 经过实例测试,ANTLR解析SQL的性能比自研的SQL解析引擎慢3-10倍左右。为了弥补这一差距,ShardingSphere将使用PreparedStatement的SQL解析的语法树放入缓存。 因此建议采用PreparedStatement这种SQL预编译的方式提升性能。–----摘自官网


由此可见,采用Antlr4更好地兼容sql,方便解析引擎对sql的理解,而Antlr4的产物,便是抽象语法树(AST,Abstract Syntax Tree),下面介绍相关概念

相关概念

名词解释备注

AST

抽象语法树(AST,Abstract Syntax Tree)是一种用于表示编程语言代码结构的树状数据结构。它将源代码解析为树状的层次结构,每个节点表示代码中的一个语法元素,例如变量、操作符、语句等,通过遍历和操作AST树,程序可以更轻松地理解和操纵源代码
  1. 树状结构:AST是一个树形结构,由多个节点组成,每个节点代表源代码中的一个语法元素

  2. 抽象性:抽象出了代码的结构和语法,去除了空白字符和不影响语法结构的细节

  3. 层次化:节点之间存在层次关系,父节点表示较高级的语法结构,子节点表示较低级的语法结构,如表达式中的操作符和操作数

  4. 语法表达:节点的类型和属性反映了源代码的语法结构,例如,变量声明节点会包含变量名和数据类型等属性

  5. 用途广泛:在编译器、解释器和代码分析工具中广泛用于分析和转换源代码,以便进行语法分析、优化、静态分析和代码生成等任务

ANTLR

ANTLR (ANother Tool for Language Recognition) 是一个用于生成语法分析器和编译器的强大工具。ANTLR 4 是ANTLR的第四个版本,它提供了许多功能,使得创建和维护语法分析器更加简单
  1. 语法描述: 编写自定义的语法描述文件,通常使用ANTLR的语法规则来定义编程语言、数据格式、配置文件等各种领域特定语言(DSL)的语法。ANTLR支持上下文无关语法(CFG)规则,但也可以处理上下文相关语法

  2. 多语言支持: 生成的ANTLR解析器可以用多种编程语言实现,包括Java、C#、Python和JavaScript等。这意味着你可以使用你熟悉的编程语言来构建解析器

  3. 生成AST: 能够轻松生成抽象语法树(AST),使得在编译器、解释器和代码分析中更容易操作和理解源代码

  4. 词法分析和语法分析: 包括对词法分析和语法分析的支持,从源代码中提取标记(tokens)和解析语法变得非常容易

  5. 监听器和访问者模式: ANTLR 4生成的解析器允许使用监听器和访问者模式来处理语法树中的节点,在树遍历期间执行特定的操作非常方便

  6. 错误处理: ANTLR 4提供了强大的错误处理机制,可以生成有用的错误消息,并允许在遇到错误时执行特定的操作。

  7. 强大的工具集成: ANTLR 4可以与各种开发工具和IDE集成,帮助开发和调试语法分析器

LL(*)

一种语法分析方法,它是基于LL(左到右,从左到右的扫描)语法分析的扩展。LL(*)语法分析器允许更灵活地处理上下文敏感语法,而不受传统LL(k)语法分析器中固定向前看符号数限制的约束
  1. 无固定向前看符号数限制:传统的LL(k)语法分析器在每一步都需要预测接下来的k个符号,而LL(*)不受此限制。LL(*)语法分析器根据需要使用不同数量的向前看符号来解决不同的语法冲突

  2. 上下文敏感性:语法分析器可以更好地处理上下文敏感的语法,因为它可以灵活地调整向前看符号的数量,以更好地理解当前的语法上下文

  3. 自动构建分析表:语法分析器通常会自动构建分析表,以便根据输入文本的实际需求来选择向前看符号,而不需要手工指定向前看符号的数量

  4. 递归下降分析器通常与递归下降语法分析器结合使用,因为递归下降语法分析器易于实现和理解,并且与LL(*)相互兼容

  5. 语法冲突解决:语法分析器通过回溯和基于输入文本的反馈来解决语法冲突,这使得它能够动态地选择正确的产生式规则

二义性

是语法分析和语言处理中的一个概念,指的是在给定的语法规则下,一个输入字符串可以有多种不同的解释或分析方式

意味着语法规则无法唯一确定输入字符串的语法结构,即存在多个可能的分析树或解析路径

java的二义性如两个不同接口名,方法A一致,实现类调用A时就有歧义

再比如sql中select user from user group by user,里面的user表达也有歧义

Lexer词法分析器,负责将源代码文本分解成词法单元(token),词法单元通常是编程语言中的最小语法单元,如关键字、标识符、操作符、常量等Lexer会扫描源代码字符流,识别和标记出各个词法单元,通常使用正则表达式或有限状态机等技术来实现。
词法分析器将生成的词法单元传递给解析器(Parser),供后者进行语法分析
Parser语法分析器负责将词法单元构建成抽象语法树(AST),这是一种树状结构,用于表示源代码的语法结构
  1. Parser根据编程语言的语法规则,将词法单元组合成更高级的结构,如语句、表达式等
  2. 如果遇到语法错误,Parser通常会生成错误消息,或者尝试恢复到一个合法的语法状态
  3. 解析器将生成的抽象语法树传递给后续的语义分析和代码生成阶段
Visitor

访问者模式,主动遍历,推荐

  1. 可以显示定义遍历语法树的顺序
  2. 不需要与antlr遍历类ParseTreeWalker一起使用,直接对tree操作
  3. 动作代码与文法产生式解耦,利于文法产生式的重用
  4. visitor方法可以直接返回值,返回值的类型必须一致,不需要使用map这种节点间传值方式,效率高
Listener观察者模式,通过节点监听,触发处理方法
  1. 不需要显示定义遍历语法树的顺序,实现简单
  2. 缺点,不能显示控制遍历语法树的顺序
  3. 动作代码与文法产生式解耦,利于文法产生式的重用
  4. 没有返回值,需要使用map、栈等结构在节点间传值

对以上名词有一定了解之后,下面说说antlr4生成AST的流程

流程说明

整体流程主要分为两个部分,词法分析

  • 词法分析----根据lexer-rule对输入进行拆分,形成token字符 

将字符聚集为单词或者符号(词法符号,token)的过程称为词法分析(lexical analysis)或者词法符号化(tokenizing)。

我们把可以将输入文本转换为词法符号的程序称为词法分析器(lexer)。

词法分析器可以将相关的词法符号归类,例如INT(整数)、ID(标识符)、FLOAT(浮点数)等。当语法分析器不关心单个符号,而仅关心符号的类型时,词法分析器就需要将词汇符号归类

词法符号包含至少两部分信息:词法符号的类型(从而能够通过类型来识别词法结构)和该词法符号对应的文本。--Antlr4权威指南-译本


  • 语法解析----根据parser-rule对拆分后的token进行解析,形成AST树

第二个阶段是实际的语法分析过程,在这个过程中,输入的词法符号被"消费"以识别语句结构,在上例中即为赋值语句。

默认情况下,ANTLR生成的语法分析器会建造一种名为语法分析树parse tree或者句法树syntax tree的数据结构,该数据结构记录了语法分析器识别出输入语句结构的过程,以及该结构的各组成部分。--Antlr4权威指南-译本


解析流程示例,一个表达式经词法分析后,形成单词或符号,而后通过parser流程形成抽象树

生成AST后,可以对AST进行遍历,在Antlr4提供的访问器或监听器上做对应的逻辑处理

入门示例

在本节中会实现一个支持简易的计算器,支持负数、小数的四则运算

我们定义\n是一个表达式的终止,并允许用前面的结果作为变量用于后面的计算

输入

a=3+2-1.1\nb=a*-2.2\n

输出

8.58

在开始前需要先做一些准备工作

环境准备

  • 下载idea plugins
  • maven工程,引入依赖(antlr4-runtime)&插件(antlr4-maven-plugin)
<dependencies>
    <dependency>
        <groupId>org.antlr</groupId>
        <artifactId>antlr4-runtime</artifactId>
        <version>4.13.1</version>
    </dependency>
</dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.antlr</groupId>
                <artifactId>antlr4-maven-plugin</artifactId>
                <version>4.13.1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>antlr4</goal>
                        </goals>
                        <phase>none</phase>
                    </execution>
                </executions>
                <configuration>
                    <outputDirectory>src/main/java</outputDirectory>
                    <!--<listener>true</listener>-->
                    <visitor>true</visitor>
                    <!--<treatWarningsAsErrors>true</treatWarningsAsErrors>-->
                </configuration>
            </plugin>
        </plugins>
    </build>

开发

首先定义语法文件

grammar Expr;
/* 起始规则,语法分析的起点 */
prog: stat+;
stat: expr NEWLINE # printExpr
    | ID '=' expr NEWLINE # assign
    | NEWLINE # blank
    ;
expr: expr op=('*'|'/') expr # MulDiv
    | expr op=('+'|'-') expr # AddSub
    | NUMBER # number
    | '-' NUMBER # negative
    | ID #id
    | '(' expr ')' #parens
    ;
NUMBER : DECIMAL|INT; //数字
fragment DECIMAL : INT '.' INT; //匹配小数
ID:  [a-zA-Z]+;     // 匹配标识符
fragment INT: [0-9]+;        // 匹配整数
NEWLINE: 'r'? '\n'; // 告诉语法分析器一个新行的开始(即语句终止标志)
WS:  [\t]+ -> skip; // 丢弃空白字符
MUL:  '*';
DIV:  '/';
ADD:  '+';
SUB:  '-';

通过插件的preview功能,观察AST树如下

通过插件生成语法文件对应的代码

可以看到生成了监听者&访问者模式,用于响应节点遍历事件,或直接用来遍历AST树

这里继承访问者,实现计算的逻辑,生成的方法在上面语法文件都有标识

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

public class ExprCalVisitor extends ExprBaseVisitor<BigDecimal>{
    Map<String, BigDecimal> memory = new HashMap<String, BigDecimal>();

    @Override
    public BigDecimal visitId(ExprParser.IdContext ctx) {
        String id = ctx.ID().getText();
        if (memory.containsKey(id))
            return memory.get(id);
        return BigDecimal.ZERO;
    }

    /**
     * expr newline
     * @param ctx the parse tree
     * @return
     */
    @Override
    public BigDecimal visitPrintExpr(ExprParser.PrintExprContext ctx) {
        BigDecimal value = visit(ctx.expr());
        System.out.println(value);
        return BigDecimal.ZERO;
    }

    /* ID '=' expr NEWLINE */
    @Override
    public BigDecimal visitAssign(ExprParser.AssignContext ctx) {
        String id = ctx.ID().getText();
        BigDecimal value = visit(ctx.expr());
        memory.put(id, value);
        return value;
    }

    /* expr op=('*'|'/') expr */
    @Override
    public BigDecimal visitMulDiv(ExprParser.MulDivContext ctx) {
        BigDecimal left = visit(ctx.expr(0));
        BigDecimal right = visit(ctx.expr(1));
        if (ctx.op.getType() == ExprLexer.MUL)
            return left.multiply( right);
        return left .divide(right,4,BigDecimal.ROUND_HALF_UP);
    }

    /* expr op=('+'|'-') expr */
    @Override
    public BigDecimal visitAddSub(ExprParser.AddSubContext ctx) {
        BigDecimal left = visit(ctx.expr(0));
        BigDecimal right = visit(ctx.expr(1));
        if(ctx.op.getType()==ExprLexer.ADD){
            return left.add(right);
        }
        return left.subtract(right);
    }

    @Override
    public BigDecimal visitNumber(ExprParser.NumberContext ctx) {
        String text = ctx.getText();
        return new BigDecimal(text);
    }

    @Override
    public BigDecimal visitParens(ExprParser.ParensContext ctx) {
        return visit(ctx.expr());
    }

    @Override
    public BigDecimal visitNegative(ExprParser.NegativeContext ctx) {
        return new BigDecimal(ctx.getText());
    }
}

执行测试代码

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CodePointCharStream;
import org.antlr.v4.runtime.CommonTokenStream;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

public class ExprDemo {

    public static void main(String[] args) {
        List<String> testSet = Arrays.asList(
                "a=1+2\nb=a*3\n",
                "res=1+2\n",
                "res=(1+0.01)*2.3*100/(15-5)\n",
                "a=-1*3-4\nb=-2*a\n"
        );
        ExprCalVisitor visitor = new ExprCalVisitor();
        for (int i = 0; i < testSet.size(); i++) {
            // 构建字符流
            CodePointCharStream charStream = CharStreams.fromString(testSet.get(i));
            // 从字符流分析词法, 解析为token
            ExprLexer lexer = new ExprLexer(charStream);
            // 从token进行分析
            ExprParser parser = new ExprParser(new CommonTokenStream(lexer));
            // 使用监听器,遍历语法树,根据语法定义,prog为语法树的根节点
            ExprParser.ProgContext prog = parser.prog();
            // 使用visitor,生成自定义的对象
            BigDecimal res = visitor.visit(prog);
            System.out.println(res);
        }
    }

}

结果如下

自此,已实现简易计算器的功能,下面简单聊聊语法规则

语法规则

常用的语法要点

  • 规则表示,以`:`开始,`;`结束, 多规则以`|`分隔
  • 符号(Token)名以大写开头
  • skip操作是一条指令,告诉词法分析器匹配并丢弃空白字符
  • channel(HIDDEN)也是一个词法分析器指令。设置词法符号的通道号,后续会被语法分析器忽略(与skip作用类似)
  • 解析规则小写开头,可跟字母,数字,下划线
  • 使用#来标记ANTLR语法文件,为获取更加精确的监听器事件,ANTLR允许用#运算符为任意规则的最外层备选分支提供标签。利用这种方法,在Expr语法的基础上,增加标签。
  • fragment表示片段规则,定义的规则可以给其他语法文件复用
  • 子规则可用符号标记在语法片段出现的次数
    • 可选(?)
    • 出现0次或多次(*)
    • 至少一次(+)
设计语法

在词法层面上,不同编程语言也倾向于实用相同的结构,例如标识符、整数、字符串等等。对单词顺序和单词间依赖关系的限制来源于自然语言,逐渐发展为以下四种抽象的计算机语言模式:

  • 序列-既一列元素,例如一个数组初始化语句中的值
  • 选择-在多种可选方案中做出选择,例如编程语言中的不同种类的语句
  • 词法符号依赖-一个词法符号需要和某种的另外一个词法符号匹配,例如左右括号匹配
  • 嵌套结构-一种自相似的语言结构,例如编程语言中的嵌套算术表达式或者嵌套语句块。

为实现以上模式,语法规则只要可选方案、词法符号引用和规则引用即可Backus-Naur-Format,BNF。为方便起见,还是将这些元素划分为子规则,与正则表达式类似,子规则是用括号()包围的内联规则。可以用以下符号标记子规则,用于指明其中的语法片段出现的次数:可选(?)出现0次或多次(*)至少一次(+);(扩展巴克斯-诺尔范式,Extended Backus-Naur Format)。----摘自Antlr4权威指南-译本


序列模式

按顺序列出各项元素,变体包括带终止符&分割符的序列模式

grammar serial;

file : (row '\n')*;       // 以一个'\n'作为终止符的序列
row : field (',' field)*; // 以一个','作为分隔符的序列
field : INT;              // 假设字段都是整数

INT:[0-9]+;

选择模式

用`|` 符号表示规则分支,类似于switch case的表达,与前面简易计算器语法里对应的分支逻辑类似

expr: expr op=('*'|'/') expr //分支1
    | expr op=('+'|'-') expr //分支2
    | NUMBER # number //分支3
词法符号依赖

如果在某个语句中看到了某个符号,就必须在同一个语句中找到和它配对的那个符号

如下面的parens所示

expr: expr op=('*'|'/') expr # MulDiv
    | expr op=('+'|'-') expr # AddSub
    | '(' expr ')' #parens
嵌套模式

表达式是一种典型的自相似结构,它包含多个嵌套的、以运算符分隔的子表达式

如下所示,这个是嵌套结构,fomula里是expr,而expr又可以有多个选择分支

grammar recursion;
import Expr;
expr : expr '=' expr
    | fomula
    | NUMBER
    | fomula (OP fomula)*
    ;
fomula:ID* '(' expr ')' ;

ID:[a-zA-Z]+;
NUMBER:INT|DECIMAL;
OP:'*'|'+'|'-'|'/';

另外这里用了import,可以看到之前定义的fragment片段规则也可以在此处使用

以上是大概的语法规则介绍,详细可以阅读后面参考资料的内容

总结

回到一开始的问题,shardingjdbc是如何解析sql?

通过翻阅代码,入口---org.apache.shardingsphere.sql.parser.SQLParserEngine#parse

可以看出解析流程(基于4.1.1版本)如下

可以看出antlr4在解析sql的功能中扮演举足轻重的角色,了解他的实现和语法规则能更好地理解shardingjdbc解析sql的实现


注:shardingsphere源码环境如果编译失败,可以执行以下命令生成parser类,参考link

./mvnw -Dcheckstyle.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true -Djacoco.skip=true -DskipITs -DskipTests install -T1C


参考资料

  • Antlr4权威指南-译本
  • Antlr4官网git介绍
  • Antlr4语法文件

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VSCode 如何设置背景图片

VSCode 设置背景图片 1.打开应用商店&#xff0c;搜索 background &#xff0c;选择第一个&#xff0c;点击安装。 2. 安装完成后点击设置&#xff0c;点击扩展设置。 3.点击在 settings.json 中编辑。 4.将原代码注释后&#xff0c;加入以下代码。 // { // "workben…

第4章_运算符

文章目录 1. 算术运算符1.1 加法与减法运算符1.2 乘法与除法运算符1.3 求模运算符 2. 比较运算符2.1 等号运算符2.2 安全等于运算符2.3 不等于运算符2.4 空运算符2.5 非空运算符2.6 最小值运算符2.7 最大值运算符2.8 BETWEEN AND运算符2.9 IN运算符2.10 NOT IN运算符2.11 LIKE运…

Mysql用sql查询数字四舍五入小数点后两位并且第二位如果没有数用0填补

表中数据小数点后几位好长&#xff0c;直接上图 核心sql REPLACE(FORMAT(ROUND(d2.jiner, 2), 2), ,, ) ROUND函数处理数字四舍五入 FORMAT处理小数点后面必须跟进两位&#xff0c;也就是第二位没数字的话用0填补 REPLACE处理将逗号全部去除&#xff0c;因为FORMAT会导致数字…

苹果相机怎么磨皮 苹果手机怎么磨皮

相信使用苹果相机的小伙伴都有这样的疑惑&#xff0c;苹果相机怎么磨皮&#xff1f;其实可以通过相机的参数进行设置从而达到磨皮的效果&#xff0c;如果觉得相机自带的设置磨皮效果不够好&#xff0c;可以下载磨皮软件来对照片磨皮。今天的文章就来给大家介绍苹果相机怎么磨皮…

【嵌入式项目应用】__cJSON基础介绍与代码测试

目录 前言 一、JSON是什么&#xff1f; 1. JSON 基本语法 2. JSON值(value)的类型 3. 逻辑值&#xff08;true 或 false&#xff09; 4. null 5. NUMBER 数字&#xff08;整数或浮点数&#xff09; 6. STRING 字符串&#xff08;在双引号""中&#xff09; 7…

在NestJS应用程序中使用 Unleash 实现功能切换的指南

前言 近年来&#xff0c;软件开发行业迅速发展&#xff0c;功能开关&#xff08;Feature Toggle&#xff09;成为了一种常见的开发实践。通过功能开关&#xff0c;可以在运行时动态地启用或禁用应用程序的特定功能&#xff0c;以提供更灵活的软件交付和配置管理。对于使用 Nes…

手把手教你使用Vue2.0实现动态路由展示

文章目录 VUE2相关组件版本原始菜单数据数据库数据树形数据 前端项目配置静态路由配置路由守卫左侧路由回显代码 使用Vue2实现动态路由展示 思路&#xff1a; 后端返回树形数据根据数据渲染左侧菜单根据数据组装路由数据 注意&#xff1a;本文主要目的讲解是一种思路&#xff0…

阿里云推出AI编程工具“通义灵码“;生成式 AI 入门教程 2

&#x1f989; AI新闻 &#x1f680; 阿里云推出AI编程工具"通义灵码"&#xff0c;支持多种语言及实时续写功能 摘要&#xff1a;阿里云推出了一款名为"通义灵码"的AI编程工具&#xff0c;支持多种主流编程语言&#xff0c;包括Java、Python、Go等。该工…

找到数组中出现一种/两种奇数——异或运算

找到数组中出现一种/两种奇数 题目&#xff1a;一个数组有一种数出现了奇数次&#xff0c;其他数都出现了偶数次&#xff0c;怎么找到并打印这个数&#xff1f; trick 因为异或运算有个特点&#xff0c;满足交换律和结合律&#xff0c;同时有两个重要的特点&#xff1a; n^n…

Xray+awvs联动扫描

首先xray开启监听 xray_windows_amd64.exe webscan --listen 127.0.0.1:7777 --html-output xray-xxx.html --plugins sqldet,xxe,upload,brute-force,cmd-injection,struts,thinkphp 然后准备目标csv文件,每行一个url或ip然后加个逗号 接着awvs导入csv 对导进来的每个目…

沉痛悼念科研分公司

今天上班途中&#xff0c;遇到了上家公司的同事王强。他正准备去体检中心体检。几句寒暄之后&#xff0c;得知他是要入职选煤公司了。 我们所在的公司比较大&#xff0c;总公司下设有几十个分、子公司&#xff0c;我和他曾经在一家子公司——科研分公司。现在的科研分公司解散…

FIFO 位宽转换

从8位转32位 module tb_fifo();reg clk,rst; initial beginclk0;forever #4.545 clk~clk; end initial beginrst1;#9.09 rst0; endreg [31:0] cnts; always (posedge clk or posedge rst) beginif(rst)begincnts < 32d0;endelsebegincnts < cnts 1b1;end endreg […

中国电子云-隐私计算-云原生安全可信计算,物理-硬件-系统-云产品-云平台,数据安全防护

目录 联邦学习的架构思想 中国电子云-隐私计算-云原生安全 可信计算&#xff0c;物理-硬件-系统-云产品-云平台&#xff0c;数据安全防护 全栈国产信创的意义 1. 提升科技创新能力 2. 推动经济发展 3. 加强信息安全与自主可控 全栈国产信创的重要领域 1. 人工智能 2.…

硬件加速器及其深度神经网络模型的性能指标理解

前言&#xff1a; 现如今&#xff0c;深度神经网络模型和硬件加速器&#xff0c;如GPU、TPU等的关系可谓是“不分彼此”&#xff0c;随着模型参数的增加&#xff0c;硬件加速器成为了训练、推理深度神经网络不可或缺的一个工具&#xff0c;而近年来硬件加速器的发展也得益于加速…

AlphaFold更新了!AlphaFold-latest

AlphaFold又有重大更新了&#xff01;AlphaFold-latest来了&#xff01; &#x1f508;&#xff1a;号外号外&#xff01;Google DeepMind联合Isomorphic Labs在2023年10月31日发布了新一代的AlphaFold&#xff08;AlphaFold-latest&#xff09;。 AlphaFold-latest显着提高了…

论文阅读 - Detecting Social Bot on the Fly using Contrastive Learning

目录 摘要&#xff1a; 引言 3 问题定义 4 CBD 4.1 框架概述 4.2 Model Learning 4.2.1 通过 GCL 进行模型预训练 4.2.2 通过一致性损失进行模型微调 4.3 在线检测 5 实验 5.1 实验设置 5.2 性能比较 5.5 少量检测研究 6 结论 https://dl.acm.org/doi/pdf/10.1145/358…

Qt信号槽

目录 1、信号的定义 2、槽定义 3、信号和槽连接 4、信号与槽断开连接 5、伪代码展示 6、注意 Qt中的信号&#xff08;signals&#xff09;和槽&#xff08;slots&#xff09;是一种用于实现对象间通信的机制&#xff0c;广泛用于Qt应用程序中&#xff0c;特别是在图形用户…

【华为】路由器以PPPoE拨号接入广域网

组网需求 用户希望以PPPoE拨号方式接入广域网&#xff0c;如图1所示&#xff0c;Router作为PPPoE客户端&#xff0c;得到PPPoE服务器的认证后获得IP地址&#xff0c;实现用户接入互联网的需求。内网网关地址&#xff08;即VLANIF1接口的IP地址&#xff09;为10.137.32.1/24。 …

资源限流 + 本地分布式多重锁——高并发性能挡板,隔绝无效流量请求

前言 在高并发分布式下&#xff0c;我们往往采用分布式锁去维护一个同步互斥的业务需求&#xff0c;但是大家细想一下&#xff0c;在一些高TPS的业务场景下&#xff0c;让这些请求全部卡在获取分布式锁&#xff0c;这会造成什么问题&#xff1f; 瞬时高并发压垮系统 众所周知…

Go Metrics SDK Tag 校验性能优化实践

背景 Metrics SDK 是与字节内场时序数据库 ByteTSD 配套的用户指标打点 SDK&#xff0c;在字节内数十万服务中集成&#xff0c;应用广泛&#xff0c;因此 SDK 的性能优化是个重要和持续性的话题。本文主要以 Go Metrics SDK 为例&#xff0c;讲述对打点 API 的 hot-path 优化的…