每月 5 美元的虚拟机可以跻身 1993 年的超算前三

当然,如果你真的关注性能,市面上自然有更出色的选择。

今年是 TOP500 公开排名全球最快超级计算机 30 周年。

为纪念这个重要的里程碑,也因应科罗拉多州正在举行的年度超级计算大会,我们想弄个有趣但稍显愚蠢的实验:看看以今天技术,我们能以多低的成本重现 1993 年超级计算机十强的性能。于是,我们在云上运行了几台虚拟机,并对 HPLinpack 基准进行了编译测试。这里简单透露一下:我们这项实验的结果,你可能并不会太震惊。

到 1993 年年末,最快的超级计算机是日本国家航空实验室的富士通数值风洞。这台装备了 140 个 CPU 核心的系统,能够实现 124 GigaFLOPS 的双精度(FP64)计算能力。

如今,我们的系统已经 突破 了 exaFLOPS 的难关,然而在 1993 年 11 月,如何在功率最高的十个系统中占据一席之地呢?只要你的 FP64 性能超过了美国 CM-5/544 机型的 15.1 GigaFLOPS。因此,我们设定的目标是让云虚拟机超过 15 GigaFLOPS 的性能。

在我们分析结果之前,有几点值得一提。如果我们选用了支持 GPU 的实例,我们知道我们能够达到更高的性能。不过,云端的 GPU 实例租赁并不便宜,并且在 2000 年年中至年底,GPU 才真正开始广泛出现在 TOP500 的超级计算机中。此外,在 CPU 上运行 Linpack 比在 GPU 上运行要容易得多。

这些测试只是为了纪念 30 周年,只是稍微有点新颖,决不具有科学严谨或详尽无遗的特征。

一台 5 美元的云虚拟机对比一部 30 年前的 TOP500 超级计算机

但在开始测试前,我们需要开启一对 VPC。在本次测试中,我们选择在 Vultr 上运行 Linpack,但其实在 AWS,Google Cloud,Azure,Digital Ocean 或者是你喜欢的任何云服务商上,这都同样适用。

首先,我们启动了一个月费 5 美元的虚拟机实例,它具备了一个共享的 vCPU,1GB 的内存和 25GB 的存储。准备就绪后,我们便启动了 Linpack 的编译。

在这,事情可能会有些复杂,因为我们实际上可以对系统进行一些调优,挤出一些额外的 FLOPS。然而,考虑到这只是一个测试,也为了尽可能保持简单,我们选择了依照 这个指南 进行操作。此份操作手册是基于 Ubuntu 18.04 编写的,但是我们发现在 20.04 LTS 上运行也一切正常。

为了产生我们的 HPL.dat 文件,我们利用了一个巧妙的 表单,它会自动产生一个优化版的 Linpack 运行配置。

我们对几种不同类型的虚拟机进行了三次基准测试,并从每次运行中挑选出最高的得分。以下就是我们的发现:

实例类型 vCPU RAM (MB) 存储 (GB) Rmax GFLOPS 每月费用 (美元)
Regular shared 1 1024 25 31.21 5
Premium shared 1 1024 25 51.85 6
Premium shared 2 2048 60 87.46 18
Premium shared 4 8192 180 133.42 48

从我们的测试结果可以看出,一个单一的共享 vCPU 在与 1993 年 11 月十大超级计算机的比较中表现出颇为出色的性能。

我们通过一个 CPU 线程就获得了 31.21 GigaFLOPS 的 FP64 性能,这使得我们的虚拟机与 1993 年排名第三的超级计算机 —— 明尼苏达超级计算中心的 30.4 GigaFLOPS CM-5/554 Thinking Machines 系统相提并论。这确实令人吃惊,因为那台系统拥有 544 个 SuperSPARC 处理器,而我们的系统只有一个 CPU 线程,虽然我们的系统运行在更高的时钟速度下。

如你从上面的图表中所见,每月多花 1 美元,我们的性能跃升至 51.85 GigaFLOPS,而选择一个价值 18 美元的“高级”共享 CPU 实例,双线程使我们进一步接近 87.46 GigaFLOPS 的性能。

然而,要超过 富士通的数值风洞,我们需要升级到四个 vCPU 的虚拟机,由此我们抓取到了 133 GigaFLOPS 的 FP64 性能。然而不幸的是,升级到四个线程的费用跳到了每月 48 美元。达到这个价格,Vultr 实际上是在销售部分 GPU,我们预计如果采用 GPU,性能应会有显著提升,效率也会更高。

更好的选择

我们需要明确的是,这些都是我们选择的共享类型实例。一般来说,共享实例意味着在一定程度上进行了超额配置。

由于共享实例可能会受到其他租户的影响,这也使得性能有时难以预知,甚至每次运行的性能都可能略有不同,这主要取决于云区域中主机系统的载荷状态。

在我们的非常不科学的测试中,我们并未观察到太多的性能变化。我们想这可能是因为核心并未处在过高的负载下。在专有 CPU 实例上进行同样的测试,结果与我们每月 6 美元的共享实例相若,但成本高达五倍。

但是,除了这场小实验的新奇趣味之外,这没太多实际意义。如果你需要在短时间内获得大量 FLOPS,有许多已优化的 CPU 和 GPU 实例可供选择。它们的成本无法与每月 5 美元的实例相媲美,然而大多数实例是按小时账单的,因此实际成本将取决于你完成工作的迅速程度。

此外,让我们不要忘记,你的智能手机与这些存在已久的 30 年老计算系统相比,又会有怎样的对比呢?

(题图:MJ/16cf957e-a4e4-43b1-99b2-df0574a064dc)


via: https://www.theregister.com/2023/11/14/five_dollar_supercomputer/

作者:Tobias Mann 译者:ChatGPT 校对:wxy

硬核观察 #1186 每月 5 美元的虚拟机性能超过了 30 年前的第三快的超算

每月 5 美元的虚拟机性能超过了 30 年前的第三快的超算

今年是全球公开的最快超级计算机 TOP500 排行榜发布 30 周年。1993 年,当时的超算榜首是位于日本国家航空航天实验室的富士通数值风洞,该系统拥有多达 140 个 CPU 内核,可实现 124 gigaFLOPS 的双精度性能。有人做了一个有趣的测试,结果表明,每月只需要 5 美元的单个 vCPU 线程的虚拟机可以与 1993 年排名第三的超级计算机明尼苏达超级计算中心相抗衡,而该系统拥有 544 个 SuperSPARC 处理器。如果升级到 4 个 vCPU 虚拟机,就可以击败当年的榜首,每个月仅需要花费 48 美元。

消息来源:The Register

老王点评:不算意外,只是有些吃惊。不敢想象三十年后计算机能强大到什么程度,或许地球会爆炸吧。

Canonical 发布快速部署全功能私有云的 MicroCloud

Canonical 公司今天发布了最新的软件产品 MicroCloud,它的目标是在 Ubuntu Linux 上轻松部署一个 “几分钟内就能实现全功能云” 的私有云。他们宣传自己的私有云部署就像使用 Snap 命令一样简单。其代码以 AGPL-3.0 许可托管在 GitHub 上。据介绍,MicroCloud 至少需要三台机器,目前可扩展到 50 台机器。

消息来源:Phoronix

老王点评:现在看起来,私有云有公有云不可比拟的好处,最起码重启起来比较快~

DeepMind 能更快更准确地预测极端天气

根据一份研究,谷歌 DeepMind 的模型 GraphCast 能够提前 10 天预测天气状况,比目前的黄金标准更准确、更快速。在 1300 多个测试区域中,GraphCast 在 90% 以上的测试中都优于欧洲中期天气预报中心的模型。最重要的是,GraphCast 还能比标准模型更早地为气象学家提供有关极端气温和气旋路径等情况的准确预警。GraphCast 使用图神经网络,将地球表面映射成 100 多万个网格点。它不使用物理方程,而是根据四十年的历史天气数据进行预测,可以利用机器学习在一分钟内完成这些计算。

消息来源:Technology Review

老王点评:没想到不是超算,而是人工智能拯救了天气预测难题。

这儿几个字节,那里几个字节,我们说的是真正的内存

今天的帖子来自于最近的 Go 语言的一次小测试,观察下面的测试基础片段 [1]

func BenchmarkSortStrings(b *testing.B) {
        s := []string{"heart", "lungs", "brain", "kidneys", "pancreas"}
        b.ReportAllocs()
        for i := 0; i < b.N; i++ {
                sort.Strings(s)
        }
}

sort.Stringssort.StringSlice(s) 的便捷包装器,sort.Strings 在原地对输入进行排序,因此不会分配内存(或至少 43% 回答此问题的 Twitter 用户是这么认为的)。然而,至少在 Go 的最近版本中,基准测试的每次迭代都会导致一次堆分配。为什么会是这种情况?

正如所有 Go 程序员应该知道的那样,接口是以 双词结构 实现的。每个接口值包含一个字段,其中保存接口内容的类型,以及指向接口内容的指针。 [2]

在 Go 语言伪代码中,一个接口可能是这样的:

type interface struct {
        // the ordinal number for the type of the value
        // assigned to the interface 
        type uintptr

        // (usually) a pointer to the value assigned to
        // the interface
        data uintptr
}

interface.data 可以容纳一个机器字(在大多数情况下为 8 个字节),但一个 []string 却需要 24 个字节:一个字用于指向切片的底层数组;一个字用于存储切片的长度;另一个字用于存储底层数组的剩余容量。那么,Go 是如何将 24 个字节装入个 8 个字节的呢?通过编程中最古老的技巧,即间接引用。一个 []string,即 s,需要 24 个字节;但 *[]string —— 即指向字符串切片的指针,只需要 8 个字节。

逃逸到堆

为了让示例更加明确,以下是重新编写的基准测试,不使用 sort.Strings 辅助函数:

func BenchmarkSortStrings(b *testing.B) {
        s := []string{"heart", "lungs", "brain", "kidneys", "pancreas"}
        b.ReportAllocs()
        for i := 0; i < b.N; i++ {
                var ss sort.StringSlice = s
                var si sort.Interface = ss // allocation
                sort.Sort(si)
        }
}

为了让接口正常运行,编译器将赋值重写为 var si sort.Interface = &ss,即 ss 的地址分配给接口值。 [3] 我们现在有这么一种情况:出现一个持有指向 ss 的指针的接口值。它指向哪里?还有 ss 存储在哪个内存位置?

似乎 ss 被移动到了堆上,这也同时导致了基准测试报告中的分配:

Total:    296.01MB   296.01MB (flat, cum) 99.66%
      8            .          .           func BenchmarkSortStrings(b *testing.B) { 
      9            .          .             s := []string{"heart", "lungs", "brain", "kidneys", "pancreas"} 
     10            .          .             b.ReportAllocs() 
     11            .          .             for i := 0; i < b.N; i++ { 
     12            .          .                 var ss sort.StringSlice = s 
     13     296.01MB   296.01MB                 var si sort.Interface = ss // allocation 
     14            .          .                 sort.Sort(si) 
     15            .          .             } 
     16            .          .           } 

发生这种分配是因为编译器当前无法确认 sssi 生存期更长。Go 编译器开发人员对此的普遍态度是,觉得 这个问题改进的余地,不过我们另找时间再议。事实上,ss 就是被分配到了堆上。因此,问题变成了:每次迭代会分配多少个字节?为什么不去询问 testing 包呢?

% go test -bench=. sort_test.go
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i7-5650U CPU @ 2.20GHz
BenchmarkSortStrings-4          12591951                91.36 ns/op           24 B/op          1 allocs/op
PASS
ok      command-line-arguments  1.260s

可以看到,在 amd 64 平台的 Go 1.16 beta1 版本上,每次操作会分配 24 字节。 [4] 然而,在同一平台先前的 Go 版本中,每次操作则消耗了 32 字节。

% go1.15 test -bench=. sort_test.go
goos: darwin
goarch: amd64
BenchmarkSortStrings-4          11453016                96.4 ns/op            32 B/op          1 allocs/op
PASS
ok      command-line-arguments  1.225s

这引出了本文的主题,即 Go 1.16 版本中即将推出的一项便利改进。不过在讨论这个内容之前,我需要聊聊 “ 尺寸类别 size class ”。

尺寸类别

在解释什么是 “ 尺寸类别 size class ” 之前,我们先考虑个问题,理论上的 Go 语言在运行时是如何在其堆上分配 24 字节的。有一个简单的方法:追踪目前为止已分配到的所有内存的动向——利用指向堆上最后分配的字节的指针。分配 24 字节,堆指针就会增加 24,然后将前一个值返回给调用函数。只要写入的请求 24 字节的代码不超出该标记的范围,这种机制就没有额外开销。不过,现实情况下,内存分配器不仅要分配内存,有时还得释放内存。

最终,Go 语言程序在运行时将释放这些 24 字节,但从运行的视角来看,它只知道它给调用者的开始地址。它不知道从该地址起始之后又分配了多少字节。为了允许释放内存,我们假设的 Go 语言程序运行时分配器必须记录堆上每个分配的长度值。那么这些长度值的分配存储在何处?当然是在堆上。

在我们的设想中,当程序运行需要分配内存的时候,它可以请求稍微多一点,并把它用来存储请求的数量。而对于我们的切片示例而言,当我们请求 24 字节时,实际上会消耗 24 字节加上存储数字 24 的一些开销。这些开销有多大?事实上,实际上的最小开销量是一个字。 [5]

用来记录 24 字节分配的开销将是 8 字节。25% 不是很大,但也不算糟糕,随着分配的大小增加,开销将变得微不足道。然而,如果我们只想在堆上存储一个字节,会发生什么?开销将是请求数据量的 8 倍!是否有一种更高效的方式在堆上分配少量内存?

与其在每个分配旁边存储长度,不如将相同大小的内容存储在一起,这个主意如何?如果所有的 24 字节的内容都存储在一起,那么运行时会自动获取它们的大小。运行时所需要的是一个单一的位,指示 24 字节区域是否在使用中。在 Go 语言中,这些区域被称为 Size Classes,因为相同大小的所有内容都会存储在一起(类似学校班级,所有学生都按同一年级分班,而不是 C++ 中的类)。当运行时需要分配少量内存时,它会使用能够容纳该分配的最小的尺寸类别。

无限制的尺寸类别

现在我们知道尺寸类别是如何工作的了,那么问题又来了,它们存储在哪里?和我们想的一样,尺寸类别的内存来自堆。为了最小化开销,运行时会从堆上分配较大的内存块(通常是系统页面大小的倍数),然后将该空间用于单个大小的分配。不过,这里存在一个问题————

将大块区域用于存储同一大小的事物的模式很好用 [6] ,如果分配大小的数量是固定的,最好是少数几个。那么在通用语言中,程序可以要求运行时以任何大小分配内存 [7]

例如,想象一下向运行时请求 9 字节。9 字节是一个不常见的大小,因此可能需要一个新的尺寸类别来存储 9 字节大小的物品。因为 9 字节大小的物品不常见,所以分配的其余部分(通常为 4KB 或更多)可能会被浪费。由于尺寸类别的集合是固定的,如果没有精确匹配的 size class 可用,分配将并入到下一个尺寸类别。在我们的示例中,9 字节可能会在 12 字节的尺寸类别中分配。未使用的 3 字节的开销要比几乎未使用的整个尺寸类别分配好。

总结一下

这是谜题的最后一块拼图。Go 1.15 版本没有 24 字节的尺寸类别,因此 ss 的堆分配是在 32 字节的尺寸类别中分配的。由于 Martin Möhrmann 的工作,Go 1.16 版本有一个 24 字节的尺寸类别,非常适合分配给接口的切片值。

相关文章

  1. 我在 Devfest 2017年西伯利亚大会谈 Go 语言
  2. 如果对齐的内存写操作是原子性的,为什么我们还需要 sync/atomic 包呢?
  3. 为你的树莓派创建一个真实的串行控制台
  4. 为什么 Go 语言线程的栈是无限制的?

(题图:MJ/01d5fe46-778f-48fe-9481-162f4d0289dc)


  1. 这不是正确的对排序函数进行基准测试的方式,因为在第一次迭代之后,输入已经排序。但这又是另外一个话题了。 ↩︎
  2. 此语句的准确性取决于所使用的 Go 版本。例如,Go 1.15 版本添加了直接将一些 整数存储在接口值 中的功能,从而节省了分配和间接性。然而,对于大多数值来说,如果它不是指针类型,它的地址将被取出并存储在接口值中。 ↩︎
  3. 编译器在接口值的类型字段中跟踪了这种手法,因此它记住了分配给 si 的类型是 sort.StringSlice 而不是 *sort.StringSlice↩︎
  4. 在 32 位平台上,这个数字减半,但我们不再关注它↩︎
  5. 如果你准备限制分配为 4G 或者可能是 64KB,你可以使用较少内存来存储分配的尺寸,但实际上使用小于一个字来存储长度标头的节省会受到填充的影响。 ↩︎
  6. 将相同大小的物品存储在一起也是一种有效的对抗碎片化的策略。 ↩︎
  7. 这并不是一个不切实际的设想,字符串有各种形状和大小,生成以前未见过的大小的字符串可能就像附加空格一样简单。 ↩︎

via: https://dave.cheney.net/2021/01/05/a-few-bytes-here-a-few-there-pretty-soon-youre-talking-real-memory

作者:Dave Cheney 选题:lujun9972 译者:Drwhooooo 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

硬核观察 #1185 宇宙射线可以导致 SSH 私钥被窃取

宇宙射线可以导致 SSH 私钥被窃取

研究人员发现,可以观察到 SSH 签名生成过程中意外或自然发生的计算错误,并利用这些错误来计算 SSH 服务器的本应保密的密钥私钥。所谓自然发生的错误,指的是宇宙射线和其他会翻转比特的小故障造成的错误;而所谓意外发生的错误,指的是 RSA 签名生成算法执行不力。如果你监控了足够多的到易受攻击的 SSH 服务器的连接,你最终会发现一个可以利用的漏洞。研究人员检查了过去七年扫描互联网收集的 10 亿个使用了 RSA 算法的签名。在这些签名中,有百万分之一的主机私钥会被暴露。

消息来源:The Register

老王点评:所以,加密算法还得防着宇宙射线的攻击。

苹果公司拿走了 1/3 的 Safari 上的谷歌搜索广告收入

谷歌和苹果公司早在 2002 年就建立了合作关系,谷歌成为苹果 Safari 浏览器的默认搜索引擎,过去几年谷歌每年为此向苹果支付了数十亿美元。在诉谷歌反垄断案审判中,谷歌的经济学家在法庭上意外披露了用户通过 Safari 浏览器使用谷歌搜索产生的广告收入,其中 36% 会支付给苹果公司。谷歌和苹果公司都曾反对公开披露双方协议的细节。

消息来源:彭博社

老王点评:好家伙,浏览器可真是个摇钱树啊。

谷歌起诉涉嫌发布植入恶意软件的山寨版 Bard 的骗子

谷歌起诉称,越南的一些人一直在建立社交媒体页面并发布广告,鼓励用户下载一个 “Bard”,但这个版本的 “Bard” 并不能提供如何烹饪意大利烩饭之类的有用答案。一旦某个傻瓜下载了这个 “Bard”,它就会侵入系统并窃取密码和社交媒体凭证。诉讼指出,这些骗子特别将 Facebook 作为他们的首选传播方式。

消息来源:Engadget

老王点评:这是把免费服务当成恶意软件的载体了,不过我觉得比起来今天圈内将开源 LLaMA “改成” 自己的开源大模型的大瓜,也算不了什么。

Linux 爱好者线下沙龙:LLUG 2023·西子湖畔相见

走走停停,最终还是走到了西子湖畔。在这个冬日,LLUG 与你在杭州线下相见。

11 月 25 日,LLUG 杭州场将在杭州未来科技城国际人才园(五常地铁站附近)举办。

本次活动依然由 Linux 中国和龙蜥社区(OpenAnolis)联合主办,杭州 GDG 协办,杭州城西科创大走廊高层次人才联合会提供场地支持。

龙蜥社区(OpenAnolis)是国内的顶尖 Linux 发行版社区,我们希望在普及 Linux 知识的同时,也能让中国的 Linux 发行版,为更多人知晓,推动国产发行版的发展和进步。

杭州城西科创大走廊高层次人才联合会简称“高联会”,高联会是在杭州城西科创大走廊管委会指导下,旨在广泛吸纳与团结廊内高层次人才,助力人才在杭州城西科创大走廊的创新创业。

杭州 GDG(杭州谷歌开发者社区),谷歌官方赞助的杭州本地技术社区,每年定期举办免费开发者线下技术沙龙,聚焦谷歌相关开源技术,欢迎大家关注微信公众号“杭州GDG”,了解我们,参与技术交流。

成都场现场照片

深圳场现场照片

上海场现场照片

本次活动,我们将设常规的技术分享、动手实践和闪电演讲三种不同分享的形态。

  • 技术分享会邀请来自 Linux 社区的开发者,分享自己在 Linux 中的技术实践,并配合 Q&A 的环节,帮助大家理解技术难点和实践,如果你有经验和实践想要分享给大家,欢迎报名分享
  • 动手实践则会有来自各厂商的 Linux 大咖,带着大家用半个小时的时间来动手实践一个 Linux 主题,帮助大家动手体验 Linux 的种种新特性、特定的能力。
  • 闪电演讲则不设定主题,每个人有 5 分钟时间来分享自己与 Linux、技术、开源有关的话题,共计 6 个闪电演讲名额,想要试试锻炼自己的演讲能力,不妨从闪电演讲开始。

欢迎大家扫码加入 LLUG 杭州分群,在群里为活动提出你的建议~

此外,如果你对分享感兴趣,欢迎填写下方问卷来提交你的议题,向开发者们分享你的研究、实践和经验:https://jinshuju.net/f/VJkeMZ

(题图:MJ/8f5c79b3-5531-4e49-872d-ddb79266600a)

Git 的遴选和撤销操作是如何利用三路合并的

大家好!几天前,我尝试向其他人解释 Git 遴选(git cherry-pick)的工作原理,结果发现自己反而更混淆了。

我原先以为 Git 遴选是简单地应用一个补丁,但当我真正这样尝试时,却未能成功!

因此,接下来我们将谈论我原来以为的遴选操作(即应用一个补丁),这个理解为何不准确,以及实际上它是如何执行的(进行“三路合并”)。

尽管本文的内容有些深入,但你并不需要全部理解才能有效地使用 Git。不过,如果你(和我一样)对 Git 的内部运作感到好奇,那就跟我一起深入探讨一下吧!

遴选操作并不只是应用一个补丁

我先前理解的 git cherry-pick COMMIT_ID 的步骤如下:

  • 首先是计算 COMMIT_ID 的差异,就如同执行 git show COMMIT_ID --patch > out.patch 这个命令
  • 然后是将补丁应用到当前分支,就如同执行 git apply out.patch 这个命令

在我们详细讨论之前,我想指出的是,虽然大部分情况下这个模型是正确的,如果这是你的认知模型,那就没有问题。但是在一些细微的地方,它可能会错,我觉得这个疑惑挺有意思的,所以我们来看看它究竟是如何运作的。

如果我在存在合并冲突的情况下尝试进行“计算差异并应用补丁”的操作,下面我们就看看具体会发生什么情况:

$ git show 10e96e46 --patch > out.patch
$ git apply out.patch
error: patch failed: content/post/2023-07-28-why-is-dns-still-hard-to-learn-.markdown:17
error: content/post/2023-07-28-why-is-dns-still-hard-to-learn-.markdown: patch does not apply

这一过程无法成功完成,它并未提供任何解决冲突或处理问题的方案。

而真正运行 git cherry-pick 时的实际情况却大为不同,我遭遇到了一处合并冲突:

$ git cherry-pick 10e96e46
error: could not apply 10e96e46... wip
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".

因此,看起来 “Git 正在应用一个补丁”这样的理解方式并不十分准确。但这里的错误信息确实标明了 “无法应用 10e96e46”,这么看来,这种理解又不完全是错的。这到底是怎么回事呢?

那么,遴选到底是怎么执行的呢?

我深入研究了 Git 的源代码,主要是想了解 cherry-pick 是如何工作的,最终我找到了 这一行代码

res = do_recursive_merge(r, base, next, base_label, next_label, &head, &msgbuf, opts);

所以,遴选实际上就是一种……合并操作?这有些出乎意料。那具体都合并了什么内容?如何执行这个合并操作的呢?

我意识到我对 Git 的合并操作并不是特别理解,于是我上网搜索了一下。结果发现 Git 实际上采用了一种被称为 “三路合并” 的合并方式。那这到底是什么含义呢?

Git 的合并策略:三路合并

假设我要合并下面两个文件,我们将其分别命名为 v1.pyv2.py

def greet():
    greeting = "hello"
    name = "julia"
    return greeting + " " + name
def say_hello():
    greeting = "hello"
    name = "aanya"
    return greeting + " " + name

在这两个文件间,存在两处不同:

  • def greet()def say_hello
  • name = "julia"name = "aanya"

我们应该选择哪个呢?看起来好像不可能有答案!

不过,如果我告诉你,原始的函数(我们称之为 base.py)是这样的:

def say_hello():
    greeting = "hello"
    name = "julia"
    return greeting + " " + name

一切似乎变得清晰许多!在这个基础上,v1 将函数的名字更改为 greetv2name = "aanya"。因此,合并时,我们应该同时做出这两处改变:

def greet():
    greeting = "hello"
    name = "aanya"
    return greeting + " " + name

我们可以命令 Git 使用 git merge-file 来完成这次合并,结果正是我们预期的:它选择了 def greet()name = "aanya"

$ git merge-file v1.py base.py v2.py -p
def greet():
    greeting = "hello"
    name = "aanya"
    return greeting + " " + name⏎

这种将两个文件与其原始版本进行合并的方式,被称为 三路合并

如果你想在线上试一试,我在 jvns.ca/3-way-merge/ 创建了一个小实验场。不过我只是草草制作,所以可能对移动端并不友好。

Git 合并的是更改,而非文件

我对三路合并的理解是 —— Git 合并的是更改,而不是文件。我们对同一个文件做出两种不同的更改,Git 试图以合理的方式将这两种更改结合到一起。当两个更改都对同一行进行操作时,Git 可能会遇到困难,此时就会产生合并冲突。

Git 也可以合并超过两处的更改:你可以对同一文件有多达 8 处不同的更改,Git 会尝试将所有更改协调一致。这被称为八爪鱼合并,但除此之外我对其并不了解,因为我从未执行过这样的操作。

Git 如何使用三路合并来应用补丁

接下来,让我们进入到一个有些出乎意料的情境!当我们讨论 Git “应用补丁”(如在变基 —— rebase、撤销 —— revert 或遴选 —— cherry-pick 中所做的)时,其实并非是生成一个补丁文件并应用它。相反,实际执行的是一次三路合并。

下面是如何将提交 X 作为补丁应用到你当前的提交,并与之前的 v1v2base 设置相对应:

  1. 在你当前提交中,文件的版本是 v1
  2. 在提交 X 之前,文件的版本是 base
  3. 在提交 X 中,文件的版本是 v2
  4. 执行 git merge-file v1 base v2 以合并它们(实际上,Git 并不直接执行 git merge-file,而是运行一个实现这个功能的 C 函数)。

总的来说,你可以将 basev2 视为“补丁”,它们之间的差异就是你想要应用到 v1 上的更改。

遴选如何运作

假设我们有如下提交图,并且我们打算在 main 分支上遴选提交 Y

A - B (main)
  \ 
   \ 
    X - Y - Z

那么,如何将此情景转化为我们前面提过的 v1v2base 组成的三路合并呢?

  • Bv1
  • Xbase,而 Yv2

所以,XY 共同构成了这个“补丁”。

其实,git rebase 无非就是重复多次执行 git cherry-pick 的过程。

撤销如何运作

现在,假如我们希望在如下的提交图上执行 git revert Y

X - Y - Z - A - B
  • Bv1
  • Ybase,而 Xv2

这个过程反映的实际上就是遴选的情况,不过 XY 的位置颠倒了。我们需要这样做因为我们期望生成一个“反向补丁”。在 Git 中,撤销和遴选关系如此的紧密,它们甚至在同一个文件中实现:revert.c

“三路补丁”是一个非常棒的技巧

使用三路合并将提交作为补丁应用的这个技巧非常巧妙且酷炫,我很惊讶之前从未听说过!我并未听过一个特定的名字来描述这种方法,但我更倾向于称之为“三路补丁”。

“三路补丁”的理念在于,你可以通过两个文件来定义补丁:在应用补丁前后的文件(在我们这篇文章中称之为 basev2)。

因此,总体来看有三个文件被涉及到:一个是原文件,另外两个构成了补丁。

最重要的是,与普通补丁相比,三路补丁是一个更加高效的补丁方案,因为在有两个完整文件的情况下,你拥有更丰富的上下文信息来进行合并。

以下是我们例子中的常规补丁的大致情况:

@@ -1,1 +1,1 @@:
- def greet():
+ def say_hello():
    greeting = "hello"

而下面这就是一个三路补丁。不过,需要提醒的是这个“三路补丁”并不是一个真正的文件格式,这只是我自己提出的一种概念。

BEFORE: (the full file)
def greet():
    greeting = "hello"
    name = "julia"
    return greeting + " " + name
AFTER: (the full file)
def say_hello():
    greeting = "hello"
    name = "julia"
    return greeting + " " + name

《Building Git》 中提到了这点

James Coglan 的书籍 《Building Git》 是我在 Git 源码之外唯一找到的地方,他解释了 git cherry-pick 是如何在底层运用三路合并的(我原以为《Pro Git》可能会提及这个,但我并没能找到此话题的内容)。

我购买完这本书后发现,我早在 2019 年时就已经买过了,这对我来说真的是个很好的参考。

Git 中的合并实际上比这更复杂

在 Git 中,合并不限于三路合并 —— 还有一种我不太理解的叫做“递归合并”,还有许多具体处理文件删除和移动的细节,同时也有多种合并算法。

如果想要了解更多相关知识,我最好的建议是阅读《Building Git》,尽管我还未完全阅读这本书。

Git 应用到底做了什么?

我也参阅了 Git 的源代码,试图理解 git apply 的功能。它似乎(不出意外地)在 apply.c 中实现。这段代码解析了一个补丁文件,并通入目标文件来寻找应该在何处应用补丁。核心逻辑似乎在 这里:思路好像是从补丁建议的行数开始,然后向前向后找寻。

    /*
     * There's probably some smart way to do this, but I'll leave
     * that to the smart and beautiful people. I'm simple and stupid.
     */
    backwards = current;
    backwards_lno = line;
    forwards = current;
    forwards_lno = line;
    current_lno = line;
for (i = 0; ; i++) {
     ...

这个处理过程不禁让人觉得非常直白、与之前的期望相符。

Git 三路应用的工作方式

git apply 命令中也有一个 --3way 参数,可以实现三路合并。因此,我们实际上可以通过如下方式,使用 git apply 来大体实现 git cherry-pick 的功能:

$ git show 10e96e46 --patch > out.patch
$ git apply out.patch --3way
Applied patch to 'content/post/2023-07-28-why-is-dns-still-hard-to-learn-.markdown' with conflicts.
U content/post/2023-07-28-why-is-dns-still-hard-to-learn-.markdown

但要注意,参数 --3way 并不只用到了补丁文件的内容!补丁文件开始的部分是:

index d63ade04..65778fc0 100644

d63ade0465778fc0 是旧/新文件版本在 Git 对象数据库中的 ID,因此 Git 可以用这些 ID 来执行三路补丁操作。但如果有人将补丁文件通过邮件发送给你,而你并没有新/旧版本的文件,就无法执行这个操作:如果你缺少 blob,将会出现如下错误:

$ git apply out.patch
error: repository lacks the necessary blob to perform 3-way merge.

三路合并有点历史了

有一部分人指出,三路合并比 Git 的历史还要久远,它起源于 70 年代末期左右。有一篇 2007 年的 论文 对此进行了讨论。

就说这么多!

我真的对于我对于 Git 内部应用补丁的核心方法其实理解得并不深入这一点感到非常吃惊——学习这一点真的很酷!

虽然我对 Git 用户界面存在 诸多不满,但是这个特定问题并不包含在内。三路合并似乎是统一解决一系列不同问题的优雅方式,它对于人们来说也很直观(“应用一个补丁”这个想法是许多编程者都习以为常的思考模式,而它底层实现为三路合并的细节,实际上没有人真正需要去思考)。

我顺便快速推荐一下:我正在写一部有关 Git 的 zine,如果你对它的发布感兴趣,你可以注册我非常不频繁的 公告邮件列表

(题图:MJ/321bc2c9-4363-4661-802a-c74fb6a721b2)


via: https://jvns.ca/blog/2023/11/10/how-cherry-pick-and-revert-work/

作者:Julia Evans 选题:lujun9972 译者:ChatGPT 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

新款 Fedora Slimbook 14 加入 Fedora Slimbook 阵营

自从我们发布 Fedora Slimbook 笔记本电脑的公告到现在已经过去近一个月了。这只是我们和 Slimbook 之间的合作关系的开始,我们的目标是在更多的设备上预装 Fedora Linux 系统。目前我们已经收到了非常积极的反馈!剩下的,我们想要和大家分享更多来自我们硬件合作伙伴的新消息,我们希望你会觉得很兴奋。

介绍 Fedora Slimbook 14 英寸版

尽管 Fedora Slimbook 16 英寸版的性能很出色,但我们注意到许多消费者对于笔记本电脑的尺寸以及英伟达显卡的配置表示了担忧,他们希望有更小的选择。为了回应这些反馈,Slimbook 推出了更小尺寸的 Fedora Slimbook 14 英寸版,以满足这些消费者的需求。这款新型号的电脑仍然保持了 Fedora 品牌的标志,包括电脑后盖和超级键上的 Fedora 标志,并且预装了 Fedora Workstation 系统!

主要特性:

  • 无英伟达 GPU:虽然将这一点作为特性有些奇怪,但对于那些希望享受 Fedora 完整体验、期望硬件全面兼容的消费者来说,这一点准没错。
  • 英特尔 i7-12700H 处理器:能满足你所有的计算需求,性能出众。
  • 99Wh 电池:超长电池寿命,让你在出门在外时也能保持高效。
  • 轻便,只有 1.25 公斤:无论你去哪里,都可以轻松携带。
  • 镁合金机身:外壳轻便且耐磨。
  • 2880x1800 的屏幕分辨率:在高分辨率的显示屏上享受鲜明的视觉效果和细节。
  • 99% 的 sRGB 色彩准确度:非常适合设计师,媒体和内容创作人员使用。

与 Fedora Slimbook 16 英寸版一样,每售出一台 Fedora Slimbook 14 英寸版,都会有 3% 的收益捐献给 GNOME 基金会。

我们希望 Fedora Slimbook 14 英寸版可以满足你对电源和便携性的需求,并且展示出你对 Fedora 的热爱!想了解更多信息,请访问 https://fedora.slimbook.es/

折扣

Slimbook 针对 Fedora 社区推出了两种折扣!

为了庆祝 Fedora Linux 39 的发布,Slimbook 推出了针对两款 Fedora Slimbook 的 100 欧元折扣活动!当你选择结账的时候,你会发现这个折扣已经直接被应用上去了。这项优惠将在限定的时间中推出。

而且,如果你是 Fedora 项目的贡献者,还可以享受额外的 100 欧元折扣!关于如何获得这个折扣的更多信息,你可以点击 这个社区博客文章 查阅。

在我们与 Slimbook 建立并发展这个伙伴关系的过程中,我们非常感谢他们的良好合作。我们致力于让 Linux 更广泛地应用于硬件设备上,我们希望这些新的公告能让你对 Fedora 的硬件合作伙伴计划感到兴奋!


via: https://fedoramagazine.org/new-fedora-slimbook-14-joins-the-fedora-slimbook-16/

作者:Joseph Gayoso 选题:lujun9972 译者:译者ID 校对:校对者ID

本文由 LCTT 原创编译,Linux中国 荣誉推出

硬核观察 #1184 等不及官方发布,创客制作了自己的树莓派 CM5

等不及官方发布,创客制作了自己的树莓派 CM5

树莓派 5 已于上月发布,但创客们在等待有关 CM5 计算模块的消息。其中有一位创客决定不再等下去,而是从零开始制作了一块 “CM5”。这块定制的 PCB 板具有树莓派 CM4 的外形尺寸,但能够支持树莓派 5 的功率。这实际上不是 CM5,也不出售。事实上,它甚至不是一个 SBC,而更像是一个载板,能让树莓派 5 与 CM4 兼容的东西进行交互。

消息来源:Tom's Hardware

老王点评:创客们总是自己动手,丰衣足食。

10 万块闲置的挖矿 GPU 被出租给人工智能负载

加密货币热潮崩溃后,许多加密货币农场都留下了大量闲置的 GPU。一些公司设法为它们的 GPU 找到了其他用途,Io.net 就开发了一个分布式网络,目前已经汇集了超过十万块 GPU,并将它们用于人工智能应用。该公司还使用 Solana 区块链技术管理其网络内的微交易,以便向 GPU 计算提供商付款。

消息来源:Tom's Hardware

老王点评:GPU 卡就是生产力,不能挖矿,还能挖 AI。

隐藏在 Python 混淆软件工具中的高入侵性后门

自今年 1 月以来,已有 8 个 Python 开发者工具包含了具有各种恶意功能的隐藏有效载荷。这几个恶意工具包的名字都以 “pyobf” 开头。它们都是混淆工具,开发人员可以用它来阻止逆向工程和篡改他们的代码。但是一旦被执行,这些恶意工具就会安装一个有效载荷,让攻击者几乎可以完全控制开发者的机器,包括窃取主机信息、浏览器密码、记录击键、加密勒索等操作。这些恶意工具已被 Python 程序员们安装了数千次。

消息来源:Ars Technica

老王点评:想要保密代码反而中了招,反正你也看不懂加密混淆后的代码在做什么,真是十分切合场景。

下一代 elementary OS 8 剧透

你是否正在关注 elementary OS 8 的升级呢?接下来的信息你必须了解。

elementary OS 无疑是 最美丽的 Linux 发行版 中的佼佼者。就在一个月之前,注重隐私保护的 elementary OS 7.1 版本也发布了。

现在,通过最新的公告,我们对即将发布的 elementary OS 8 有了更全面的了解。

而且这一次,我们看起来可能会早一点体验到新的 elementary OS 版本。

让我们深入挖掘下吧!?

elementary OS 8:一项雄心勃勃的尝试

elementary OS 的开发者已经将目标转向 OS 8 系列,他们 对此寄予了深厚的期待,看好其带来的大量结构性改变和升级

根据 elementary OS 8 的开发路线图,此次主要版本将以 Ubuntu 24.04 的源代码库 为基础构建,然而,目前的情况显示,我们至少需要 等到 2024 年 4 月才能见到 OS 8 的发布

同时,他们也明确提到,他们设定了一些 非常雄心勃勃的目标,希望未来的 6 个月内就可以完成。不过,他们 打算在 OS 8 完全准备就绪后再进行发布

那么,这些目标具体有哪些呢?

首先,他们计划默认实现对 Wayland过渡,这不算令人意外,因为我们已经看到许多主流发行版都在采用它。接下来便是 延续 GTK 4 的过渡,其中包含了一些目前处于开发最后阶段的核心应用。

此外,他们正处于 设计新的快速设置菜单的初级阶段,并且还明确表示,此次发布会对他们的桌面环境 Pantheon 的设计进行重大改进

读到这里,你可能会产生一个问题;那么,elementary OS 7 将会如何呢?

开发者已经明确表示,当前正在使用 OS 7 的用户从现在起可能会收到的更新会变少,因为他们认为 OS 7 版本已经相当完善。

但是,所有以 Flatpak 包形式提供的应用还将继续定期接收更新,这当然也包括了许多 elementary OS 的核心应用。

想要了解更多信息,你可以参考 官方公告。如果你对 elementary OS 8 的开发进度 感兴趣,你可以在其 GitHub 项目看板 上进行关注。

你是否想要尝试一下 elementary OS 8 的早期构建版本呢?

好的,基于 Ubuntu 24.04 源代码库的试验构建版 现在就可以下载了!请记住,想要获取下载权限,你需要成为 GitHub 上的赞助者

现在就可以前往官方的 构建网站 开始下载了。

elementary OS 早期访问

? 你对此感到兴奋吗?欢迎在下方留言分享你的观点!

(题图:MJ/e707c7c7-8d97-4f41-a955-cf455784493f)


via: https://news.itsfoss.com/elementary-os-8-dev/

作者:Sourav Rudra 选题:lujun9972 译者:译者ID 校对:校对者ID

本文由 LCTT 原创编译,Linux中国 荣誉推出

你应该知道的主流开源数据库

随着数据的飞速增长,数据的组织变得至关重要。本文将简要介绍当今软件开发中最流行的数据库。

在软件系统中,数据被格式化地组织和存储,通过数据库可以以电子方式访问它们。因为数据已经成为一种非常重要的资产,对我们来说,掌握当今使用的各种数据库的基本知识是非常重要的。

我们要看的第一个数据库是 MySQL。

MySQL

MySQL 官网

MySQL 是使用最广泛的开源数据库管理系统之一。它由 甲骨文公司 Oracle Corporation 所有。它可以在大多数主流操作系统上运行,如 Windows、MacOS、Linux 等。MySQL 既适用于小型应用,同时也能胜任大型应用。

优点
  • 适配各种操作系统
  • 适配多种编程语言,如 PHP、C、C++、Perl 等
  • 开源、免费
  • 它支持高达 8 百万 Tb 的巨大数据量
  • 可定制化
  • 比其他数据库快得多

要在基于 Ubuntu 的计算机上安装并使用 MySQL,使用下面的命令:

$sudo apt update
$sudo apt install mysql-server
$sudo systemctl start mysql.service

MariaDB

MariaDB 官网

MariaDB 是一款由 MySQL 的开发人员开发的开源关系型数据库,因其优秀的性能和与 MySQL 良好的兼容性而广受欢迎。它是当今大多数主要云产品的一部分,对其稳定性和性能起到重要作用。最近通过使用 Galera Cluster 技术,MariaDB 新增了集群功能。另外 MariaDB 还与 Oracle 数据库有(一定的)兼容性。

优点
  • 安装方便
  • 支持大数据操作
  • 高可扩展性
  • 易于导入数据

要在基于 Ubuntu 的计算机上安装并使用 MariaDB,请使用以下命令:

$sudo apt update
$sudo apt install mariadb-server
$sudo systemctl start mariadb.service

RethinkDB

RethinkDB 官网

RethinkDB 是一个开源、免费、分布式、基于文档的 NoSQL 数据库。它由 RethinkDB 公司开发。(LCTT 译注:RethinkDB 公司已于 2016 年倒闭。RethinkDB 数据库现作为开源项目继续维护。消息来源)它可以存储具有动态模式的 JSON 文件。更重要的是,它可以将查询结果的实时更新推送给应用程序。由于它的分布式特性,它具有高度可扩展性。RethinkDB 提供了丰富的内置函数,使其成为一个高可用性的数据库。由于它是当今流行的数据库,学习如何使用它是很重要的。

优点
  • 适合于 Web 应用
  • 易于扩展
  • 内置函数多,可用性高
  • 基于 JSON 动态文档

要在基于 Ubuntu 的计算机上使用 RethinkDB,下面的命令会有帮助:

# 添加软件仓库源 
source /etc/lsb-release && echo "deb https://download.rethinkdb.com/repository/ubuntu-$DISTRIB_CODENAME $DISTRIB_CODENAME main" | sudo tee /etc/apt/sources.list.d/rethinkdb.list

# 下载并安装 RethinkDB 的 GPG 密钥
$wget -qO- https://download.rethinkdb.com/repository/raw/pubkey.gpg | sudo apt-key add - 

$sudo apt update
$sudo apt-get install rethinkdb
$sudo systemctl start rethinkdb

OrientDB

OrientDB 官网

OrientDB 是一个基于 Java 的开源 NoSQL 数据库管理系统。它支持多种数据模型,比如文档、字典、对象和图。它以图数据库的形式存储关系。下面的命令可以帮助你在 Ubuntu 机器上使用 OrientDB:

$sudo apt-get update
$wget -O orientdb-community-2.2.20.tar.gz http://orientdb.com/download.php?file=orientdb-community-2.2.20.tar.gz&os=linux
$tar -zxvf orientdb-community-2.2.20.tar.gz
$sudo mv ~/orientdb-community-2.2.20 /opt/orientdb

CouchDB

CouchDB 官网

CouchDB 是用 Erlang 开发的开源 NoSQL 数据库。它使用多种协议和格式来传输、处理和共享数据。它使用 JSON 格式存储数据,支持 MapReduce,并用 JavaScript 作为查询语言。

优点
  • 可以存储任何类型的数据
  • 支持 MapReduce,可以高效地处理数据
  • 整体结构非常简单
  • 索引和检索速度快

下面的命令可以帮助你在 Ubuntu 机器上使用 CouchDB:

$echo "deb https://apache.bintray.com/couchdb-deb focal main" >> /etc/apt/sources.list
$sudo apt-get update
$sudo apt install apache2 couchdb -y

Firebird

Firebird 官网

Firebird 是一个开源关系型数据库。它兼容所有操作系统,如 Linux、Windows 和 MacOS。它最初是从开源数据库 Interbase 派生而来的。

优点
  • 数据库功能不受限制
  • 非常稳定,功能强大
  • 配置和使用简单

以下命令可以帮助你在 Ubuntu 机器上使用 Firebird:

$sudo apt-get update
$sudo apt-get install firebird2.5-superclassic

Cassandra

Cassandra 官网

Cassandra 是一个 Apache 基金会旗下的 NoSQL 数据库。它具有高度可扩展性、分布式、高性能的特点,可以很好地处理大量数据。其分布式的特性,使它没有单点故障。

优点
  • 高性能
  • 高可扩展性
  • 采用点对点架构

以下命令可以帮助你在 Ubuntu 机器上使用 Cassandra:

$curl https://www.apache.org/dist/cassandra/KEYS | sudo apt-key add -
$sudo apt-get update
$sudo apt-get install cassandra
$sudo systemctl enable cassandra
$sudo systemctl start cassandra

PostgreSQL

PostgreSQL 官网

如今,PostgreSQL 是最流行的开源关系数据库管理系统之一。它易于扩展,同时还与 SQL 兼容。这个数据库管理系统经过了 30 多年的积极开发。

优点
  • 与 MySQL 相比,Postgres 可以存储更多种类的数据
  • 支持几乎所有的 SQL 特性
  • 高度可扩展

下面的命令可以帮助你在 Ubuntu 机器上使用 PostgreSQL:

$sudo apt-get update
$sudo apt-get install postgresql postgresql-contrib

CockroachDB

CockroachDB 官网

CockroachDB 是一个为可靠性而生的数据库。它可以像 蟑螂 cockroach 一样在灾难性的情况下顽强生存、蓬勃发展。它可以处理大量的数据。还可以构建多集群数据库。

优点
  • 很容易部署
  • 高一致性
  • 分布式事务
  • 高可用性
  • 兼容 SQL

Redis

Redis 官网

Redis 是一个基于键值的开源 NoSQL 数据存储数据库。它支持各种类型的键,使用非常方便。

结语

我们已经浏览了最知名和最流行的开源数据库管理系统。了解这些不同的数据库非常有趣。尝试不同的选择,发现最适合你需求的数据库。另外,一定要查看这些数据库的官方文档。

(题图:MJ/40ba9f14-5948-431a-a899-36c6b1ff4dfe)


via: https://www.opensourceforu.com/2022/09/are-you-familiar-with-these-popular-open-source-databases/

作者:Jishnu Saurav Mittapalli 选题:lkxed 译者:toknow-gh 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出