Go GC:了解便利背后的开销

news2024/11/24 10:54:40

1. 简介

当今,移动互联网和人工智能的快(越)速(来)发(越)展(卷),对编程语言的高效性和便利性提出了更高的要求。Go作为一门高效、简洁、易于学习的编程语言,受到了越来越多开发者的青睐。

Go语言的垃圾回收机制(Garbage Collection,简称 GC)是其重要的运行机制之一,它可以帮助开发人员避免手动管理内存的复杂性和错误,为开发者带来开发上的便利,使开发者可以更专注于业务逻辑的实现。然而,GC的便利性背后也带来了一定的系统开销,作为成熟的Go开发者,我们需要了解GC带来的开销和优化方法,以帮助我们更好的了解和使用Go语言。

了解Go GC的原理是了解GC开销的前提条件,我们首先来简要看看Go GC的原理。

2. Go GC的简明原理

Go语言的垃圾回收器采用了并发三色标记清除算法(Concurrent Tri-Color Mark-And-Sweep),尽可能减少STW(stop the world)时间,以降低吞吐为代价换取低延迟,实现了高效的垃圾回收。

标记清除算法的基本原理是,垃圾回收器将所有的存活对象标记为“活”的,未被标记的对象则被认为是垃圾。经典的标记清除算法通常分为两个阶段:

  • 标记阶段:垃圾回收器从根对象开始,遍历所有可达对象,并将它们标记为“活”的。

  • 清除阶段:垃圾回收器从堆的起始地址开始遍历,将未被标记的对象清除,回收内存。

Go语言的垃圾回收器采用了三色标记法(Tri-Color Marking),将堆上的内存对象分为三种颜色:

  • 白色:未被标记为“活”的对象,是潜在的垃圾,后续可能会被GC回收。

  • 灰色:待扫描的对象,当扫描某个灰色对象时,GC会将其标记为黑色,然后将该对象指向的所有对象都标记为灰色,待后续标记。

  • 黑色:被标记为“活”的对象,在这轮GC中不会被回收。

垃圾回收器开始工作时不存在黑色对象,垃圾回收器会将根对象标记为灰色,并从根对象(通常是栈对象和全局对象)开始遍历。垃圾回收器会将灰色对象标记为黑色,并将该对象指向的对象标记为灰色。垃圾回收器重复这个过程,直到所有可达对象都被标记为黑色。最后,垃圾回收器清除所有未被标记为黑色的对象,即清除所有白色对象。

前面提到过,Go语言的GC采用了并发标记的技术,以减少GC对系统性能的影响。并发标记指的是在GC运行时程序仍然可以继续运行,而不必停止程序的执行。为了避免程序修改对象时对标记的影响,GC会利用混合写屏障技术,在对象被修改时进行特殊标记(若程序修改黑色对象(已被扫描完毕,不会再扫描),使之指向白色对象时,写屏障技术会将白色对象标记为灰色,避免白色对象被释放导致黑色对象出现悬挂指针的情况)。写屏障技术可以有效避免并发标记阶段的错误标记,但也会带来一定的性能开销

3. GC的开销

从上面的Go GC原理来看,GC在带来便利的同时,开销是不可避免的。

3.1 GC开销的主要来源

GC开销的主要来源包括以下几个:

  • STW时间

Go诞生初期,GC的实现不是很成熟,STW时间很长,这让很对想使用Go在生产上作为一番的开发人员打了“退堂鼓”。Go 1.5版本[1]自举后,GC的STW时间大幅下降,又经过几个版本的打磨后,STW时间已经被Go降低到很短了,通常情况下都在1毫秒以内,甚至可以到几十微秒,STW时间的大幅缩短让Go真正走进了生产环境。

不过再短的STW对于程序执行来说也是开销,因为STW期间,所有属于业务逻辑的代码都无法向前推进(make progress)。

那么一个GC周期究竟会做几次STW呢?这里借用“Go语言原本”[2]中的一个表格:

80f63fa7144df55f4107c6e1e189a530.png

这个表格描述了Go垃圾回收器主要包含的五个阶段,我们看到虽然采用了并发三色标记和清除,但在一次GC周期内,还是要有2次STW,一次是结束标记,关闭写屏障,另一次是为下一个周期的并发标记做准备,开启写屏障。

STW时间依然是GC开销的主要来源之一。减少STW时间对于优化GC的性能依然至关重要,尤其是任意场景下都要保证尽可能短暂的STW,但这是Go core团队的任务。

  • 标记与清除阶段的负荷

在标记与清除阶段,GC需要遍历堆内存中的所有对象,并进行标记和清除,这也是十分消耗cpu的工作。

  • 标记辅助

GC的并发标记并非只是由特定(dedicated) goroutine去完成的,为了保证GC标记清扫的速度不低于业务goroutine分配内存的速度,保证程序不因消耗内存过快过大而被OS OOM(Out Of Memory) Killed,GC引入标记辅助技术,即让每个业务goroutine都有机会参与到GC标记工作中来!并且,这种标记辅助采用的是一种补偿机制,即该业务goroutine分配的内存越多,它要辅助标记的内存就越多。一旦某个业务goroutine被“拉壮丁”执行标记辅助工作,那么该goroutine的业务执行就会暂停,业务逻辑也就无法向前推进。

  • 堆内存的释放

当Go GC回收了堆内存之后,如果堆的大小变得比之前小了,那么垃圾回收器会向操作系统归还多余的内存空间。在Linux等操作系统中,操作系统会将这些内存页标记为“未使用”,但是这些内存页并不会立即返回给操作系统,而是留给程序使用,以便程序将来再次申请内存时可以直接使用已经分配的内存页,从而减少内存分配的时间和开销。当程序没有使用这些内存页一段时间后,操作系统会将这些内存页回收,并将它们标记为“可用”,并在需要时重新分配给程序。这个过程是由操作系统的虚拟内存管理机制来完成的,具体的开销取决于操作系统的实现和硬件的性能等因素。

3.2 度量GC的开销

由于标记辅助技术的存在,单纯地从每个GC cycle的执行时间以及GC间隔时间来度量GC开销似乎就不那么准确了,更为直观的反映GC开销的是GC消耗cpu的占比

不过目前上没有特别好的工具可以特别直观且直接告诉你当前Go程序执行时GC CPU占用率。我们可以通过pprof工具或类似Pyroscope[3]这样的持续profiling的图形化工具来间接查看GC的cpu占用。

比如:通过Pyroscope提供的火焰图,查看runtime.gcBgMarkWorker(runtime后台专用的用于GC标记阶段的goroutine执行的函数)和runtime.gcAssistAlloc(标记辅助时调用的函数)的cpu消耗时间。

更为完整的Go runtime metrics指标,可以查看metrics包的文档[4]

注:GODEBUG=gctrace=1可以输出关于每个GC周期的详细信息,关于详细信息中各个字段的解读可以参见这里[5]。更高级的选手还可以使用Go execution tracer工具[6]来剖析GC的开销。

GC的CPU开销占比通常在25%以下,一旦超过这个负荷比例,就要考虑做调优了,Go保证GC cpu占用不会超过50%[7]

4. 优化GC的开销

优化GC的开销是提高系统性能和响应速度的重要手段。

前面我们分析了Go GC开销的主要来源。下面就针对每种来源说说优化开销的可能性与手段。

4.1 缩短STW时间

我们知道一旦GC STW后,所有业务逻辑都将暂停,这期间的CPU由GC 100%占用,降低STW时间是降低gc cpu占比的好方法。不过STW的算法是Go核心团队把控的,降低每个GC周期的STW时间也是Go核心团队的不二职责。从用户层面是很难影响到单次STW时间的。

不过,我们可以通过减少GC次数来间接减少STW次数,从而降低GC CPU占比。当然减少GC次数对后面的所有优化手段都有效,这是一个总开关。

那么如何减少GC次数呢?我们先来了解GC的触发时机。Go GC触发时机大体分为三种:

  • 手动触发:调用runtime.GC()

  • 常规触发:Target heap memory = Live heap + (Live heap + GC roots) * GOGC / 100

  • sysmon后台周期性强制触发GC

我们看到,这三种触发时机我们能干预的只有常规触发,而常规触发的公式中,可以调整的只有GOGC这个参数(等价于debug.SetGCPercent())。GOGC默认值为100,也就是说当新分配heap内存的数量是上一周期的活跃heap内存的一倍的时候,触发GC:

af344c9d4996c9bf76e0edd2ddcca13d.png

如果我们将GOGC改为200,那么GC的触发间隔将增加,频度会下降,CPU开销会降低(6.4%->3.8%),如下图:

2fbdb10b5d915f649fe2696c25f48b73.png

不过这是以整个程序的内存开销增大为代价的(40MB -> 60MB),并且对一般开发者而言,GOGC的值改起来确有风险,稍有不慎可能就会触发OMM killed。之前uber曾发表一篇文章,讲述了uber是如何通过在线自动调整GOGC参数来大幅降低CPU资源开销的[8],可以一看。

当然除了GOGC这一个唯一可调参数外,Go社区在降低GC频率方面也有自己的小妙招,比如之前经常使用的ballast(压舱石)技术[9]。其原理就是在程序初始化时先分配一块大内存:

func main() {

 // Create a large heap allocation of 10 GiB
 ballast := make([]byte, 10<<30)

 // Application execution continues
 // ...
 runtime.KeepAlive(ballast) // make sure the ballast won't be collected 
}

这块内存仅体现在VSZ中,即该程序进程的虚拟内存中,但并不占用程序进程的常驻内存(RSS)中。但一旦分配,Go GC就会将其算作是一个“活”堆内存对象,在计算下一次GC时就会将其作为上述公式中的live heap考量。如果ballast为10GB,那么GC就会在程序每新分配10GB内存时才会被触发。

注:RSS是这个进程目前在主内存(RAM)中拥有多少内存。VSZ是该进程总共有多少虚拟内存。

Go 1.19版本[10]引入了Soft memory limit[11],这个方案在runtime/debug包中添加了一个名为SetMemoryLimit的函数以及GOMEMLIMIT环境变量,通过他们任意一个都可以设定Go应用的Memory limit。

一旦设定了Memory limit,当Go堆大小达到“Memory limit减去非堆内存后的值”时,一轮GC会被触发。即便你手动关闭了GC(GOGC=off),GC亦会被触发。不过soft memory limit不保证不会出现oom-killed。并且如果一个Go应用的live heap object超过了soft memory limit但还尚未被kill,那么此时GC可能会被频繁触发,将大量消耗cpu资源:

69c1c1e23f21fb2a11da96ad6e5bf72f.png

但为了保证在这种情况下业务依然能继续进行,soft memory limit方案保证GC最多只会使用50%的CPU算力,以保证业务处理依然能够得到cpu资源。

那么多大的值是合理的soft memory limit值呢?在Go服务独占容器资源时,一个好的经验法则是留下额外的5-10%的空间。uber在其博客中设定的limit为资源上限的70%,也是一个不错的经验值。

Memory Limit被看作是Go官方的ballast替代方案,但还是不有所不同的。Memory limit只是规定了一个上限,如果未到memory limit,Go的常规GC还是会照例执行的。GOGC=off+ soft Memory limit下的行为特征与ballast更类似,不过将GC关掉的风险还是很大的,要三思而后行。

Go GC没有采用分代机制,每次都是FullGC,减少GC次数确是降低GC CPU开销的良方。不过除此之外,我们还有一个优化GC开销的方法,我们继续看。

4.2 减少堆内存的分配和释放

GC开销大的根源在于heap object多,Go的每轮GC都是FullGC,每轮都要将所有heap object标记(mark)一遍,即便大多数heap object都是长期alive的,因此,一个直观的降低GC开销的方法就是减少heap object的数量,即减少alloc

沿着这样的思路,我们可以很直接的想出如下两种手段:

  • 把小对象聚合到一个结构体中,然后做一次分配即可

这样不仅利于减少分配次数,还有利于减少堆内存碎片,提高堆内存的利用率。如果整个结构体中没有指针对象,那么结构体的分配与释放将更加高效,具体原因可参见我的《Go GC如何检测内存对象中是否包含指针》[12]一文。

  • 重用

Go GC开销优化的一个典型手段就是内存空间重用,即建立一个池子,需要的时候从池中申请,用完后再放回池子里,供其他goroutine重用。这个过程不再有分配与释放。

Go中最典型的重用的例子就是sync.Pool的使用,不过sync.Pool并非完全不做释放操作,它是在一定程度上提高了重用的比例罢了。

5. 小结

Go GC的自动内存管理减少了内存泄漏和悬挂指针等问题。然而,GC给开发者带来便利的同时,开销也是不可避免的,它会对系统的性能和响应速度产生影响。Go开发者需要了解这些开销。

在本文中,我们介绍了GC的基本原理、GC的开销及其主要来源,并提供了优化GC开销的一些方法。

然而,要想有效地利用 GC,开发者需要了解其内部机制和算法,并根据实际情况进行调优。

除了通过GC参数降低GC频率外,在实际编码过程中,开发者还应该尽可能地减少对象的分配以降低Go每轮FullGC扫描对象的数量。

GC的优化是一项长期的工作。开发者应该不断地监控系统的性能和行为,并根据需要进行调整和优化,以确保系统的性能和响应速度始终保持在最佳状态。

6. 参考资料

  • A Guide to the Go Garbage Collector[13] - https://go.dev/doc/gc-guide

  • Go GC的过去、现在与未来[14] - https://golang.design/under-the-hood/zh-cn/part2runtime/ch08gc/history/

  • Go memory ballast: How I learned to stop worrying and love the heap[15] - https://blog.twitch.tv/en/2019/04/10/go-memory-ballast-how-i-learnt-to-stop-worrying-and-love-the-heap/


“Gopher部落”知识星球[16]旨在打造一个精品Go学习和进阶社群!高品质首发Go技术文章,“三天”首发阅读权,每年两期Go语言发展现状分析,每天提前1小时阅读到新鲜的Gopher日报,网课、技术专栏、图书内容前瞻,六小时内必答保证等满足你关于Go语言生态的所有需求!2023年,Gopher部落将进一步聚焦于如何编写雅、地道、可读、可测试的Go代码,关注代码质量并深入理解Go核心技术,并继续加强与星友的互动。欢迎大家加入!

608ede5b334f5a3e992b3d3481ed6ad0.png

587311c6e62646e936db7dee6c3bea25.png

2f25ede0ca3774a9e6898a33f8583602.png

f6b922aa6e17f2fca33624df3f1db0b0.jpeg

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址[17]:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻)归档仓库 - https://github.com/bigwhite/gopherdaily

我的联系方式:

  • 微博(暂不可用):https://weibo.com/bigwhite20xx

  • 微博2:https://weibo.com/u/6484441286

  • 博客:tonybai.com

  • github: https://github.com/bigwhite

aa7d278403dbf39b0051c1395d642dd3.png

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

参考资料

[1] 

Go 1.5版本: https://tonybai.com/2015/07/10/some-changes-in-go-1-5/

[2] 

“Go语言原本”: https://golang.design/under-the-hood/zh-cn/part2runtime/ch08gc/basic/

[3] 

Pyroscope: https://pyroscope.io/docs/golang/

[4] 

metrics包的文档: https://pkg.go.dev/runtime/metrics

[5] 

这里: https://pkg.go.dev/runtime

[6] 

Go execution tracer工具: https://tonybai.com/2021/06/28/understand-go-execution-tracer-by-example

[7] 

Go保证GC cpu占用不会超过50%: https://go.dev/doc/gc-guide

[8] 

uber是如何通过在线自动调整GOGC参数来大幅降低CPU资源开销的: https://www.uber.com/en-KR/blog/how-we-saved-70k-cores-across-30-mission-critical-services/

[9] 

ballast(压舱石)技术: https://medium.com/twitch-news/go-memory-ballast-how-i-learnt-to-stop-worrying-and-love-the-heap-26c2462549a2

[10] 

Go 1.19版本: https://tonybai.com/2022/08/22/some-changes-in-go-1-19

[11] 

Soft memory limit: https://github.com/golang/proposal/blob/master/design/48409-soft-memory-limit.md

[12] 

《Go GC如何检测内存对象中是否包含指针》: https://tonybai.com/2022/02/21/how-gc-detect-pointer-in-mem-obj

[13] 

A Guide to the Go Garbage Collector: https://go.dev/doc/gc-guide

[14] 

Go GC的过去、现在与未来: https://golang.design/under-the-hood/zh-cn/part2runtime/ch08gc/history/

[15] 

Go memory ballast: How I learned to stop worrying and love the heap: https://blog.twitch.tv/en/2019/04/10/go-memory-ballast-how-i-learnt-to-stop-worrying-and-love-the-heap/

[16] 

“Gopher部落”知识星球: https://wx.zsxq.com/dweb2/index/group/51284458844544

[17] 

链接地址: https://m.do.co/c/bff6eed92687

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

client-go的Indexer三部曲之一:基本功能

关于《client-go的Indexer三部曲》系列 该系列是《client-go实战系列》的子系列文章&#xff0c;共三篇内容&#xff0c;分别从功能、性能、源码三个角度对client-go内部的Indexer组件进行说明&#xff0c;目标是与大家一同学习Indexer&#xff0c;并掌握如何在开发中通过Inde…

EBU5476 Microprocessor System Design 知识点总结_6 Serial Communication

Serial Communication 串口通信&#xff0c;一种发送消息的通信方式。 串&#xff0c;指的是发数据的方式&#xff1a;一位一位串行发&#xff0c;并行是可能有多路通道&#xff0c;每路同时发一个数据&#xff0c;多路同时到达。 串口通信有单工 Simplex&#xff0c;半双工…

基于SpringBoot+Vue的乐校园二手书交易管理系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

35. 应用监控【监控端点健康信息】

1、展示健康信息详情 开发者可以通过查看健康信息来获取应用的运行数据&#xff0c;进而提早发现应用问题&#xff0c;提早解决&#xff0c; 免造成损失。默认情况下开发者只能获取 status 信息&#xff08;见图 1 &#xff09;&#xff0c;这是因为 detail 信息默认不显示&…

【Java常见面试题】Spring篇

导航&#xff1a; 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线常见面试题 目录 1、简单介绍Spring 2、说说你对IOC的理解 3、说说你对AOP的理解 4、说说Bean的生命周期 5、说说循环依赖和三级缓存 6、说说Bean的几种…

DataV图表-排名轮播表自定义

DataV图表-排名轮播表自定义数据大屏可视化 场景&#xff1a;需要计算根据分数不同柱子的颜色不同 低于60分变成为橙色柱子 一开始使用的是 dv-scroll-ranking-board 这个不可以自定义颜色和属性 我们可以更改 dv-scroll-board 样式来实现 排名轮播表 安装 data-view npm ins…

如何使用Leangoo领歌管理敏捷缺陷

缺陷管理通常关注如下几个方面&#xff1a; 1. 缺陷的处理速度 2. 缺陷处理的状态 3. 缺陷的分布 4. 缺陷产生的原因 使用​​​​​​​Leangoo领歌敏捷工具​​​​​​​我们可以对缺陷进行可视化的管理&#xff0c;方便我们对缺陷的处理进展、负责人、当前状态、分布情…

『 MySQL篇 』:MySQL 锁机制介绍

目录 一. 概述 二. 全局锁 三 . 表级锁 三. 行级锁 一. 概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;除传统的计算资源&#xff08;CPU、RAM、I/O&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据…

三菱FX5U通讯、定位、伺服32讲

三菱FX5U系列&#xff08;现在已经升级改成为MELSEC iQ-F系列&#xff09;PLC的CPU模块中内置了能够支持各种控制的优异功能&#xff0c;全系标配Ethernet端口、RS-485端口、SD存储卡槽。Ethernet端口可支持CC-Link IE现场网络Basic&#xff0c;因此能连接多种多样的设备。 第一…

eChart折线图动态特效和隔几秒高亮特效

示例&#xff1a; 说明&#xff1a; 因为现在公司经常要做大屏可视化特效&#xff0c;没办法&#xff0c;只能让图尽量动起来&#xff08;之前开会挨叼了&#xff0c;说俺们深圳做的&#xff0c;不能比西安那些人做的差。。。&#xff09; 主要代码&#xff1a; 折线图的滚呀滚…

基于Hexo和Butterfly创建个人技术博客,(7) 配置butterfly主题搭建博客网站主体UI框架

Butterfly官方网站&#xff0c;请 点击进入。 本文面向使用 butterfly theme 的用户, 主题安装方法可查看基于Hexo和Butterfly创建个人技术博客&#xff0c;(1) 初始化博客站点 这章内容。 一、概述 1、什么是theme? Hexo可以认为是一个基础框架&#xff0c;主要提供渲染和插…

平行云——开启通往元宇宙的通道

元宇宙是平行于真实世界的虚拟世界&#xff0c;是新一代互联网。具有真三维、可交互、可沉浸特性的XR&#xff0c;是构建元宇宙的终极数字媒体形态。如何打破XR终端设备与XR内容之间的紧耦合&#xff0c;实现任意平台、任意终端的线上访问&#xff0c;Cloud XR是其必由之路&…

Diffie-Hellman Key Agreement Protocol 资源管理错误漏洞(CVE-2002-20001)

详细描述: Diffie-Hellman Key Agreement Protocol是一种密钥协商协议。它最初在 Diffie 和 Hellman 关于公钥密码学的开创性论文中有所描述。该密钥协商协议允许 Alice 和 Bob 交换公钥值&#xff0c;并根据这些值和他们自己对应的私钥的知识&#xff0c;安全地计算共享密钥K…

C语言柔型数组

何为柔性数组 所谓柔性数组&#xff0c;是C语言中的一个概念&#xff0c;也叫零长数组。顾名思义&#xff0c;这个数组的长度是不固定的&#xff0c;当没有值时&#xff0c;它的sizeof长度为0。 我们一般这样定义一个柔性数组&#xff1a; struct buffer_t {int len;char buf…

FasterTransformer 002: cuda调试env

VSCODE ENV cmake NVIDIA Nsight Systems 当我们装好了CUDA的时候&#xff0c;其实在图形界面下已经装好了一个叫“nsight”的编译器&#xff0c;我们可以直接用终端打开这个编译器&#xff0c;然后写好程序直接编译然后debug就可以了。WINDOWS NVIDIA Nsight Systems 入门及…

【ARM AMBA APB 入门 1 -- APB总线介绍】

文章目录 APB 总线历史1.1 APB 总线介绍1.1.1 APB 使用场景1.1.2 APB 信号列表1.1.3 APB 状态机 1.2 APB 传输时序1.2.1 APB 写传输时序1.2.1.1 Write transfer with no wait states1.2.1.2 Write transfer with wait states 1.2.2 APB 读时序1.2.2.1 Read transfer with no wa…

C语言二级指针复习

之前写过一篇二级指针的博文&#xff0c;C语言二级指针Demo - Win32 版本_bcbobo21cn的博客-CSDN博客 下面复习一下二级指针&#xff1b; 二级指针的概念是这样&#xff0c; int a 100; int *p1 &a; int **p2 &p1; 有一个整型变量a被赋值100&#xff1b;…

【Python开发】FastAPI 10:SQL 数据库操作

在 FastAPI 中使用 SQL 数据库可以使用多个 ORM 工具&#xff0c;例如 SQLAlchemy、Tortoise ORM 等&#xff0c;类似 Java 的 Mybatis 。这些 ORM 工具可以帮助我们方便地与关系型数据库进行交互&#xff0c;如 MySQL 、PostgreSQL等。本篇文章将介绍如何使用 SQLAlchemy 来完…

osgb倾斜摄影三维模型数据web端在线管理平台,一键查看、分享

「四维轻云」是基于浏览器打造的一款osgb倾斜摄影三维模型数据web端在线管理平台&#xff0c;为用户提供了项目管理、团队管理、空间测量、场景编辑、在线标绘等功能&#xff0c;实现了osgb倾斜摄影三维模型数据在线管理、浏览和分享。 此外&#xff0c;为了更好地满足用户需求…

数据库信息速递 AWS因迁移PostgreSQL DBaaS而遭遇长时间停机时间而备受诟病

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…