深入浅析Linux Perf 性能分析工具及火焰图
Perf Event 子系统
Perf
是内置于 Linux 内核源码树中的性能剖析(profiling)工具。它基于事件采样的原理,以性能事件为基础,支持针对处理器相关性能指标与操作系统相关性能指标的性能剖析。可用于性能瓶颈的查找与热点代码的定位。
本文将详细介绍 Linux Perf 的工作模式、Perf Events 的分类、Perf Tool 工具集以及火焰图的相关内容。
下图展示了Perf的整体架构。
Linux Perf 共由两部分组成:
- Perf Tools:用户态的 Perf Tools 为用户提供了一系列丰富的工具集用于收集、分析性能数据。
- Perf Event Subsystem:Perf Event 子系统是内核众多子系统中的一员,其主要功能是和 Perf Tool 共同完成数据采集的工作。另外,Linux Hard Lockup Detector 也是通过 Perf Event 子系统来实现的。
Perf 工作模式
1. Couting Mode
Counting Mode 将会精确统计一段时间内 CPU 相关硬件计数器数值的变化。为了统计用户感兴趣的事件,Perf Tool 将设置性能控制相关的寄存器。这些寄存器的值将在监控周期结束后被读出。典型工具:Perf Stat。
2. Sampling Mode
Sampling Mode 将以定期采样方式获取性能数据。PMU 计数器将为某些特定事件配置溢出周期。当计数器溢出时,相关数据,如 IP、通用寄存器、EFLAG 将会被捕捉到。典型工具:Perf Record。
Perf Events分类
Couting 事件
# CPU counter statistics for the specified command:
perf stat command# CPU counter statistics for the specified PID, until Ctrl-C:
perf stat -p PID# CPU counter statistics for the entire system, for 5 seconds:
perf stat -a sleep 5# Various basic CPU statistics, system wide, for 10 seconds:
perf stat -e cycles,instructions,cache-references,cache-misses,bus-cycles -a sleep 10# Various CPU level 1 data cache statistics for the specified command:
perf stat -e L1-dcache-loads,L1-dcache-load-misses,L1-dcache-stores command# Various CPU data TLB statistics for the specified command:
perf stat -e dTLB-loads,dTLB-load-misses,dTLB-prefetch-misses command# Various CPU last level cache statistics for the specified command:
perf stat -e LLC-loads,LLC-load-misses,LLC-stores,LLC-prefetches command# Count syscalls per-second system-wide:
perf stat -e raw_syscalls:sys_enter -I 1000 -a# Count system calls by type for the specified PID, until Ctrl-C:
perf stat -e 'syscalls:sys_enter_*' -p PID# Count system calls by type for the entire system, for 5 seconds:
perf stat -e 'syscalls:sys_enter_*' -a sleep 5# Count scheduler events for the specified PID, until Ctrl-C:
perf stat -e 'sched:*' -p PID# Count scheduler events for the specified PID, for 10 seconds:
perf stat -e 'sched:*' -p PID sleep 10# Count ext4 events for the entire system, for 10 seconds:
perf stat -e 'ext4:*' -a sleep 10# Count block device I/O events for the entire system, for 10 seconds:
perf stat -e 'block:*' -a sleep 10
Profiling 事件
# Sample on-CPU functions for the specified command, at 99 Hertz:
perf record -F 99 command# Sample on-CPU functions for the specified PID, at 99 Hertz, until Ctrl-C:
perf record -F 99 -p PID# Sample on-CPU functions for the specified PID, at 99 Hertz, for 10 seconds:
perf record -F 99 -p PID sleep 10# Sample CPU stack traces (via frame pointers) for the specified PID, at 99 Hertz, for 10 seconds:
perf record -F 99 -p PID -g -- sleep 10# Sample CPU stack traces for the entire system, at 99 Hertz, for 10 seconds (< Linux 4.11):
perf record -F 99 -ag -- sleep 10# Sample CPU stack traces for the entire system, at 99 Hertz, for 10 seconds (>= Linux 4.11):
perf record -F 99 -g -- sleep 10# If the previous command didn't work, try forcing perf to use the cpu-clock event:
perf record -F 99 -e cpu-clock -ag -- sleep 10# Sample CPU stack traces, once every 10,000 Level 1 data cache misses, for 5 seconds:
perf record -e L1-dcache-load-misses -c 10000 -ag -- sleep 5# Sample CPU stack traces, once every 100 last level cache misses, for 5 seconds:
perf record -e LLC-load-misses -c 100 -ag -- sleep 5 # Sample on-CPU kernel instructions, for 5 seconds:
perf record -e cycles:k -a -- sleep 5 # Sample on-CPU user instructions, for 5 seconds:
perf record -e cycles:u -a -- sleep 5
Static Tracing 事件
# Trace new processes, until Ctrl-C:
perf record -e sched:sched_process_exec -a# Sample context-switches, until Ctrl-C:
perf record -e context-switches -a# Trace all context-switches, until Ctrl-C:
perf record -e context-switches -c 1 -a# Trace all context-switches via sched tracepoint, until Ctrl-C:
perf record -e sched:sched_switch -a# Sample context-switches with stack traces, until Ctrl-C:
perf record -e context-switches -ag# Sample context-switches with stack traces, for 10 seconds:
perf record -e context-switches -ag -- sleep 10# Sample CS, stack traces, and with timestamps (< Linux 3.17, -T now default):
perf record -e context-switches -ag -T# Sample CPU migrations, for 10 seconds:
perf record -e migrations -a -- sleep 10# Trace all connect()s with stack traces (outbound connections), until Ctrl-C:
perf record -e syscalls:sys_enter_connect -ag# Trace all accepts()s with stack traces (inbound connections), until Ctrl-C:
perf record -e syscalls:sys_enter_accept* -ag# Trace all block device (disk I/O) requests with stack traces, until Ctrl-C:
perf record -e block:block_rq_insert -ag# Trace all block device issues and completions (has timestamps), until Ctrl-C:
perf record -e block:block_rq_issue -e block:block_rq_complete -a# Trace all block completions, of size at least 100 Kbytes, until Ctrl-C:
perf record -e block:block_rq_complete --filter 'nr_sector > 200'# Trace all block completions, synchronous writes only, until Ctrl-C:
perf record -e block:block_rq_complete --filter 'rwbs == "WS"'# Trace all block completions, all types of writes, until Ctrl-C:
perf record -e block:block_rq_complete --filter 'rwbs ~ "*W*"'# Sample minor faults (RSS growth) with stack traces, until Ctrl-C:
perf record -e minor-faults -ag# Trace all minor faults with stack traces, until Ctrl-C:
perf record -e minor-faults -c 1 -ag# Sample page faults with stack traces, until Ctrl-C:
perf record -e page-faults -ag# Trace all ext4 calls, and write to a non-ext4 location, until Ctrl-C:
perf record -e 'ext4:*' -o /tmp/perf.data -a # Trace kswapd wakeup events, until Ctrl-C:
perf record -e vmscan:mm_vmscan_wakeup_kswapd -ag# Add Node.js USDT probes (Linux 4.10+):
perf buildid-cache --add `which node`# Trace the node http__server__request USDT event (Linux 4.10+):
perf record -e sdt_node:http__server__request -a
Dynamic Tracing 事件
# Add a tracepoint for the kernel tcp_sendmsg() function entry ("--add" is optional):
perf probe --add tcp_sendmsg# Remove the tcp_sendmsg() tracepoint (or use "--del"):
perf probe -d tcp_sendmsg# Add a tracepoint for the kernel tcp_sendmsg() function return:
perf probe 'tcp_sendmsg%return'# Show available variables for the kernel tcp_sendmsg() function (needs debuginfo):
perf probe -V tcp_sendmsg# Show available variables for the kernel tcp_sendmsg() function, plus external vars (needs debuginfo):
perf probe -V tcp_sendmsg --externs# Show available line probes for tcp_sendmsg() (needs debuginfo):
perf probe -L tcp_sendmsg# Show available variables for tcp_sendmsg() at line number 81 (needs debuginfo):
perf probe -V tcp_sendmsg:81# Add a tracepoint for tcp_sendmsg(), with three entry argument registers (platform specific):
perf probe 'tcp_sendmsg %ax %dx %cx'# Add a tracepoint for tcp_sendmsg(), with an alias ("bytes") for the %cx register (platform specific):
perf probe 'tcp_sendmsg bytes=%cx'# Trace previously created probe when the bytes (alias) variable is greater than 100:
perf record -e probe:tcp_sendmsg --filter 'bytes > 100'# Add a tracepoint for tcp_sendmsg() return, and capture the return value:
perf probe 'tcp_sendmsg%return $retval'# Add a tracepoint for tcp_sendmsg(), and "size" entry argument (reliable, but needs debuginfo):
perf probe 'tcp_sendmsg size'# Add a tracepoint for tcp_sendmsg(), with size and socket state (needs debuginfo):
perf probe 'tcp_sendmsg size sk->__sk_common.skc_state'# Tell me how on Earth you would do this, but don't actually do it (needs debuginfo):
perf probe -nv 'tcp_sendmsg size sk->__sk_common.skc_state'# Trace previous probe when size is non-zero, and state is not TCP_ESTABLISHED(1) (needs debuginfo):
perf record -e probe:tcp_sendmsg --filter 'size > 0 && skc_state != 1' -a# Add a tracepoint for tcp_sendmsg() line 81 with local variable seglen (needs debuginfo):
perf probe 'tcp_sendmsg:81 seglen'# Add a tracepoint for do_sys_open() with the filename as a string (needs debuginfo):
perf probe 'do_sys_open filename:string'# Add a tracepoint for myfunc() return, and include the retval as a string:
perf probe 'myfunc%return +0($retval):string'# Add a tracepoint for the user-level malloc() function from libc:
perf probe -x /lib64/libc.so.6 malloc# Add a tracepoint for this user-level static probe (USDT, aka SDT event):
perf probe -x /usr/lib64/libpthread-2.24.so %sdt_libpthread:mutex_entry# List currently available dynamic probes:
资料直通车:Linux内核源码技术学习路线+视频教程内核源码
学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈
Perf Tool 工具集介绍
Perf Tool 是一个用户态工具集,包含了 22 种子工具集,下表具体介绍每种工具的基本功能:
Perf List
Perf List:查看当前软硬件平台支持的性能事件列表,性能事件的属性。
- u: 仅统计用户空间程序触发的性能事件
- k: 仅统计内核触发的性能事件
- h: 仅统计 Hypervisor 触发的性能事件
- G: 在 KVM 虚拟机中,仅统计 Guest 系统触发的性能事件
- H: 仅统计 Host 系统触发的性能事件
- p: 精度级别
Perf Stat
Perf Stat:分析性能。
perf stat -p $pid -d # 进程级别统计perf stat -a -d sleep 5 # 系统整体统计perf stat -p $pid -e 'syscalls:sys_enter' sleep 10 #分析进程调用系统调用的情形
Perf Top
Perf Top:实时显示系统/进程的性能统计信息, 默认性能事件为 cycles ( CPU 周期数 )。与 Linux top tool 功能类似。
perf top -p $pid -g # 进程级别
perf top -g # 系统整体
Perf Record
Perf Record:记录一段时间内系统/进程的性能事件, 默认性能事件为 cycles ( CPU 周期数 )。
perf record -p $pid -g -e cycles -e cs #进程采样
perf record -a -g -e cycles -e cs #系统整体采样
Perf Script
读取 Perf Record 结果。
-i, --input <file> input file name-G, --hide-call-graphWhen printing symbols do not display call chain-F, --fields <str> comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr,symoff,period-a, --all-cpus system-wide collection from all CPUs-S, --symbols <symbol[,symbol...]>only consider these symbols-C, --cpu <cpu> list of cpus to profile-c, --comms <comm[,comm...]>only display events for these comms--pid <pid[,pid...]>only consider symbols in these pids--tid <tid[,tid...]>only consider symbols in these tids--time <str> Time span of interest (start,stop)--show-kernel-pathShow the path of [kernel.kallsyms]--show-task-eventsShow the fork/comm/exit events--show-mmap-eventsShow the mmap events--per-event-dump Dump trace output to files named by the monitored events
Perf Script 输出样式
$ perf script
...
swapper 0 [000] 222998.934740: 1 cycles: 7fff81062eaa native_write_msr_safe ([kernel.kallsyms])7fff8100ae75 __intel_pmu_enable_all.isra.12 ([kernel.kallsyms])7fff8100aef0 intel_pmu_enable_all ([kernel.kallsyms])7fff810077bc x86_pmu_enable ([kernel.kallsyms])7fff81172817 perf_pmu_enable ([kernel.kallsyms])7fff81173701 ctx_resched ([kernel.kallsyms])7fff81173870 __perf_event_enable ([kernel.kallsyms])7fff8116dfdc event_function ([kernel.kallsyms])7fff8116eaa4 remote_function ([kernel.kallsyms])7fff810fbb5d flush_smp_call_function_queue ([kernel.kallsyms])7fff810fc233 generic_smp_call_function_single_interrupt ([kernel.kallsyms])7fff810505c7 smp_call_function_single_interrupt ([kernel.kallsyms])7fff8169a41d call_function_single_interrupt ([kernel.kallsyms])7fff810367bf default_idle ([kernel.kallsyms])7fff81037106 arch_cpu_idle ([kernel.kallsyms])7fff810ea2a5 cpu_startup_entry ([kernel.kallsyms])7fff81676fe7 rest_init ([kernel.kallsyms])7fff81b0c05a start_kernel ([kernel.kallsyms])7fff81b0b5ee x86_64_start_reservations ([kernel.kallsyms])7fff81b0b742 x86_64_start_kernel ([kernel.kallsyms])
...
火焰图
火焰图是一种剖析软件运行状态的工具,它能够快速的将频繁执行的代码路径以图式的形式展现给用户。根据 Brendan Gregg 先生的介绍,常用的火焰图包括以下 5 种:
- CPU
- Memory
- Off-CPU
- Hot/Cold
- Differential
本文只着重介绍了 CPU 和 Off-CPU 火焰图,若读者对另三种火焰图感兴趣可参看 Brendan Gregg 先生的博客。
CPU 火焰图
CPU 火焰图反映了一段时间内用户程序在 CPU 上运行的热点,其绘制原理是对 Perf 采集到的 samples 进行解析,对函数调用栈进行归纳合并,以柱状图的形式呈现给系统管理员。
图片描述
每个长方块代表了函数调用栈中的一个函数,即为一层堆栈的内容。Y 轴显示堆栈的深度。顶层方块表示 CPU 上正在运行的函数。下面的函数即为它的祖先。X 轴的宽度代表被采集的 sample 的数量,越宽表示采集到的越多。
绘制原理
火焰图的绘制需要 Perf Tool 以及一些 Perl 脚本的辅助。
采集样本 通过 Perf Record 收集 CPU 热点样本原始文件。解析样本 通过 Perf Script 解析样本原始文件,得到样本对应的堆栈。绘制火焰图 统计堆栈中函数出现的频率,并以此绘制火焰图。
Off-CPU 火焰图
On CPU 火焰图可反映某时刻 CPU 的运行热点,然而它却留下了 Off-CPU 的问题:某些程序为何进入睡眠状态?睡眠时长有多久?
下图是一张 Off-CPU 时间图, 展示了一个由于系统调用而被阻塞的应用线程的运行情况。
从图中我们可以看出应用线程长时间被阻塞在 Off-CPU 状态,而这段时间则无法通过 On-CPU 火焰图反映。
Brendan Gregg 共总结了 4 种类型的 Off-CPU 火焰图:
1、I/O 火焰图
File I/O 或 block device I/O 的时间消耗。
2、Off-CPU 火焰图
分析线程睡眠路径的火焰图。
3、Wakeup 火焰图
分析线程被阻塞源头的火焰图。
4、Chain 火焰图
结合了 Off-CPU 和 Wakeup 火焰图,详细记录了线程的睡眠原因及唤醒条件。注意:Chain 火焰图性能开销巨大,慎用!
Off-CPU 火焰图绘制原理
通过 Off-CPU 火焰图,我们可以轻松地了解系统中任何进程的睡眠过程。其原理是利用 Perf Static Tracer 抓取一些进程调度的相关事件,并利用 Perf Inject 将这些事件合并,最终得到诱发进程睡眠的调用流程以及睡眠时间。
相关 Tracepoints 介绍
1、sched : sched_switch
记录了某进程引发调度器调度的执行流程,即产生进程切换的原因。产生进程切换的原因可能存在多种:
- 时间片耗尽
- 等待资源,如 I/O
- 等待锁释放
- 主动放弃 CPU
2、sched : sched_stat_sleep
由于主动放弃 CPU 而进入睡眠的等待事件。它记录了进程处于睡眠状态的时间。
3、sched : sched_stat_iowait
由于磁盘或网络 I/O 而引发的等待事件。它记录了进程因为等待 I/O 资源而进入 D 状态的时间。
4、sched : sched_stat_blocked
由于等待内核锁而引发的等待事件。它记录了进程等待锁释放而进入 D 状态的时间。
5、sched : sched_stat_wait
这个事件记录了进程在就绪队列中等待执行的时间。
实例介绍
下面这个例子介绍了如何统计系统中进入 S 状态的进程的睡眠时长及原因。
root@node10:/home$ echo 1 >/proc/sys/kernel/sched_schedstats
root@node10:/home$ perf record -e sched:sched_stat_sleep -e sched:sched_switch -a -g -o perf.data.raw sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.430 MB perf.data.raw (1031 samples) ]
root@node10:/home$ perf inject -s -v -i perf.data.raw -o perf.data
build id event received for [kernel.kallsyms]: f63207ec0e8d394d5a860306746f9064bfd0290a
symsrc__init: cannot get elf header.
Looking at the vmlinux_path (7 entries long)
Using /proc/kcore for kernel object code
Using /proc/kallsyms for symbols
通过追踪 sched_switch 事件获取相关进程切换的调用栈;通过追踪 sched_stat_sleep 事件获取进程的睡眠时间,最后利用 Perf Inject 合并两个事件即可。下面我们看看合并的过程:
1、首先查看合并前的事件:
root@node10:/home$ perf script -i perf.data.raw -F comm,pid,tid,cpu,time,period,event,ip,sym,dso,trace
...client 2344/2345 [007] 342165.258739: 1 sched:sched_switch: prev_comm=client prev_pid=2345 prev_prio=120 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=1207fff8168dbb0 __schedule ([kernel.kallsyms])7fff8168e069 schedule ([kernel.kallsyms])7fff8168d0f2 schedule_hrtimeout_range_clock ([kernel.kallsyms])7fff8168d1a3 schedule_hrtimeout_range ([kernel.kallsyms])7fff81215215 poll_schedule_timeout ([kernel.kallsyms])7fff81215b91 do_select ([kernel.kallsyms])7fff81215e5b core_sys_select ([kernel.kallsyms])7fff812162af sys_pselect6 ([kernel.kallsyms])7fff81699089 system_call_fastpath ([kernel.kallsyms])1cc4e3 runtime.usleep (/usr/local/gundam/gundam_client/client)1aac33 runtime.sysmon (/usr/local/gundam/gundam_client/client)1373300000500 [unknown] ([unknown])58b000003d98f0f [unknown] ([unknown])
...
swapper 0/0 [007] 342165.260097: 1358063 sched:sched_stat_sleep: comm=client pid=2345 delay=1358063 [ns]7fff810d2a40 enqueue_entity ([kernel.kallsyms])7fff810d2f59 enqueue_task_fair ([kernel.kallsyms])7fff810bf481 enqueue_task ([kernel.kallsyms])7fff810c3dc3 activate_task ([kernel.kallsyms])7fff810c4103 ttwu_do_activate.constprop.91 ([kernel.kallsyms])7fff810c72e9 try_to_wake_up ([kernel.kallsyms])7fff810c7483 wake_up_process ([kernel.kallsyms])7fff810b6662 hrtimer_wakeup ([kernel.kallsyms])7fff810b6d72 __hrtimer_run_queues ([kernel.kallsyms])7fff810b7310 hrtimer_interrupt ([kernel.kallsyms])7fff81052fd7 local_apic_timer_interrupt ([kernel.kallsyms])7fff8169b78f smp_apic_timer_interrupt ([kernel.kallsyms])7fff81699cdd apic_timer_interrupt ([kernel.kallsyms])7fff81516a69 cpuidle_idle_call ([kernel.kallsyms])7fff810370ee arch_cpu_idle ([kernel.kallsyms])7fff810ea2a5 cpu_startup_entry ([kernel.kallsyms])7fff8105107a start_secondary ([kernel.kallsyms])
...
2、合并后的事件:
root@node10:/home$ perf script -i perf.data -F comm,pid,tid,cpu,time,period,event,ip,sym,dso,trace
...
client 2344/2345 [007] 342165.260097: 1358063 sched:sched_switch: prev_comm=client prev_pid=2345 prev_prio=120 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=1207fff8168dbb0 __schedule ([kernel.kallsyms])7fff8168e069 schedule ([kernel.kallsyms])7fff8168d0f2 schedule_hrtimeout_range_clock ([kernel.kallsyms])7fff8168d1a3 schedule_hrtimeout_range ([kernel.kallsyms])7fff81215215 poll_schedule_timeout ([kernel.kallsyms])7fff81215b91 do_select ([kernel.kallsyms])7fff81215e5b core_sys_select ([kernel.kallsyms])7fff812162af sys_pselect6 ([kernel.kallsyms])7fff81699089 system_call_fastpath ([kernel.kallsyms])1cc4e3 runtime.usleep (/usr/local/gundam/gundam_client/client)1aac33 runtime.sysmon (/usr/local/gundam/gundam_client/client)1373300000500 [unknown] ([unknown])58b000003d98f0f [unknown] ([unknown])
...
总结
本文首先介绍了 Linux Perf Event 子系统的整体架构,接着为读者展示了 Perf 的两种工作模式及各种类别的 Perf Events,之后详细介绍了 Perf Tool 的多种子工具集,最后为读者展示了 Bredan Gregg 先生引入的各种火焰图及其绘制原理。通过阅读本文,读者将会对 Linux Perf 有更为深入的理解。
相关文章:

深入浅析Linux Perf 性能分析工具及火焰图
Perf Event 子系统 Perf 是内置于 Linux 内核源码树中的性能剖析(profiling)工具。它基于事件采样的原理,以性能事件为基础,支持针对处理器相关性能指标与操作系统相关性能指标的性能剖析。可用于性能瓶颈的查找与热点代码的定位…...
java关键术语
java具有11个关键的术语,这些术语是从java的设计者所编写的白皮书中摘取,这些术语分别为:简单性、面向对象、分布式、健壮性、安全性、体系结构中立、可移植性、解释型、高性能、多线程、多态性。以下开始我们将逐一解说这些术语。 一、简单性 Java是C++语法的纯净版本,剔…...
1. 两数之和【简单】
题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺…...

《编码——隐匿在计算机软硬件背后的语言》精炼——第17章(自动操作)
夫道成于学而藏于书,学进于振而废于穷。 文章目录 完善加法器加入代码的加法器扩大加数范围自由调用地址的加法器合并代码RAM和数据RAMJump指令硬件实现条件Jump指令零转移的硬件实现条件Jump指令的例子 总结 完善加法器 我们在第14章介绍了一个可以进行连加的加法…...

用Colab免费部署AI绘画云平台Stable Diffusion webUI
Google Colab 版的 Stable Diffusion WebUI 1.4 webui github 地址:https://github.com/sd-webui/stable-diffusion-webui 平台搭建 今天就来交大家如果来搭建和使用这个云平台。 第一步: 打开链接 https://colab.research.google.com/github/altryne/sd-webu…...

R.I.P,又一位程序员巨佬——左耳朵耗子陨落
震惊!谣言吧!求辟谣!默哀! 左耳朵耗子,在程序员这个群体里应该属于 GOAT 的存在了,虽然每个人心目中都有自己的 GOAT,但耗子叔的影响力可以说是有目共睹。 我也是在技术群刷到这张图片的&#…...

捷威信keithley吉时利2410数字源表 销售回收KEITHLEY2470新款源表
吉时利Keithley 2410 /2470高压源表/数字源表 产品概览 Keithley 2410 高压源表专为需要紧密耦合源和测量的测试应用而设计。Keithly 2410 提供精密电压和电流源以及测量功能。它既是高度稳定的直流电源,又是真正的仪器级 5-1/2 数字万用表。电源特性包括低噪声、…...
第二十九回:如何给ListView添加分隔线
文章目录 概念介绍添加方法使用属性装饰器 示例代码经验总结: 我们在上一章回中介绍了多种创建ListView的方式,本章回中将介绍" 如何给ListView添加分隔线".闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们在这里说的分隔线也叫Divider,…...
用友 LRP计划维护视图
select planlotnumber 计划单号, demandId 自动编号, PartId 物料Id , sotype 单据类型(1:销售/2:预测), sodid 销售订单明细Id , socode 销售订单单号 , soseq 销售订单行号, PlanCode 计划单号 , DueDate 完工日期 , StartDate 开工日期 , UnitCode 主计量单位, C…...

数组--part 5--螺旋矩阵(力扣59/54)(剑指offer 29)
文章目录 基本算法思想leetcode 59 螺旋矩阵 IIleetcode 54 螺旋矩阵剑指Offer 29 顺时针打印矩阵 基本算法思想 建议先去把题目看了,再来思考相关的代码。 错误的想法:实际上这种题型并不存在算法,只涉及到模拟,但是模拟难度并…...

加密解密软件VMProtect入门使用教程(九)许可制度之许可系统功能
VMProtect是新一代软件保护实用程序。VMProtect支持德尔菲、Borland C Builder、Visual C/C、Visual Basic(本机)、Virtual Pascal和XCode编译器。 同时,VMProtect有一个内置的反汇编程序,可以与Windows和Mac OS X可执行文件一起…...

MySQL基础-事务详解
本文主要介绍MySQL事务 文章目录 前言事务定义事务四大特性(ACID) 事务操作事务并发问题事务隔离级别 前言 参考链接: 链接1链接2 事务定义 事务是一组操作的集合,他是一个不可分割的工作单位,事务会把所有的操作作…...

python 读写csv文件方法
csv是一种结构化文件,可以将文本转化成矩阵的形式,方便程序读取和处理。下面来介绍一下使用 python读写 csv文件的方法: 1.首先需要使用 pip安装 python包,然后将 csv文件解压到一个文件夹下 2.使用 pip安装 python包,…...

命令行更新Windows
命令行更新Windows powershell命令行更新安装 Windows Update module for Windows Powershell连接到 Windows Update 服务器并下载更新安装下载好的 Windows Update 更新 cmd执行Windows update更新检查更新下载 Windows Update 更新安装更新安装更新后重新启动设备 win10以下版…...
lwIP 多线程注意事项
关于 lwIP 多线程的总结: lwIP 内核不是线程安全的。如果在多线程环境中使用 lwIP,必须使用高层次的 Sequential 或 socket API。使用 raw API 时,需要自己保护好应用程序和协议栈核心代码。在无操作系统环境中使用 raw API: 使用…...
工业革命的本质是动力革命:人类使用能量的水平得到了飞跃(蒸汽动力取代畜力和水力,机械代替人工。)【工业革命的诞生是能量富余的结果】
文章目录 引言I 用能量守恒方式看工业革命的影响1.1 中学物理能量守恒1.2 看清历史事件的影响1.3 工业革命的意义1.4 透过现象看本质的方法II 工业革命的本质2.1 动力革命2.2 多余的能量造就了工业革命引言 人类文明进步的目的是改善人们的生活,任何文明都以养活更多的人口为…...
【Kubernetes】Windows安装kubectl
准备开始 kubectl版本和集群版本之间的差异必须在一个小版本号内。 例如:v1.27版本的客户端能与 v1.26、 v1.27 和 v1.28 版本的控制面通信。 用最新兼容版的 kubectl 有助于避免不可预见的问题。 下载 官方安装文档: https://kubernetes.io/zh/docs/tasks/tools…...

菜鸟健身-新手使用哑铃锻炼手臂的动作与注意事项
目录 一、前言 二、哑铃锻炼手臂的好处 三、哑铃锻炼手臂的注意事项 四、哑铃锻炼手臂的基本动作 1. 哑铃弯举 2. 哑铃推举 3. 哑铃飞鸟 五、哑铃锻炼手臂的进阶动作 1. 哑铃侧平举 2. 哑铃俯身划船 六、哑铃锻炼手臂的训练计划 七、总结 一、前言 哑铃是一种非常…...

二、LLC 谐振变换器
半桥 LLC 谐振变换器主电路结构 如图所示,半桥 LLC 谐振变换器主电路可以分为四个部分,即:逆变网络、谐振网络、变压器及整流滤波网络。两个 MOSFET(S1、S2)以及它们的体二极管(D1、D2)和寄生电…...

JWT 入门
1.介绍 JSON Web Token(JWT)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO…...
链表题解——环形链表【LeetCode】
141. 环形链表 方法一 核心思想: 使用一个集合 seen 来记录已经访问过的节点。遍历链表,如果当前节点已经存在于集合中,说明链表存在环;否则,将当前节点添加到集合中,继续遍历。如果遍历结束(h…...

人机融合智能 | 可穿戴计算设备的多模态交互
可穿戴计算设备可以对人体以及周围环境进行连续感知和计算,为用户提供随时随地的智能交互服务。本章主要介绍人机智能交互领域中可穿戴计算设备的多模态交互,阐述以人为中心的智能穿戴交互设计目标和原则,为可穿戴技术和智能穿戴交互技术的设计提供指导,进而简述支持智能穿戴交…...

leetcode刷题日记——1.组合总和
解答: class Solution { public:void dfs(vector<int>& candidates, int target, vector<vector<int>>& ans, vector<int>& combine, int idx) {if(idxcandidates.size()){//遍历完的边界return;}if(target0){//找完了能组成和…...
调试器基本原理
调试器基本原理 前言 调试器(debugger),是一种用于控制其他程序执行流程、监控和修改其他程序状态的软件工具。 调试器通过实时分析程序的执行状态,协助开发者定位代码错误、了解程序工作原理、性能调优及逆向工程等。 1. 调试器核心功能 1.1 控制程…...
DHCP 动态主机配置协议(Dynamic host configuration protocol)逐层封装过程: DHCP --> UDP --> IP
📦 DHCP 报文逐层封装结构(自上而下) 应用层(DHCP 报文) ↓ 传输层(UDP 首部) ↓ 网络层(IP 首部) ↓ 数据链路层(以太网帧头) ↓ 物理层&#x…...
MS2691 全频段、多模导航、射频低噪声放大器芯片,应用于导航仪 双频测量仪
MS2691 全频段、多模导航、射频低噪声放大器芯片,应用于导航仪 双频测量仪 产品简述 MS2691 是一款具有 1164MHz 1615MHz 全频段、低功耗的低噪声放大器芯片。该芯片通过对外围电路的简单配置,使得频带具有宽带或窄带特性。支持不同频段的各种导…...
tpc udp http
TCP(传输控制协议)、UDP(用户数据报协议)和 HTTP(超文本传输协议)是网络通信中常用的三种协议,它们在不同的层次和场景中发挥作用。以下是对这三种协议的详细解释以及它们之间的区别:…...
数据库密码加密
数据库密码加密 添加jar包构建工具类具体使用优缺点 添加jar包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId> </dependency>构建工具类 public class PasswordUtil …...
wordpress+woocommerce电商平台搭建方案的优势分析
以下是WordPress WooCommerce电商平台搭建方案的优势分析: 技术架构与功能扩展优势 强大的插件生态系统:WordPress拥有超过58000个插件,WooCommerce作为其中最受欢迎的电商插件,提供了丰富的功能扩展选项,如支持超过…...

OS11.【Linux】vim文本编辑器
目录 1.四种模式 命令模式 几个命令 插入模式 底行模式 一图展示三种模式之间的关系 2.分屏(多文件操作) 3.配置vim的原理 4.脚本一键配置vim CentOS 7 x86_64 其他发行版 5.NeoVim(推荐) vim文本编辑器是一个多模式的编辑器,因此先介绍它的四种模式 附vim的官网:…...