Jemalloc内存分配与优化实践

Linux阅码场 2023-05-30 08:01

前言

C++ 语言中提供了大量的类库和编程接口,虽然可以帮助开发者提升研发效率,但在特定场景下,其性能表现仍存在优化空间。开发者往往追求极致的代码性能逻辑,一点点的优化改变就可以帮助业务获得良好的性能收益。在字节降本提效的过程中,STE 团队在算力监控系统中发现 Jemalloc 是业务的前五大 CPU 热点基础库,具有很高的潜在性能优化空间。因此,从 2019 年开始对 Jemalloc 进行深度优化,并在字节内部进行了大范围的优化落地,帮助业务团队取得了较好的收益。本文将主要介绍 Jemalloc 的基本原理以及一些简单易用的优化方法,帮助开发者在 Jemalloc 的实际应用中,获得更好的性能表现。


内存相关概念简介

Linux内存分配与分配器

当代 Linux 系统中可以同时运行多种多样的进程,并且进程之间可以做到内存互相隔离,这得益于 Linux 的进程地址空间管理。


一个进程的地址空间中,包含了静态内存、以及动态内存(常说的堆栈),栈的动态分配和释放由编译器完成,对于堆上内存,Linux 提供了 brk、sbrk、mmap、munmap 等系统调用来进行内存分配和释放,但是这些函数的直接使用会带来不小的理解门槛和使用复杂性,如 brk 需要指定堆的上界地址,容易出现内存错误;mmap 直接申请 pagesize 为单位的内存,对于小于此内存的分配会造成极大的内存浪费。因此需要有内存分配器来辅助管理堆的动态申请和释放。


通常内存分配器如 ptmalloc提供了 malloc 等函数来进行内存的分配,free 进行内存释放,这些函数在底层调用了 brk、mmap 等函数申请内存,并以地址的形式返回给用户,用户在 malloc、free 匹配的情况下不必担心在分配和释放时出现内存错误或者内存浪费。


内存碎片

虽然内存分配器在一定程度上保证了内存的利用率,但是不可避免地会出现内存碎片,包括了内存页内碎片和内存页间碎片,碎片的产生会导致部分内存不可用,内存碎片的大小也是评估一个内存分配器好坏的重要指标。


常见的内存分配管理算法

堆上内存以链式形式存在,最简单的动态内存分配算法有:

  • First fit:寻找找第一个满足请求 size 的内存块做分配

  • Next fit:从当前分配的地址开始,寻找下一个满足请求 size 的空闲块

  • best fist:对空闲块进行排序,然后找第一个满足要求的空闲块

另外还有 Buddy 算法和 Slab 算法,也是 jemalloc 中用到的核心算法:


Buddy allocation


Buddy 算法简单来说如上图,一般 2 的 n 次幂大小来管理内存,当申请的内存 size 较小,且当前空闲内存块均大于 size 的两倍,那么会将较大的块分裂,直到分裂出大于size,并小于 size * 2的块为止;当内存 size 较大时则相反,会将空闲块不断合并。


Buddy 算法没有块间内存碎片,但是块内内存碎片较大,可以看到当申请 2KB+1B 的 size 时,需要用 4KB 的内存块,内存碎片最坏情况可达 50%。


Slab allocation

调用 Linux 系统调用进行内存的分配和释放会让程序陷入内核态,带来不小的性能开销,slab 算法应运而生。每个 slab 都是一块连续内存,并将其划分成大小相同的 slots,用 bitmap 来记录这些 slots 的空闲情况,内存分配时,返回一个 bitmap 中记录的空闲块,释放时,将其记录忙碌即可,而 slab size 和 slot size 是内存碎片大小的关键。


Jemalloc简介

Jemalloc 是 malloc(3) 的实现,在现代多线程、高并发的互联网应用中,有良好的性能表现,并提供了优秀的内存分析功能。


Jemalloc 主要有以下几个特点:
  • 高效地分配和释放内存,可以有效提升程序的运行速度,并且节省 CPU 资源
  • 尽量少的内存碎片,一个长稳运行地程序如果不控制内存碎片的产生,那么可以预见地这个程序会在某一时刻崩溃,限制了程序的运行生命周期
  • 支持堆的 profiling,可以有效地用来分析内存问题
  • 支持多样化的参数,可以针对自身地程序特点来定制运行时 Jemalloc 各个模块大小,以获得最优的性能和资源占用比

下文主要介绍了 Jemalloc 的内存分配算法、数据结构,以及一些针对具体程序的优化实践和建议。


Jemalloc核心算法与数据结构

Jemalloc 整体的算法和数据结构基于高效和低内存碎片的原则进行设计,主要体现在:
  • 隔离了大 Size 和小 Size 的内存分配(区分默认阈值为 3.5 个 Pagesize),可以有效地减少内存碎片
  • 在内存重用时默认使用低地址,并将内存控制在尽量少的内存页上
  • 制定 size class 和 slab class,以便减少内存碎片
  • 严格限制 Jemalloc 自身的元数据大小
  • 用一定数量的 arena 来管理内存的单元,每个 arena 管理相当数量的线程,arena 之间独立,尽量减少多线程时锁竞争

我们来看下 Jemalloc 是如何来实现这些特性的。


Extent

Jemalloc 的内存管理结合了 buddy 算法和 slab 算法。Jemalloc 引入 extent 的概念,extent 是 arena 管理的内存对象,在 large size 的 allocation 中充当 buddy 算法中的 chunk,small size allocation 中,充当 slab。


每个 extent 的大小是 Pagesize 的整数倍,不同 size 的 extent 会用 buddy 算法来进行拆分和合并,大内存的分配会直接使用一整个的 extent 来存储。小内存的分配使用的是 slab 算法,slab size 的计算规则为 size 和 pagesize 的最小公倍数,因此每个extent总是可以存储整数倍个对应 size。


extent 本身设置 bitmap,来记录内存占用情况,以及自身的各种属性,同类型的 extents 用 paring heap 存储。


此外,arena 将 extent 分为多种类型,有当前正在使用未被填满的extent,有一段时间未使用的dirty extent,还有长时间未使用的muzzy extent,以及开启retained功能后的retained extent,extent分类的作用相当于多级缓存,当线程内存分配压力较小时,空余的extent会被缓存,以备压力增大时使用,可以避免与操作系统的交互。


Small size align and Slab size

为了减少页内内存碎片,Jemalloc 对 small size 进行了对齐,对于每一个 size,以二进制的视角来看,将其分为两个数:group、mod。group 表示 size 的二进制最高位,如果 size 正好为 2 的幂次,则将其分在上一个 group 中;mod 表示最高位的后两位,有 0、1、2、3 共 4 种可能。这样构成的 align 后的 size 在同一个 group 中步长(即两个相邻 mod 计算得到的 size 之间的差值)相同,group 越大,步长会呈 2 的倍数增长。


如下图,框中的 4个是同一个 group 中 4 种 mod 在 align 后的 size,其中 160 表示包含了 129B 到 160B 在对齐后的大小:

计算出 aligned size 后,就需要计算 slab size,每个 slab size 为 pagesize 和 aligned size 的最小公倍数,以防止跨 slab 的 size 或者 slab 无法被填满的情况出现。以 4K page 为例,128B 的 slab size 即 4K,160B 的 slab size 为 20K。


Tcache and arena

为了减少多线程下锁的竞争,Jemalloc 参考 lkmalloc 和 tcmalloc,实现了一套由多个 arena 独立管理内存加 thread cache 的机制,形成 tcache 有空余空间时不需要加锁分配,没有空余空间时将锁控制在线程所属 arena 管理的几个线程之间的模式。

tcache 中每一个 size 对应一个 bin,当 tcache 需要填充时,在 arena 中发生的如下图:


allocation/dallocation in tcache

tcache 以 thread local storage对象的形式存储,主要服务于 small size 和一小部分 large size。


当 tcache 中有空闲时,一次 malloc 的过程很简单:
  1. 对 size 做 align 得到 usize
  2. 查找 usize 对应的 bin,bin 为 tcache 中针对不同 size 设置的 slots
  3. bin 有空闲地址则直接返回,没有空闲地址则会向 arena 请求填充

每个 bin 的结构如下图,avail 指向 bin 的起始地址,ncached 初始为 bin 的最大值 ncached_max (与 slab size 相关,最小为 20 最大为 200),每次申请内存会返回 ncached 指向的地址并自减1,直到小于限制值。

释放的时候相反,当 tcache 不为空,即 ncached 不等于 bin 的 ncached_max 时,ncached 自加1,并且将 free 的地址填入 bin 中。


Tcache fill

上面的 allocation 过程是 tcache 中有足够的空闲块供分配,当 tcache 中已经没有空闲块时,会向其所属的 arena 申请 fill,此时 arena 中会加锁去分级 extent 取空闲块,并把当前使用的 extent 移入full extent。


Tcache flush

当 dallocate 触发 tcache 中又没有分配任何内存,即 ncached_max 等于 ncached_max 时,tcache 会触发 flush,flush 会将 tcache 中一半的内存释放回原 extent,即将 tache 的可用空间压缩到原来的一半,这个过程中也会加对应 extent 的锁以保证同步。


Jemalloc优化思路

从上一章节可以看到,jemalloc 对于内存用的是多级缓存的思路,tcache 的代价最小,无须加锁可以直接返回;其次是 arena 的 bin->extent,锁的粒度在对应的 bin 上,会是 bin 对应的 size 在这个 arena 中无法再做 fill 或 flush;然后是 dirty extent、muzzy extent,这部分是 arena 全局加锁,会锁住其他线程的 fill 或者 purge,那么在多线程下,我们可以用几个思路来优化锁的竞争。


arena优化

从上一章节可知,jemalloc 将锁的范围都控制在 arena 中,每个 arena 会管理一系列线程,线程在 arena 中是平均分配的,arena 默认数量是 CPU 个数 * 4。因此,当我们在一台 8 核的机器上运行 256 个线程时,意味着每个arena 需要管理 8 个线程,这些线程在内存任务繁重时会产生严重的锁竞争,从而影响性能。此时可选择使用 malloc_conf:narenas:128,增加 arena 数量到 128 个,每个 arena 只需管理 2 个线程,线程之间产生锁竞争的概率就会大大减小。


此外还可以选择用 mallocx 隔离线程,让内存分配任务较重的线程独占 arena。


Slab size优化

Slab size 的大小如上所述,为 usize 大小和 pagesize 的最小公倍数,这一机制可以保证减少内存碎片,但是tcache 的 fill 与 flush 都与 slab size 相关,一个和业务内存模型匹配的 slab class 才可以得到最好的性能效果。


下面是一张 jemalloc 和 ptmalloc 的对比图,可以看到在 1024 以下的性能 jemalloc 都优于 ptmalloc,但是jemalloc 自身的性能明显存在波动,几个波动出现在 128B、256B、512B 以及 1024B 周围,因为这些 size 本身就是 pagesize 的因子或者公因子较多,所以 slab size 占用的 page 数也相对较少,fill 和 flush 所需要的slab数也越多。

dirty decay & muzzy decay

尽管我们希望将所有的 malloc、free 内存都可以放在 tcache 中或者 bin 中,这样可以最大化执行效率,但是实际的程序中这很难做到,因为每个线程都需要增加内存,会造成不小的内存压力,而且内存的申请释放往往会有波峰,dirty extents 和 muzzy extents 就可以来应对这些内存申请的波峰,而避免需要转入内核态来重新申请内存页。


dirty_decay_ms 和 muzzy_decay_ms 是 jemalloc 中用来控制长时间空闲内存衰变的时间参数,适当地扩大 dirty decay 的时间可以有效地解决性能劣化的尖刺。


Tcache ncached_max

tcache 中每一个 bin 的 slots 数量由 ncached_max 决定,当 tcache 中 ncached_max 耗尽时会触发 arena 的 fill  tcache 而产生锁,而 ncached_max 的大小默认为 2 * slab size,最小为 20,最大为 200,适当地扩大 ncached_max 值可以在一些线程上形成更优的 allocation/deallocation 循环(5.3版本已支持用malloc_conf进行更改)。


优化方法:调优三板斧

结合以上优化思路,通过以下步骤对应用进行调优:


Dump stats

在 long exist 的程序中可调用 jemalloc 的 malloc_stats_print 函数,dump 出应用当前内存分配信息:

// reference: https://jemalloc.net/jemalloc.3.htmlvoid malloc_stats_print(void (*write_cb)(void *, const char *), // 回调函数,可以写入文件                        void *cbopaque, // 回调函数参数                        const char *opts); // stats的一些选项,如"J"是导出json格式

或通过设置 malloc_conf,在程序运行结束后自动 dump stats:

export MALLOC_CONF=stats_print:true
stats 分析

用 Json 格式 dump stats 后,可以得到如下图所示结构的 json 文件:

各字段含义可参考:
https://jemalloc.net/jemalloc.3.html


按上一章节思路,可主要关注以下几点:
(1)arena 数量与 threads 数量比例
  • arena 数:jemalloc->arenas->narenas
  • threads 数:jemalloc->stats.arenas->merged->nthreads

分析:

threads : arenas 比例代表了单个 arena 中管理的线程数,将 malloc、free 较多,并且有可能产生竞争的线程尽量独占 arena。


(2)各个 extent 中 mutex 开销
  • jemalloc->stats.arenas->merged->mutexes

分析

该节点中的 mutex 操作次数、等锁时间可以反映出该类型 extent 的锁竞争程度,若 extent_retained 锁竞争严重,可适当调大 muzzy_decay_ms;同理,当 extents_muzzy 锁竞争严重,可适当调大 diry_decay_ms;extents_dirty 锁竞争严重,可适当调大 ncached_max,让malloc 尽量可以在 tcache 中完成


(3)arena 中各个 bin 的 malloc、free 次数
  • jemalloc->stats.arenas->merged->bins

分析

bin 中的 nfills 可以反映该 slab 填充的次数,针对 regions 本身较少,nfill 次数又多的 size,如 521B、1024B、2048B、4096B 等,可适当调大 slab size 来减小开销


添加MALLOC_CONF参数或修改代码

MALLOC_CONF 是 jemalloc 中用来动态设置参数的途径,无须重新编译二进制,可以通过 MALLOC_CONF 环境变量或者 /etc/malloc_conf 软链接形式设置,参数之间用 ',' 分割。除需要使用线程独占的 arena 外,以上其他优化均可通过 MALLOC_CONF 配置来完成。


(1)arena优化方法
narenas 设置:
export MALLOC_CONF=narenas:xxx  # xxx最大为1024

ln -s "narenas:xxx" /etc/malloc_conf

设置线程独占的 arena:

unsigned thread_set_je_exclusive_arena() {  unsigned arena_old, arena_new;  size_t sz = sizeof(unsigned);
/* Bind to a manual arena. */ if (mallctl("arenas.create", &arena_new, &sz, NULL, 0)) { std::cout << "Jemalloc arena create error\n"; return 0; } if (mallctl("thread.arena", &arena_old, &sz, &arena_new, sizeof(arena_new))) { std::cout << "Thread bind to jemalloc arena error\n"; return 0; } return arena_new;}


(2)各类大小优化方法

dirty extents:

export MALLOC_CONF=dirty_decay_ms:xxx  # -1为不释放dirty extents,易发生OOM

muzzy extents:

export MALLOC_CONF=muzzy_decay_ms:xxx  # -1为不释放muzzy extents,易发生OOM

tcache ncached_max 调整,ncached_max 与 slab size 相关,计算方式为

(slab_size / region_size) << lg_tcache_nslots_mul (默认值1)
最大限值为 tcache_nslots_small_max(默认200),最小限值为 tcache_nslots_small_min(默认20)。


如调整 32B 的 ncached_max,当前系统 page size 为 4K,计算默认的 ncached_max 的方法:
(slab_size / region_size) << lg_tcache_nslots_mul = (4096 / 32) << 1 = 256
超过了 tcache_nslots_small_max,所以 32B 的 ncache_max 默认即为 200。


调整 ncached_max 默认值相关参数:
export MALLOC_CONF=tcache_nslots_small_min:xxx,tcache_nslots_small_max:xxx,lg_tcache_nslots_mul:xxx

Slab size 设置方法:

export MALLOC_CONF="slab_sizes:1-4096:17|100-200:1|128-128:2" # -左右表示size范围,:后设置page数,|分割各个不同的size范围


字节业务优化案例

Jemalloc 的 stats dump 已经集成到监控系统中,经过分析发现,字节内部的应用普遍线程数量较多,在 arena 中的锁竞争比较激烈,并且 allocte/deallocte 集中在某些线程中,因此可以通过让核心线程独占 arena 来完成优化。以其中一个业务在平台上的 stats 数据为例:

可以看到进程总线程数为 1776 个,arenas 数量为 256 个,平均每个 arena 中的内存需要有 7-8 个线程共享,再查看 mutexs 的 stats :

可以看到在 extents 中产生锁的开销并不小,首先选择扩大 arenas 的数量,从 256 扩大到 1024 个,发现 CPU 相对下降了 4.5%,但是相对的内存上涨了 10%,在分析代码后,发现 allocate/deallocate 较多的线程总数量只有80+,针对这些线程通过 mallctl 单独创建了 arena,并绑定 tcache,并调小其他线程的 muzzy_decay_ms,最终为该业务节省了 4% 的 CPU 收益,内存基本持平。


总结

最好的基础库总是通用的,最适合的基础库总是最个性化的。对于 jemalloc 在业务上的优化与实践,STE团队进行不断探索,采集内存信息并进行平台化展示,以便业务及时发现自身程序在 jemalloc 上的性能瓶颈,并做出针对性地调优,目前已在 10+ 业务上进行参数优化平均帮助各业务团队节省了 3% 的 CPU(jemalloc 在部分业务中平均占用 10% ~ 15% 的CPU)。未来 STE 团队将继续深入 jemalloc 性能优化,探索定制化的业务内存分配和管理方案,以获得更好的优化成果。


往期精彩

DPDK内存碎片优化,性能最高提升30+倍!

万字长文,GPU Render Engine 详细介绍

DPDK Graph Pipeline框架简介与实现原理

字节跳动算力监控系统的落地与实践

JVM 内存使用大起底

字节跳动在PGO反馈优化技术上的探索与实践
内核优化之 PSI 篇:快速发现性能瓶颈,提高资源利用率
探索Mac mini M1的QEMU/KVM虚拟化实现
字节跳动提出KVM内核热升级方案,效率提升5.25倍!
安全容器文件服务 Virtio-fs 的高可用实践
字节跳动开源高性能C++ JSON库sonic-cpp
深入浅出 Sanitizer Interceptor 机制
eBPF 技术实践:加速容器网络转发,耗时降低60%+
十年磨一剑,veLinux深度解读


关于STE团队

字节跳动STE团队System Technologies&Engineering,系统技术与工程),一直致力于操作系统内核与虚拟化、系统基础软件与基础库的构建和性能优化、超大规模数据中心的系统稳定性和可靠性建设、新硬件与软件的协同设计等基础技术领域的研发与工程化落地,具备全面的基础软件工程能力,为字节上层业务保驾护航。同时,团队积极关注社区技术动向,拥抱开源和标准,欢迎更多同学加入我们,一起交流学习。

Linux阅码场 专业的Linux技术社区和Linux操作系统学习平台,内容涉及Linux内核,Linux内存管理,Linux进程管理,Linux文件系统和IO,Linux性能调优,Linux设备驱动以及Linux虚拟化和云计算等各方各面.
评论
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 325浏览
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 206浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 135浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 181浏览
  • 故障现象 一辆2007款日产天籁车,搭载VQ23发动机(气缸编号如图1所示,点火顺序为1-2-3-4-5-6),累计行驶里程约为21万km。车主反映,该车起步加速时偶尔抖动,且行驶中加速无力。 图1 VQ23发动机的气缸编号 故障诊断接车后试车,发动机怠速运转平稳,但只要换挡起步,稍微踩下一点加速踏板,就能感觉到车身明显抖动。用故障检测仪检测,发动机控制模块(ECM)无故障代码存储,且无失火数据流。用虹科Pico汽车示波器测量气缸1点火信号(COP点火信号)和曲轴位置传感器信
    虹科Pico汽车示波器 2025-01-23 10:46 82浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 195浏览
  • 飞凌嵌入式基于瑞芯微RK3562系列处理器打造的FET3562J-C全国产核心板,是一款专为工业自动化及消费类电子设备设计的产品,凭借其强大的功能和灵活性,自上市以来得到了各行业客户的广泛关注。本文将详细介绍如何启动并测试RK3562J处理器的MCU,通过实际操作步骤,帮助各位工程师朋友更好地了解这款芯片。1、RK3562J处理器概述RK3562J处理器采用了4*Cortex-A53@1.8GHz+Cortex-M0@200MHz架构。其中,4个Cortex-A53核心作为主要核心,负责处理复杂
    飞凌嵌入式 2025-01-24 11:21 50浏览
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 630浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 210浏览
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 159浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 123浏览
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 148浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 671浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦