Google 的 Git v2 带来颠覆性性能提升?恐怕未必

作者简介

王振威,CODING 创始团队成员之一,多年系统软件开发经验,擅长 Linux,Golang,Java,Ruby,Docker 等技术领域,近两年来一直在 CODING 从事系统架构和运维工作

前言

最近 Google 发布了一篇文章,描述了对 Git 的一个传输协议的更新,引起了国内技术圈的不小规模的轰动(相关文章请自行百度“Git v2 性能提升”)。 很多技术圈的朋友也在转载这个新闻,那至于性能改进有多大,里面的细节是什么呢?事实上这次改动只在极端情况下有性能提升,绝大多数情况下,用户感受不到性能的提升。很多不明所以的转发大概是因为 Google 的品牌效应吧 :)

Git 是什么?

为了讲清楚 why,我们先来简单介绍一下 Git 相关的协议。如果你还不了解 Git,想了解更多内容,可参考其官方网站:http://git-scm.com/ . 也可来 https://coding.net/help/doc/git 这里了解如何在国内使用优质快速的 Git 托管服务。

Git 传输协议

Git 常见的有三种协议,SSH,HTTP(S),Git,使用最广泛的是前两种。

让我们来看一下, HTTP(S) 和 SSH 协议的使用示例

git clone https://git.coding.net/wzw/coding-demo.git

Cloning into 'coding-demo'...

remote: Counting objects: 3, done.

remote: Total 3 (delta 0), reused 0 (delta 0)

Unpacking objects: 100% (3/3), done.

git clone git@git.coding.net:wzw/coding-demo.git

Cloning into 'coding-demo'...

remote: Counting objects: 3, done.

remote: Total 3 (delta 0), reused 0 (delta 0)

Receiving objects: 100% (3/3), done.

可以看到,对于全新 clone 来讲两者基本上的过程是一模一样的。

事实上, Git 底层对于各种应用层协议的底层处理是一致的,不管是 HTTP(S) 还是 SSH 还是 Git 协议。

让我们来进一步看一下, Git 在传输过程中都做了什么。

GIT_TRACE=1 GIT_TRACE_PACKET=1 git clone https://git.coding.net/wzw/coding-demo.git

17:48:21.767799 git.c:344               trace: built-in: git 'clone' 'https://git.coding.net/wzw/coding-demo.git'

Cloning into 'coding-demo'...

17:48:21.797959 run-command.c:626       trace: run_command: 'git-remote-https' 'origin' 'https://git.coding.net/wzw/coding-demo.git'

17:48:22.278880 pkt-line.c:80           packet:          git< # service=git-upload-pack

17:48:22.279390 pkt-line.c:80           packet:          git< 0000

17:48:22.279405 pkt-line.c:80           packet:          git< fdacba1d541c75bd48f2cd742ee18f77ea3517a1 HEAD\0multi_ack thin-pack side-band side-band-64k ofs-delta shallow deepen-since deepen-not deepen-relative no-progress include-tag multi_ack_detailed no-done symref=HEAD:refs/heads/master agent=git/2.15.0

17:48:22.279419 pkt-line.c:80           packet:          git< fdacba1d541c75bd48f2cd742ee18f77ea3517a1 refs/heads/master

17:48:22.279431 pkt-line.c:80           packet:  

好,基础知识补充完毕,有没有发现火爆的区块链在技术层面上跟 Git 的存储是有相似之处的 :)

在 Clone 过程中,服务器端首先会推荐给客户端一些 ref 列表,这也是 Git v2 协议号称的性能改进的地方,后文有解释。

像这样:

17:49:19.772436 pkt-line.c:80           packet:        clone< fdacba1d541c75bd48f2cd742ee18f77ea3517a1 refs/heads/master

17:49:19.772527 pkt-line.c:80           packet:        clone< 1536ad10fc0a188c50680932ca191c8da46938c4 refs/heads/test-abc

17:49:19.772549 pkt-line.c:80           packet:        clone< 1536ad10fc0a188c50680932ca191c8da46938c4 refs/heads/test-bcd

17:49:19.772566 pkt-line.c:80           packet:        clone< 30eb4b0d813c662c4d7e87c4d3b4cf561e544f8e refs/tags/v1.0

17:49:19.772863 pkt-line.c:80           packet:        clone< 1536ad10fc0a188c50680932ca191c8da46938c4 refs/tags/v1.0^{}

很显然,上文中的 40 位16进制数字就是对应后面的 ref 指向的对象 ID。

而客户端,只需要依据自己感兴趣的 ref 和自己本地已经存在的对象库(对于 pull 和 fetch 来讲,本地有对象库,对于 clone 来讲本地还没有对象库,那么他就是需要所有的感兴趣的对象)。

在客户端计算完毕自己感兴趣的对象列表后,会用 want 指令告诉远端服务器。

17:49:19.776185 pkt-line.c:80           packet:        clone> want fdacba1d541c75bd48f2cd742ee18f77ea3517a1 multi_ack_detailed side-band-64k thin-pack ofs-delta deepen-since deepen-not agent=git/2.15.1.(Apple.Git-101)

17:49:19.776215 pkt-line.c:80           packet:        clone> want fdacba1d541c75bd48f2cd742ee18f77ea3517a1

17:49:19.776224 pkt-line.c:80           packet:        clone> want 1536ad10fc0a188c50680932ca191c8da46938c4

17:49:19.776232 pkt-line.c:80           packet:        clone> want 1536ad10fc0a188c50680932ca191c8da46938c4

17:49:19.776239 pkt-line.c:80           packet:        clone> want 30eb4b0d813c662c4d7e87c4d3b4cf561e544f8e

如果客户端执行的是 pull 或者 fetch ,他还会告诉远端自己已经有了什么对象(在文章的后面,我们会补充一段专门说明此点)。

远端服务器会根据客户端想要的对象以及客户端已经有的对象并对比自身的对象库和对象依赖关系,将客户端必须的对象整理起来并打包压缩传给客户端。

客户端收到对象包后,解包并校验对象,并更新引用的对应指向。

Google 在 Protocol version 2 做了什么

完整的 version 2 的协议说明在这里: https://www.kernel.org/pub/software/scm/git/docs/technical/protocol-v2.html

这里我们对其做的主要改动做些说明,主要有三点:

服务端引用过滤

新特性的易扩展性升级(例如可声明想要什么 ref)

简化的客户端 HTTP 协议处理

被很多标题党夸大其词的主要是其第一点:服务端引用过滤。

Google 官方的博客中对此段的描述是这样的:

The main motivation for the new protocol was to enable server sid

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Python3:sqlalchemy对mysql数据库操作,非sql语句

Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''