Linux程序性能分析
为什么程序会慢?
在深入工具和方法之前,我们先来聊聊为什么程序会慢。一个程序主要在三个方面消耗资源:
-
CPU时间 - 计算太多、算法效率低
-
内存使用 - 内存泄漏、频繁申请释放内存
-
I/O操作 - 文件读写、网络通信太频繁
今天我们主要聚焦CPU性能分析,因为这通常是最直接影响程序速度的因素。内存和 I/O 问题咱们后面再专门讲。
谁是 CPU 时间的大户?用 top 找出来
既然要分析性能,那首先得知道是不是我们的程序真的耗 CPU。最直观的方法就是用top
命令实时监控程序的 CPU 和内存使用情况:
$ top -p $(pgrep 进程名)
这样你就能看到程序的 CPU 使用率。如果一个程序占用 CPU 接近 100%,那它八成是有性能问题了。而且通过 top,你还能看到程序使用了多少内存等信息,这些都是判断程序健康状况的重要指标。
入门级工具:time命令
发现程序确实吃 CPU 后,我们需要更具体地知道它到底慢在哪里。这时可以用 Linux 自带的 time
命令来分析程序的运行时间构成:
$ time ./my_program
执行后你会看到类似这样的输出:
real 0m1.234s
user 0m1.000s
sys 0m0.234s
-
real:实际经过的时间(墙上时钟时间)
-
user:CPU在用户态的执行时间
-
sys:CPU在内核态的执行时间
如果user
时间特别长,说明你的程序计算量太大;如果sys
时间特别长,说明你的程序系统调用太多。
打个比方,这就像你去餐厅吃饭:
-
real时间是从你进门到出门的总时间
-
user时间是你实际吃饭的时间
-
sys时间是服务员端菜、收拾桌子的时间
性能分析的秘密武器:perf
time
和top
只能告诉你程序慢,但具体慢在哪个函数,还得靠专业工具。Linux下最强大的性能分析工具之一就是perf
。
安装perf
# Ubuntu/Debian
$ sudo apt-get install linux-tools-common linux-tools-generic# CentOS/RHEL
$ sudo yum install perf
实战:找出CPU杀手
程序慢了,我们需要找出具体是哪段代码拖了后腿。perf 就是最好的侦探工具:
# 开发环境:从启动开始记录
$ sudo perf record -g ./slow_program# 生产环境:对运行中程序采样30秒
$ sudo perf record -p <进程ID> -g -F 99 sleep 30# 分析结果
$ perf report
开发环境用第一种方式,能看到程序从启动到结束的全过程;生产环境用第二种方式,不用重启服务就能采样数据。perf report
会显示哪些函数最耗 CPU,直接指出问题所在!
我曾经遇到过一个实际案例:程序处理大量数据非常慢,用 perf 一看,发现 80% 的 CPU 时间都花在了一个字符串处理函数上。把这个函数优化后,整个程序速度提升了 5 倍。
更直观的火焰图:FlameGraph
perf 的输出有时候不够直观,这时候就需要"火焰图"(FlameGraph)出场了。火焰图能把 perf 的结果可视化,一眼就能看出哪个函数最耗时。
生成火焰图
# 先记录perf数据
$ sudo perf record -p <进程ID> -g -F 99 sleep 30# 导出数据
$ perf script > perf.out# 用FlameGraph工具生成SVG图
$ git clone https://github.com/brendangregg/FlameGraph.git
$ cd FlameGraph
$ ./stackcollapse-perf.pl ../perf.out > ../perf.folded
$ ./flamegraph.pl ../perf.folded > ../flamegraph.svg# 使用 firefox 打开
$ firefox flamegraph.svg
然后用浏览器打开生成的 svg 文件,你会看到一个炫酷的火焰图!图中宽度越大的函数,占用的 CPU 时间就越多。
实战案例:优化一个日志解析程序
前几天我有个小需求,需要解析一些服务器日志文件,提取出所有 ERROR 级别的日志,并生成个简单报告。我写了个第一版的程序,但在处理一个 893MB 的日志文件时,跑了整整 3 分钟才出结果,这也太慢了吧!
代码是这样的:
// slow_parser.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include <vector>struct LogEntry {std::string timestamp;std::string level;std::string message;
};std::vector<LogEntry> parse_log(const std::string& filename) {std::vector<LogEntry> entries;std::ifstream file(filename);std::string line;// 使用正则表达式解析日志格式:[时间戳] [日志级别] 消息内容std::regex log_pattern(R"(\[(.*?)\]\s*\[(.*?)\]\s*(.*))");while (std::getline(file, line)) {std::smatch matches;if (std::regex_search(line, matches, log_pattern)) {LogEntry entry;entry.timestamp = matches[1];entry.level = matches[2];entry.message = matches[3];// 只保留ERROR级别的日志if (entry.level == "ERROR") {entries.push_back(entry);}}}return entries;
}int main(int argc, char* argv[]) {if (argc != 2) {std::cerr << "用法: " << argv[0] << " <日志文件路径>" << std::endl;return1;}std::cout << "开始解析日志文件: " << argv[1] << std::endl;auto entries = parse_log(argv[1]);std::cout << "共发现 " << entries.size() << " 条ERROR级别日志" << std::endl;// 输出前10条错误日志int count = 0;for (constauto& entry : entries) {if (count++ < 10) {std::cout << entry.timestamp << ": " << entry.message << std::endl;} else {break;}}return0;
}
编译并测试了下运行时间:
$ g++ -g slow_parser.cpp -o slow_parser
$ time ./slow_parser server.log
运行结果:
real 3m0.753s
user 2m54.315s
sys 0m6.399s
差不多 3 分钟,太离谱了!我决定用 perf 来分析一下到底是哪里慢:
$ perf record -g ./slow_parser server.log
$ perf report
perf report 的结果让我眼前一亮:
Samples: 197K of event 'cycles', Event count (approx.): 94623200788Children Self Command Shared Object Symbol
+ 77.46% 15.58% a.out a.out [.] std::__detail::_Executor<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, s◆
+ 76.84% 5.75% a.out a.out [.] std::__detail::_Executor<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, s
+ 75.84% 5.91% a.out a.out [.] std::__detail::_Executor<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, s
+ 75.01% 4.26% a.out a.out [.] std::__detail::_Executor<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, s
+ 71.60% 0.62% a.out a.out [.] std::__detail::_Executor<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, s
...
+ 48.18% 0.05% a.out a.out [.] std::regex_search<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::cha
...
这里需要理解两个关键列:
-
Self:函数自身消耗的CPU时间百分比
-
Children:函数及其调用的所有子函数消耗的CPU时间百分比
简单说,Self 告诉你"这个函数本身"有多慢,Children 告诉你"这个函数及它调用的所有函数"一共有多慢。性能优化时,通常先看 Children 高的函数找到热点调用链,再看 Self 高的函数找到真正耗时的代码。
虽然输出结果有点复杂,但很明显,大部分 CPU 时间都花在了 std::__detail::_Executor
和std::regex_search
这些函数上,这些都是正则表达式相关的函数!看来正则表达式是罪魁祸首。
其实想想也对,正则表达式虽然功能强大,但在处理大量文本时,性能确实不太理想。于是我决定用普通的字符串处理函数来替代正则表达式:
// fast_parser.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <chrono>struct LogEntry {std::string timestamp;std::string level;std::string message;
};std::vector<LogEntry> parse_log(const std::string& filename) {std::vector<LogEntry> entries;std::ifstream file(filename);std::string line;// 预分配空间,减少内存重新分配entries.reserve(10000);// 使用字符串搜索和截取替代正则表达式while (std::getline(file, line)) {size_t first_bracket = line.find('[');size_t second_bracket = line.find(']', first_bracket);size_t third_bracket = line.find('[', second_bracket);size_t fourth_bracket = line.find(']', third_bracket);if (first_bracket != std::string::npos && second_bracket != std::string::npos &&third_bracket != std::string::npos && fourth_bracket != std::string::npos) {LogEntry entry;entry.timestamp = line.substr(first_bracket + 1, second_bracket - first_bracket - 1);entry.level = line.substr(third_bracket + 1, fourth_bracket - third_bracket - 1);entry.message = line.substr(fourth_bracket + 1);// 去除消息前面的空格size_t message_start = entry.message.find_first_not_of(' ');if (message_start != std::string::npos) {entry.message = entry.message.substr(message_start);}// 只保留ERROR级别的日志if (entry.level == "ERROR") {entries.push_back(entry);}}}return entries;
}int main(int argc, char* argv[]) {if (argc != 2) {std::cerr << "用法: " << argv[0] << " <日志文件路径>" << std::endl;return1;}auto start_time = std::chrono::high_resolution_clock::now();std::cout << "开始解析日志文件: " << argv[1] << std::endl;auto entries = parse_log(argv[1]);std::cout << "共发现 " << entries.size() << " 条ERROR级别日志" << std::endl;// 输出前10条错误日志int count = 0;for (constauto& entry : entries) {if (count++ < 10) {std::cout << entry.timestamp << ": " << entry.message << std::endl;} else {break;}}auto end_time = std::chrono::high_resolution_clock::now();auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);std::cout << "处理耗时: " << duration.count() / 1000.0 << " 秒" << std::endl;return0;
}
再次编译运行:
$ g++ -O2 fast_parser.cpp -o fast_parser
$ time ./fast_parser server.log
优化后的结果:
real 0m8.188s
user 0m7.240s
sys 0m0.945s
哇!只用了 8 秒多!相比原来的 3 分钟,这简直就是天壤之别啊,速度提升了 20 多倍!
主要优化点:
-
使用基本的字符串操作替代了正则表达式
-
预分配了 vector 的空间,减少内存重新分配
-
增加了 -O2 编译优化选项
-
添加了时间测量代码,方便对比性能
这个小实验给我的启示是:虽然正则表达式写起来很方便,但在处理大量数据时,可能成为严重的性能瓶颈。
用性能分析工具找出这些瓶颈,然后用更高效的方法替代,就能大幅提升程序性能。这在实际工作中可是能省下不少时间的技能啊!
性能分析的实用技巧
1、 先用简单工具:不要一上来就用复杂工具。先用 time、top 这些简单命令,确定问题大致在哪。
2、二八原则:程序 80% 的时间往往花在 20% 的代码上。找到这 20% 的"热点"代码是关键。
3、 二分查找法找性能问题:如果项目很大,不知道从哪下手,可以试试"二分法":
-
把程序的功能模块分成两半
-
暂时禁用一半,看问题是否还存在
-
根据结果,继续对有问题的那一半再分成两半
-
如此反复,直到定位到具体模块
4、编译优化:别忘了编译时的优化选项,比如:
$ g++ -O2 your_program.cpp -o your_program
5、使用性能分析器:除了 perf,还有很多好用的工具,比如 Valgrind 的Callgrind、gperftools等。
6、不要过早优化:先让程序正确运行,再考虑性能优化。过早优化是万恶之源!
总结:性能分析的"三板斧"
如果你是初学者,记住这个简单的流程就够了:
-
用 top 监控 CPU 使用率
-
用 time 测量总执行时间
-
用 perf 找出具体的热点函数
相关文章:
Linux程序性能分析
为什么程序会慢? 在深入工具和方法之前,我们先来聊聊为什么程序会慢。一个程序主要在三个方面消耗资源: CPU时间 - 计算太多、算法效率低 内存使用 - 内存泄漏、频繁申请释放内存 I/O操作 - 文件读写、网络通信太频繁 今天我们主要聚焦C…...
【开题报告+论文+源码】基于SpringBoot的智能安全与急救知识科普系统设计与实现
项目背景与意义 在全球范围内,安全与急救知识的普及已成为提升公众安全素养、减少意外伤害发生率、提高突发事件应对能力的重要举措。尤其是在当今社会,人们面临的生活、工作环境日益复杂,交通事故、火灾、溺水、突发疾病等各种意外事件的发生…...
Linux shift 命令使用详解
简介 在 Bash 脚本中,shift 命令用于将命令行参数向左移动,有效地丢弃第一个参数并将其他参数向下移动。 基础语法 shift [N]N(可选)→ 要移动的位置数。默认值为 1 示例用法 移动参数 #!/bin/bash echo "Before shift…...
【C++网络编程】第5篇:UDP与广播通信
一、UDP协议核心特性 1. UDP vs TCP 特性 UDPTCP连接方式无连接面向连接(三次握手)可靠性不保证数据到达或顺序可靠传输(超时重传、顺序控制)传输效率低延迟,高吞吐相对较低(因握手和确认机制&…...
C++11QT复习 (五)
文章目录 **Day6-2 成员访问运算符重载(2025.03.25)****1. 复习****2. 成员访问运算符重载****2.1 箭头运算符 (->) 重载****(1) 语法** **2.2 解引用运算符 (*) 重载****(1) 语法** **3. 代码分析****3.1 代码结构****3.2 代码解析****(1) Data 类**…...
Python项目-基于Python的网络爬虫与数据可视化系统
1. 项目简介 在当今数据驱动的时代,网络爬虫和数据可视化已成为获取、分析和展示信息的重要工具。本文将详细介绍如何使用Python构建一个完整的网络爬虫与数据可视化系统,该系统能够自动从互联网收集数据,进行处理分析,并通过直观…...
SpringCloud Zuul 使用教程
SpringCloud Zuul 使用教程 目录 Zuul 简介环境准备搭建 Zuul 网关 • 3.1 Maven 依赖 • 3.2 配置文件 • 3.3 启动类注解基本路由配置 • 4.1 简单路由 • 4.2 基于路径的路由 • 4.3 基于服务的路由Zuul 高级配置 • 5.1 过滤器配置 • 5.2 限流与熔断 • 5.3 负载均衡 •…...
介绍一款基于MinerU的PDF翻译工具
一。简介 Fast pdf translate是一款pdf翻译软件,基于MinerU实现pdf转markdown的功能,接着对markdown进行分割, 送给大模型翻译,最后组装翻译结果并由pypandoc生成结果pdf。 git地址: https://github.com/kv1830/fast…...
轻量级TLS反向代理工具TLS-reverse-proxy:打造安全通信桥梁
在数字化浪潮席卷全球的今天,数据隐私与传输安全已成为企业及个人的核心关切。TLS(传输层安全协议)作为互联网通信的"隐形卫士",承担着保护数据在传输过程中不被窃取或篡改的重要使命。然而,对于许多传统服务…...
SQL问题分析与诊断(8)——前提
8.1. 前提 与其他关系库类似,SQL Server中,当我们对存在性能问题的SQL语句进行分析和诊断时,除了获取该SQL语句本身外,还需要获取SQL语句相应的查询计划及其相关的数据环境。这里,所谓数据环境,具体是指SQ…...
关于cmd中出现无法识别某某指令的问题
今天来解决以下这个比较常见的问题,安装各种软件都可能会发生,一般是安装时没勾选注册环境变量,导致cmd无法识别该指令。例如mysql,git等,一般初学者可能不太清楚。 解决这类问题最主要的是了解环境变量的概念&#x…...
如何处理不同输入类型(例如邮箱、电话号码)的验证?
处理不同输入类型(如邮箱、电话号码)的验证可以通过多种方法实现,包括使用 HTML5 内置验证、JavaScript/jQuery 自定义验证和正则表达式。以下是一些常用的验证方法和示例。 1. 使用 HTML5 内置验证 HTML5 提供了一些内置的输入类型,可以自动处理基本的验证。 示例 <…...
Redis集群哨兵相关面试题
目录 1.Redis 主从复制的实现原理是什么? 详解 补充增量同步 replication buffer repl backlog buffer 2.Redis 主从复制的常见拓扑结构有哪些? 3.Redis 复制延迟的常见原因有哪些? 4.Redis 的哨兵机制是什么? 主观下线和客观下线 哨兵leader如何选出来的&#x…...
【CXX-Qt】4.1 extern “RustQt“
QObjects Properties Methods Signals #[cxx_qt::bridge] mod ffi {extern "RustQt" {} }extern “RustQt” 部分是 CXX-Qt 桥接的核心,用于声明 Rust 类型和签名,使其可用于 Qt 和 C。 CXX-Qt 代码生成器使用你的 extern “RustQt” 部…...
当 0 编程基础,用 ChatGPT 和 Cursor 开发同一应用时… |AI 开发初体验
求人不如求己。 事情是这样的,前段时间,我看了本书,书里介绍了款应用,能计算财富自由价格,还能制定退休计划。 结果,我迫不及待去下载这个应用时,发现这应用功能残缺,完全不可用。 …...
如何排查C++程序的CPU占用过高的问题
文章目录 可能的原因程序设计的BUG系统资源问题恶意软件硬件问题 通常步骤一个简单的问题代码在windows平台上如何排查Windows Process ExplorerWinDBG 在Linux平台如何排查使用TOP GDBPerf 可能的原因 程序设计的BUG 有死循环低效算法与数据结构滥用自旋锁频繁的系统调用&a…...
数据库练习
完善t_hero表 -- 添加作者字段 alter table t_hero add author varchar(100);-- 更新数据update t_hero set author "曹雪芹" where id 1; update t_hero set author "曹雪芹" where id 2; update t_hero set author "曹雪芹" where id…...
nodejs-原型污染链
还是老规矩,边写边学,先分享两篇文章 深入理解 JavaScript Prototype 污染攻击 | 离别歌 《JavaScript百炼成仙》 全书知识点整理-CSDN博客 Ctfshow web入门 nodejs篇 web334-web344_web334 ctfshow-CSDN博客 334-js审计 var express require(expr…...
无人机与AI技术结合的突破性应用场景
1. 自主导航与动态避障 技术栈:SLAM 强化学习 (PPO算法) 代码示例(Python PyTorch): import torch class DronePPO(torch.nn.Module):def __init__(self):super().__init__()self.actor torch.nn.Sequential(torch.nn.Linear…...
jsBridge在vue中使用
创建jsBridge.js /* eslint-disable */ function connectWebViewJavascriptBridge (callback) {if (window.WebViewJavascriptBridge) {callback(window.WebViewJavascriptBridge)} else {document.addEventListener(WebViewJavascriptBridgeReady, function () { callback(wi…...
Windows下docker使用教程
docker安装 镜像制作镜像加载容器创建更新镜像导出镜像 Windows10安装dockerdocker image制作docker 镜像加载docker 容器创建更新imageimage 导出为.tar文件 #以Windows10 、11为例 linux和Windows区别在于docker安装的程序是哪个操作系统的,后面的内容其实不变 …...
iOS:GCD信号量、同步、异步的使用方法
信号量的详细用法,可以用此方法进行队列管理 -(void)dispatchSignal{//crate的value表示,最多几个资源可访问dispatch_semaphore_t semaphore dispatch_semaphore_create(3);dispatch_queue_t quene dispatch_get_global_queue(DISPATCH_QUEUE_PRIORI…...
Nginx相关漏洞解析
一、CRLF注入漏洞 原理:Nginx将传入的url进行解码,对其中的%0a%0d替换成换行符,导致后面的数据注入至头部,造成CRLF 注入漏洞 1、开环境 2、访问网站,并抓包 3、构造请求头 %0ASet-cookie:JSPSESSID%3D1 这样就可以…...
SpringCloud构建一个服务步骤
Spring Cloud是一个用于构建分布式系统的开源框架,可以帮助开发者快速构建各种云原生应用。下面是一个简单的步骤,展示如何使用Spring Cloud构建一个服务: 创建一个Spring Boot项目:首先需要创建一个Spring Boot项目作为基础。可以…...
MySQL中怎么分析性能?
MySQL中主要有4种方式可以分析数据库性能,分别是慢查询日志,profile,Com_xxx和explain。 慢查询日志 先用下面命令查询慢查询日志是否开启, show variables like slow_query_log;# 一般默认都是以下结果 ---------------------…...
MinGW与使用VScode写C语言适配
压缩包 通过网盘分享的文件:MinGW.zip 链接: https://pan.baidu.com/s/1QB-Zkuk2lCIZuVSHc-5T6A 提取码: 2c2q 需要下载的插件 1.翻译 找到VScode页面,从上数第4个,点击扩展(以下通此) 搜索---Chinese--点击---安装--o…...
k8s存储介绍(五)PV与PVC
在 Kubernetes(k8s)中,持久化存储(Persistent Storage)是一个非常重要的概念,因为 Pod 本身是无状态的,重启后会丢失数据。为了支持有状态应用,Kubernetes 提供了持久化存储的机制&a…...
LangChain开发(五)消息管理与聊天历史存储
文章目录 消息存储在内存使用单参数session_id配置会话唯一键 消息持久化到redis安装redis依赖安装redis调用聊天接口,看Redis是否存储历史记录 裁剪消息总结记忆源码地址参考资料 消息存储在内存 我们展示一个简单的示例,其中聊天历史保存在内存中&…...
HTML 表单处理进阶:验证与提交机制的学习心得与进度(一)
引言 在前端开发的广袤领域中,HTML 表单处理堪称基石般的存在,是构建交互性 Web 应用不可或缺的关键环节。从日常频繁使用的登录注册表单,到功能多样的搜索栏、反馈表单,HTML 表单如同桥梁,紧密连接着用户与 Web 应用…...
【文献25/03/26】Hyperspectral Image Transformer Classification Networks
高光谱图像Transformer分类网络 Hyperspectral Image Transformer Classification Networks | IEEE Journals & Magazine | IEEE Xplore 摘要 高光谱图像(HSI)分类是地球观测任务中的一项重要工作。 卷积神经网络(CNN)凭借…...
数字转换(c++)
【题目描述】 如果一个数 xx 的约数和 yy (不包括他本身)比他本身小,那么 xx 可以变成 yy ,yy 也可以变成 xx 。例如 44 可以变为 33 ,11 可以变为 77 。限定所有数字变换在不超过 nn 的正整数范围内进行,…...
WPF ContentPresenter详解2
ContentPresenter与ContentControl的区别 ContentControl 和 ContentPresenter 是 WPF 中两个相关的控件,但它们在用途和功能上有一些关键的区别。理解这两者的区别和联系有助于更好地设计和开发用户界面。 1. 类层次结构 ContentControl:位于 WPF 控件…...
【git】认识git的本地仓库
1.创建本地仓库 git init2. 配置本地仓库 git config user.name xxx git config user.email xxx3. 认识本地仓库 创建完本地仓库后,目录下会有一个.git文件,这个就是本地仓库 而创建本地仓库的目录叫做工作区,我们不能对.git文件进行任何手…...
正则表达式基本语法和Java中的简单使用
先来个例子 public static final Pattern CHINESE_PATTERN Pattern.compile("[\\u4e00-\\u9fa5]"); / 检测字符串是否包含汉字 String text "Hello 世界"; boolean hasChinese CHINESE_PATTERN.matcher(text).find(); // 返回 true// 提取所有汉字 Mat…...
【大模型】什么是循环神经网络(RNNs)
在人工智能(AI)的世界里,**循环神经网络(Recurrent Neural Networks, RNNs)**是一种非常强大的工具,特别适合处理序列数据。无论是语言、时间序列还是音乐,RNNs都能帮助我们理解和预测这些数据的…...
Leetcode 交错字符串
java solution class Solution {public boolean isInterleave(String s1, String s2, String s3) {//首先获取这三个字符串的长度int m s1.length();int n s2.length();int l s3.length();if(m n ! l) return false;//创建dp数组,dp[i][j]其含义是s3的前ij个字符是否可以由…...
Vue动态绑定:文本框、单选按钮、下拉列表、多选按钮
Vue 指令系列文章: 《Vue插值:双大括号标签、v-text、v-html、v-bind 指令》 《Vue指令:v-cloak、v-once、v-pre 指令》 《Vue条件判断:v-if、v-else、v-else-if、v-show 指令》 《Vue循环遍历:v-for 指令》 《Vue事件处理:v-on 指令》 《Vue表单元素绑定:v-model 指令》…...
MySQL - 数据库基础操作
SQL语句 结构化查询语言(Structured Query Language),在关系型数据库上执行数据操作、数据检索以及数据维护的标准语言。 分类 DDL 数据定义语言(Data Definition Language),定义对数据库对象(库、表、列、索引)的操作。 DML 数据操作语言(Data Manip…...
从入门到精通:SQL注入防御与攻防实战——红队如何突破,蓝队如何应对!
引言:为什么SQL注入攻击依然如此强大? SQL注入(SQL Injection)是最古老且最常见的Web应用漏洞之一。尽管很多公司和组织都已经采取了WAF、防火墙、数据库隔离等防护措施,但SQL注入依然在许多情况下能够突破防线&#…...
关于优麒麟ukylin如何更换清华源以及ubuntu24.04安装gcc-i686-linux-gnu找不到包的问题
打算把这个文章当成一个调试Linux bug的汇总,会持续更新 1、关于优麒麟ukylin如何更换清华源 (1)首先打开命令行,切换root权限 su root 输入密码 如果第一次使用ubuntu会提示密码不正确,输入 sudo passwd root …...
Spring Boot 自定义 Starter 组件的技术指南
1、简述 Spring Boot 通过 Starter 机制,让开发者可以快速集成第三方组件。在企业级开发中,我们常常需要封装自己的 Starter 组件,以提高代码复用性,简化配置,并实现可插拔的模块化开发。 Spring Boot Starter 机制 …...
基于Spring Boot的ONLY在线商城系统设计与实现的设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
HarmonyOS 之 @Require 装饰器自学指南
在 HarmonyOS 应用开发工作中,我频繁碰到组件初始化传参校验的难题。在复杂的组件嵌套里,要是无法确保必要参数在构造时准确传入,就极易引发运行时错误,而且排查起来费时费力。一次偶然的机会,我接触到了 Require 装饰…...
【Unity】 HTFramework框架(六十三)SerializableDictionary可序列化字典
更新日期:2025年3月26日。 Github 仓库:https://github.com/SaiTingHu/HTFramework Gitee 仓库:https://gitee.com/SaiTingHu/HTFramework 索引 一、SerializableDictionary可序列化字典1.使用SerializableDictionary2.实现思路 二、Serializ…...
JavaScript的性能优化指导
JavaScript 的性能优化可以从多个层面入手,涵盖代码执行效率、内存管理、DOM 操作、网络请求等。以下是一些关键优化策略: 一、代码执行优化 减少作用域链查找 避免在循环中频繁访问全局变量或深层嵌套的属性,将其缓存到局部变量中。 // 优化…...
如何在 Vue 项目中使用v - for指令进行列表渲染,如何优化其性能?
大白话如何在 Vue 项目中使用v - for指令进行列表渲染,如何优化其性能? 在Vue项目里,咱们常常会碰到要把一组数据渲染成列表的状况。这时候,v-for指令就派上大用场啦!它能让咱们轻松地把数据数组里的每个元素渲染成对…...
Notepad++ 替换 换行符 为 逗号
多行转一行,逗号分隔 SPO2025032575773 SPO2025032575772 SPO2025032575771 SPO2025032575771 SPO2025032575770为了方便快速替换,我们需要先知道这样类型的数据都存在哪些换行符。 点击【视图】-【显示符号】-【显示行尾符】 对于显示的行尾换行符【C…...
《基于机器学习发电数据电量预测》开题报告
个人主页:大数据蟒行探索者 目录 一、选题背景、研究意义及文献综述 (一)选题背景 (二)选题意义 (三)文献综述 1. 国内外研究现状 2. 未来方向展望 二、研究的基本内容,拟解…...
【Linux】MAC帧
目录 一、MAC帧 (一)IP地址和MAC地址 (二)MAC帧格式 (三)MTU对IP协议的影响、 (四)MTU对UDP协议的影响 (五)MTU对TCP协议的影响 二、以太网协议 &…...
企业入驻成都国际数字影像产业园,可享150多项专业服务
企业入驻成都国际数字影像产业园,可享150多项专业服务 全方位赋能,助力影像企业腾飞 入驻成都国际数字影像产业园,企业将获得一个涵盖超过150项专业服务的全周期、一站式支持体系,旨在精准解决企业发展各阶段的核心需求…...