Simpleperf 使用
////////////////////////////////////////////////////////////谈到Android上的性能剖析很多人会想到TraceViewSysTrace。TraceView擅长Method Tracing与IDE集成使用方便不过有时候它的误差让人无法忍受SysTrace的牛逼之处在于它可以给出整个系统的一些关键模块的性能信息因此用途广泛虽然它也支持分析自定义模块但是使用起来稍显复杂。事实上在AOSP中有另外一个性能剖析工具不为人知这个安静的小可爱就是今天要介绍的主角—— simpleperf。我们先来看看它的介绍Simpleperf is a native profiling tool for Android. Its command-line interface supports broadly the same options as the linux-tools perf, but also supports various Android-specific improvements.native profiling是不是很心动至于simpleperf的原理简单来说现代CPU一般都带有一个叫做性能监视单元PMU的组件这个硬件能够记录诸如cpu周期数、执行的指令数、缓存失效次数等等关键信息Linux内核对这个硬件做了一层封装通过 perf_event_open 系统调用把接口暴露给用户空间这就是simpleperf工具的由来。简介和原理都表明这个工具貌似很牛逼接下来我们就试一试。首先把AOSP上的源码下载下来点我。simpleperf是一个命令行工具与systrace不同的是它的工具集包涵client端和host端client端运行在Android系统上负责收集性能数据host端则运行在你的开发机上负责对数据进行分析和可视化。这些可执行文件在下载后的bin文件夹的android和win/mac/linux下整个工具链使用起来相对复杂所幸simpleperf的创造者提供了一个炒鸡傻瓜的使用脚本使用起来毫不费力非常方便这个脚本就是 app_profile.py。我们把 simpleperf 下载下来之后首先修改 app_profile.config 文件中的配置主要是以下几个字段# 待分析的app的包名需要是debuggable的 app_package_name # 分析的命令体验的话使用默认即可更详细的用途看文档。 record_options -e cpu-cycles:u -f 4000 -g --dump-symbols --duration 10 # 待分析app的主界面app_profile.py会通过am start 帮助开启app main_activity 然后在你的设备上安装待分析的App要注意的是这个App必须是debuggable的在AndroidManifest中把debuggable设置为true即可。接下来就可以直接通过python app_profile.py进行分析了这个脚本帮你完成了simpleperf下载权限设置打开app导出数据等等一系列过程开始分析之后就可以对App进行操作在设置好的时间之后就会停止分析跟SysTrace一样。分析完毕之后脚本会自动把分析数据从设备上pull下来并存放在当前目录下叫 perf.data。接下来就是分析数据了原始的数据是一个文本文件长这样0.00% 0.00% ORDERED_THREAD_ 17046 18210 /system/lib/libart.so art::Mutex::ExclusiveLock(art::Thread*) | -- art::Mutex::ExclusiveLock(art::Thread*) 0.00% 0.00% AsyncTaskExecut 17046 18216 /system/lib/libart.so art::Monitor::Lock(art::Thread*) | -- art::Monitor::Lock(art::Thread*) | |--52.01%-- art::Mutex::ExclusiveLock(art::Thread*) | --0.54%-- art::Mutex::ExclusiveUnlock(art::Thread*)嵌套如果过深基本就看不懂了所幸我们有另外一个分析脚本直接运行python report.py -g会启动一个GUI显示分析得到的数据这个GUI使用python的tk写的实话说长得比较丑。。简单观察分析图可以知道的确支持native profilinggui和TraceView差不多比较直观但是指标没有TraceView多。另外这个工具由于硬件直接支持对性能的影响非常小光是这一点就好顶赞了。你以为这就完了No这玩意儿还支持火焰图! 如果你不知道火焰图为何物建议看看这篇文章 动态追踪技术漫谈。然后要绘制火焰图我们需要借助 FlameGraph 这个工具clone下来之后里面的脚本就可以直接使用了。perl脚本windows系统需要安装Perl语言的支持接下来我们执行命令$python report_sample.py out.perf $stackcollapse-perf.pl out.perf out.folded $./flamegraph.pl out.folded graph.svg我们用Chrome浏览器打开这个 graph.svg 即可得到火焰图通过火焰图我们能非常直观地看到性能的瓶颈对于分析性能问题很有帮助相信这个图已经说明一切了。////////////////////////////////////////////////////////////通用技巧这里有一些技巧给有root权限的Android系统开发者:运行adb root后, simpleperf可用于分析系统范围内任何进程。如果不是在主分支上工作建议使用AOSP main中最新的simpleperf。脚本位置在system/extras/simpleperf/scripts二进制程序在system/extras/simpleperf/scripts/bin/android.推荐使用app_profiler.py抓trace然后用report_html.py生成html报告。 下面是一个示例。# Record surfaceflinger process for 10 seconds with dwarf based call graph. More examples are in # scripts reference in the doc. $ python app_profiler.py -np surfaceflinger -r -g --duration 10 # Generate html report. $ python report_html.py从 Android O 开始系统库默认有符号表我们不需要用$ANDROID_PRODUCT_OUT/symbols中未striped二进制文件来抓了。 但是在报告中添加源代码和反汇编(带有行号)时需要它们。下面是一个例子。# Doing recording with app_profiler.py or simpleperf on device, and generates perf.data on host. $ python app_profiler.py -np surfaceflinger -r --call-graph fp --duration 10 # Collect unstripped binaries from $ANDROID_PRODUCT_OUT/symbols to binary_cache/. $ python binary_cache_builder.py -lib $ANDROID_PRODUCT_OUT/symbols # Report source code and disassembly. Disassembling all binaries is slow, so its better to add # --binary_filter option to only disassemble selected binaries. $ python report_html.py --add_source_code --source_dirs $ANDROID_BUILD_TOP --add_disassembly \ --binary_filter surfaceflinger.so在system_server进程上抓simpleperf有时我们希望在发生特殊情况时抓系统进程。在这种情况下我们可以在检测到情况的点处添加SimplEperf的代码。关掉selinuxadb shell setenforce 0。因为selinux只允许simpleperf在shell或debuggable/profileable 应用中使用。在检测到特殊情况的地方添加下面的代码。try { // for capability check Os.prctl(OsConstants.PR_CAP_AMBIENT, OsConstants.PR_CAP_AMBIENT_RAISE, OsConstants.CAP_SYS_PTRACE, 0, 0); // Write to /data instead of /data/local/tmp. Because /data can be written by system user. Runtime.getRuntime().exec(/system/bin/simpleperf record -g -p String.valueOf(Process.myPid()) -o /data/perf.data --duration 30 --log-to-android-buffer --log verbose); } catch (Exception e) { Slog.e(TAG, error while running simpleperf); e.printStackTrace(); }硬件 PMU 计数器限制监视指令和缓存相关的性能事件时 (在list命令列出的hw/cache/raw/pmu 类别)这些事件被映射到每个cpu核心上的PMU计数器。但每个核心只有有限数量的PMU计数器。如果事件数量 PMU计数器的数量然后计数器在事件之间多路复用这可能不是我们想要的。在Pixel设备上每个核上的PMU计数器的数量通常是7个其中4个被内核用于监视内存延迟。所以只有3个计数器可用。可以同时监控最多3个PMU事件。要监视3个以上的事件可以使用--use-devfreq-counters选项借用内核使用的计数器。////////////////////////////////////////////////////////////定义Simpleperf 是Google随NDK一起发布的一款profile工具注从NDK r13开始它是针对Android平台的一个 native 层性能分析工具。使用步骤本篇是分析运行在android设备下的程序1. 将NDK中Simpleperf工具的可执行程序 push 到手机上cd NDK/simpleperf/bin/android/对应的版本根据被测程序和CPU来选择对应的版本例如 我的路径是 /home/hqb/Android/Sdk/ndk/21.3.6528147/simpleperf/bin/android/arm64cd /home/hqb/Android/Sdk/ndk/21.3.6528147/simpleperf/bin/android/arm64 adb push simpleperf /data/local/tmp adb shell chmod 777 /data/local/tmp/simpleperf2. 启动手机上的被测程序ps 出该程序的进程IDadb shell ps -ef | grep 需要分析的应用程序包名3. 使用Simpleperf工具进行分析1record-记录运行结果数据adb shell /data/local/tmp/simpleperf record -p 进程号 --duration 持续的时间秒为单位 -o 输出文件名称 --call-graph fp --call-graph dwarf 用在32位系统中64位则采用--call-graph fp例子adb shell /data/local/tmp/simpleperf record -p 4844 --duration 10 -o /data/local/tmp/perf.data --call-graph fp输出simpleperf I cmd_record.cpp:658] Samples recorded: 12013. Samples lost: 0.2报告结果数据adb shell /data/local/tmp/simpleperf report -i /data/local/tmp/perf.data -o /data/local/tmp/perf_report.txt4. 解析火焰图1将data文件和txt文件从手机pull到电脑电脑上新建simpleperf_test目录例子/home/hqb/simpleperf_testmkdir simpleperf_test adb pull /data/local/tmp/perf.data /home/hqb/simpleperf_test adb pull /data/local/tmp/perf_report.txt /home/hqb/simpleperf_test经常使用simpleperf就用alias设置别名vim ~/.bashrc alias pfpython /home/hqb/Android/Sdk/ndk/21.3.6528147/simpleperf/report_html.py source ~/.bashrc2data格式转化成html格式cd /home/hqb/simpleperf_test //设置别名 pf -i ./perf.data -o ./perf.html //如果不设置别名 python /home/hqb/Android/Sdk/ndk/21.3.6528147/simpleperf/report_html.py -i ./perf.data -o ./perf.html3下载FlameGraph到simpleperf_test目录下将simpleperf复制到simpleperf_test目录下git clone https://github.com/brendangregg/FlameGraph.git chmod 777 FlameGraph/flamegraph.pl chmod 777 FlameGraph/stackcollapse-perf.pl cp -r /home/hqb/Android/Sdk/ndk/21.3.6528147/simpleperf /home/hqb/simpleperf_test4生成火焰图cd /home/hqb/simpleperf_test python ./simpleperf/report_sample.py out.perf ./FlameGraph/stackcollapse-perf.pl out.perf out.folded ./FlameGraph/flamegraph.pl out.folded out.svgout.svg就是最后得到的火焰图用浏览器打开就可以看/////////////////////////////////////////////////////////////Android Studio 包含 Simpleperf 的图形前端记录在使用 CPU Profiler 检查 CPU Activity 中。大多数用户更喜欢使用该图形前端而不是直接使用 Simpleperf。如果您更喜欢使用命令行可以直接使用 Simpleperf。Simpleperf 是一个通用的命令行 CPU 性能剖析工具包含在面向 Mac、Linux 和 Windows 的 NDK 中。Simpleperf包含两部分simpleperf可执行文件和Python脚本。路径Android/sdk/ndk/20.0.5594570/simpleperfsimpleperf可执行文件的工作方式类似于linux-tools-perf但是具有针对Android分析环境的一些特定功能详情参看simpleperfPython 脚本根据功能划成如下三部分:用于记录事件的脚本, like app_profiler.py, run_simpleperf_without_usb_connection.py.用于报告的脚本, like report.py, report_html.py, inferno.用于分析 profiling data的脚本, like simpleperf_report_lib.py.1.事件2.分析Android App性能分析一个 Android 应用的性能可以按照如下三步走准备一个要分析的APP.例如Google官方的实例$ git clone https://android.googlesource.com/platform/system/extras $ cd extras/simpleperf/demo # Open SimpleperfExamplesWithNative project with Android studio, and build this project # successfully, otherwise the ./gradlew command below will fail. $ cd SimpleperfExampleWithNative # On windows, use gradlew instead. $ ./gradlew clean assemble $ adb install -r app/build/outputs/apk/profiling/app-profiling.apk2.抓取性能数据python app_profiler.py -p com.example.simpleperf.simpleperfexamplewithnative --compile_java_code -a .MixActivity --lib app/build/intermediates/cmake/debug/obj/arm64-v8a/3.分析性能数据python report_html.py4.查看对应的性能分析数据通过数据我们可以看到各个线程占用的CPU时钟周期/////////////////////////////////////////////////////////////了多少事件的摘要。以下是它的工作原理给定用户选项simpleperf通过对linux内核进行系统调用来启用分析Linux 内核在调度到被分析进程时启用计数器分析之后simpleperf从内核读取计数器并报告计数器摘要。Record命令在一段时间内记录剖析进程的样本。它的工作原理如下给定用户选项simpleperf通过对linux内核进行系统调用来启用分析Simpleperf在simpleperf和linux内核之间创建映射缓冲区Linux内核在调度到被分析进程时启用计数器每次给定数量的事件发生时linux内核将样本转储到映射缓冲区Simpleperf从映射缓冲区读取样本并生成perf.data。Report命令读取perf.data文件及所有被剖析进程用到的共享库并输出一份报告展示时间消耗在了哪里。Simpleperf的使用尽管不推荐使用一键脚本但得益于Simpleperf的命令不多使用起来也很简单快捷。文件准备将simpleperf可执行文件传输到Android设备上:adb push 文件源地址 文件目的地址可执行文件都存储在bin/android/目录下可自行获取。性能分析在性能分析前首先启动需要分析的APP获取APP的进程号adb shell am start -n 包名/启动程序adb shell pidof 包名接下来就可以使用命令三连击了adb shellcd simpleperf所在目录./simpleperf stat [options] [command [command-args]]./simpleperf record [options] [command [command-args]]./simpleperf report [options]stat命令获取一段时间内已分析进程中发生的事件数摘要。 最常使用的选项为./simpleperf stat -p 进程号 --duration 检测进程的持续时间(秒)1record命令记录一段时间内已分析进程的样本这是simpleperf的主命令。最常使用的选项为./simpleperf record -p 进程号 -o 输出文件(默认perf.data) --duration 监测进程的持续时间(秒)1需要注意的是如果出现Access to kernel symbol addresses is restricted的警告需要使用一下命令来取消echo 0/proc/sys/kernel/kptr_restrictreport命令读取perf.data文件(由simpleperf record创建)并显示报告表明花费时间的地方。最常使用的选项为./simpleperf report --dsos 选定动态共享对象(so库) -f 记录文件(默认perf.data) --sort 用于排序和打印报告的键 -n注意点如果使用report命令进行查找的时候发现so现实的Symbol都是地址而不是函数内容。这多数是因为在安卓编译的时候设备上使用的so库已经被strip过也就是说已经抛离了.symbol段的内容。那么我们需要将带有Symbol信息的so下载到设备上。同时需要将so放置到perf.data中记录的相同的路径(否则simpleperf无法找到它)。如果找不到路径可以在perf.data文件中直接搜索需要选定的so库的名称即可查看到路径。实例设备上执行命令./simpleperf stat -p 5932 --duration 10./simpleperf record -p 5932 -o dms.data --duration 10./simpleperf report --dsos /data/app/com.hobot.dms.sample-1/lib/arm/libhobot_dms.so --sort comm,pid,tid,symbol -n通过report命令可以看到主要是集中在libhobot_dms.so中。但是显示的都是地址并非函数调用。这是因为Android的so库已经抛离了.symbol段的内容。可以重新指定完整的so文件。将perf.data从设备上拷贝下来传输到Linux开发机上执行命令./bin/linux/x86_64/simpleperf report --dsos /data/app/com.hobot.dms.sample-1/lib/arm/libhobot_dms.so --sort comm,pid,tid,symbol1/////////////////////////////////////////////////////////////使用 Android SimplePerf生成的网页无法打开或加载的问题一直困扰了很多使用 Simpleperf 的 Android 性能开发工作者。这是因为本地生成的页面依赖一些 JavaScript 文件国内的网络访问不到 CDN 源此时需要将这些源替换成国内可以访问的源。以下是两种解决办法修改 Simpleperf 生成的 HTML 文件将 JavaScript 源替换成国内网络可以访问到的源修改 Python 使其在生成 HTML 前完成 JavaScript 源的替换工作。这两种方法前者仅一次生效后者永久生效。修改 HTML 文件因为这个方法是使用了 Simpleperf 的 Python 生成 HTML 后再去做替换所以最大的弊端就是每次都需要手动替换。具体的替换步骤如下使用记事本软件打开 HTML 文件我本地这个文件名字叫report.html按照如下的方式进行替换替换前htmlheadlink relstylesheet typetext/css hrefhttps://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css/link link relstylesheet typetext/css hrefhttps://cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css/link script srchttps://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js/script script srchttps://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js/script script srchttps://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js/script script srchttps://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js/script script srchttps://cdn.datatables.net/1.10.19/js/dataTables.bootstrap4.min.js/script script srchttps://www.gstatic.com/charts/loader.js/script scriptgoogle.charts.load(current, {packages: [corechart, table]});/script style typetext/css .colForLine { width: 50px; } .colForCount { width: 100px; } .tableCell { font-size: 17px; } .boldTableCell { font-weight: bold; font-size: 17px; } /style /head bodyscript替换后htmlheadlink relstylesheet typetext/css hrefhttps://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.1.2/css/bootstrap.min.css/link link relstylesheet typetext/css hrefhttps://cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css/link script srchttps://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js/script script srchttps://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js/script script srchttps://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.1.2/js/bootstrap.min.js/script script srchttps://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js/script script srchttps://cdn.datatables.net/1.10.19/js/dataTables.bootstrap4.min.js/script script srchttps://www.gstatic.com/charts/loader.js/script scriptgoogle.charts.load(current, {packages: [corechart, table]});/script style typetext/css .colForLine { width: 50px; } .colForCount { width: 100px; } .tableCell { font-size: 17px; } .boldTableCell { font-weight: bold; font-size: 17px; } /style /head bodyscript然后刷新页面即可正确渲染数据替换成国内源后渲染速度加倍修改 Python 脚本因为这个方法是在 HTML 生成之前就做了替换所以最大的优点就是不需要每次手动替换。在获取到perf.data 文件后我们会使用 Simpleperf 中的 report_html.py 脚本进行渲染出 report.html 文件python ./report_html.py -i D:\temp\perf.data -o D:\temp\report.html因此需要修改的是 report_html.py 文件。具体步骤如下使用记事本打开 report_html.py搜索关键字“URLS”找到 JavaScript 按照如下的方式进行替换替换前URLS { jquery: https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js, bootstrap4-css: https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css, bootstrap4-popper: https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js, bootstrap4: https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js, dataTable: https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js, dataTable-bootstrap4: https://cdn.datatables.net/1.10.19/js/dataTables.bootstrap4.min.js, dataTable-css: https://cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css, gstatic-charts: https://www.gstatic.com/charts/loader.js, }替换后URLS { jquery: https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js, bootstrap4-css: https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.1.2/css/bootstrap.min.css, bootstrap4-popper: https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js, bootstrap4: https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.1.2/js/bootstrap.min.js, dataTable: https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js, dataTable-bootstrap4: https://cdn.datatables.net/1.10.19/js/dataTables.bootstrap4.min.js, dataTable-css: https://cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css, gstatic-charts: https://www.gstatic.com/charts/loader.js, }最后再次执行命令即可正确渲染数据替换成国内源后渲染速度加倍//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

相关新闻

TI bq77910A BMS评估板解析:从硬件保护到量产设计的工程实践

TI bq77910A BMS评估板解析:从硬件保护到量产设计的工程实践

1. 项目概述与核心价值 在开发基于多节串联锂电池的应用时,比如电动工具、储能电源或者轻型电动车,工程师面临的最大挑战之一就是电池管理系统的设计与验证。电池管理系统,也就是我们常说的BMS,它不仅仅是给电池充放电那么简单&am…

2026/10/6 19:07:38 阅读更多 →
【工具-Visual Studio Code】

【工具-Visual Studio Code】

工具-Visual Studio Code使用■ Windos11安装VSCode■ Ubuntu安装VSCode■ Ubuntu安装VSCode-第二种方法■VSCode C/C■ 1. vscode 安装扩展■ 2. C编译器安装■ 3. Win10下VScodeMSVCCMake搭建C开发环境■ 3.1. VScode安装必要的插件■ 3.2.■ 3.3. 测试■ 4 VScode配置 C/C 环…

2026/10/11 11:27:09 阅读更多 →
职场汇报能力四点

职场汇报能力四点

做好职场汇报就抓四个点: 1. 别跑偏核心:别光自夸晒功劳,本质是给领导递有用信息帮他做决策,领导更在意业绩能不能持续、后续业务怎么走 2. 内容按固定逻辑走:讲清成果、成果的业务价值、成败经验、行业业务洞察&#…

2026/10/8 17:12:37 阅读更多 →

最新新闻

Kiln AI Server Python 客户端库使用指南:同步/异步 API 调用与高级定制实战

Kiln AI Server Python 客户端库使用指南:同步/异步 API 调用与高级定制实战

人工智能AI 应用AI 评测RAG微调提示工程开发工具桌面应用 【免费下载链接】Kiln Build, Evaluate, and Optimize AI Systems. Includes evals, RAG, agents, fine-tuning, synthetic data generation, dataset management, MCP, and more. 项目地址: https://gitcod…

2026/10/14 18:22:46 阅读更多 →
鸿蒙应用内添加服务卡片到桌面:权限配置至formId管理的完整实践

鸿蒙应用内添加服务卡片到桌面:权限配置至formId管理的完整实践

前两天有个开发者在我写的卡片文章下面留言:应用里能不能直接触发“添加卡片到桌面”?用户根本不知道要长按桌面再选卡片,好多功能做出来都没人发现。这个问题其实问的人挺多的。鸿蒙的服务卡片虽然好用,但系统默认的添加路径藏在…

2026/10/14 18:22:46 阅读更多 →
自制轻量级单片机UI框架:低资源平台的架构设计与内存优化

自制轻量级单片机UI框架:低资源平台的架构设计与内存优化

我最早动起"自制轻量级单片机UI框架"这个念头,是在一个被现成UI库逼疯的下午。手里这块板子的MCU只给了64KB Flash和16KB RAM,产品需求却要一个带按钮、进度条和多级菜单的界面。我试着把一个开源UI库编进去,编译完一看&#xff0c…

2026/10/14 18:22:46 阅读更多 →
51单片机红外遥控NEC解码与波形显示方案

51单片机红外遥控NEC解码与波形显示方案

简介:这是一套基于51单片机的红外遥控解码与波形显示项目资料,面向电子爱好者、嵌入式初学者以及单片机课程设计/毕业设计人群,解决从红外信号接收、脉冲解码到LCD波形显示的全流程实现问题。压缩包共38个文件、9.68MB,涵盖C语言源…

2026/10/14 18:22:46 阅读更多 →
uIP TCP/IP协议栈实战:从Client到Server的嵌入式移植全解析

uIP TCP/IP协议栈实战:从Client到Server的嵌入式移植全解析

简介:基于uIP协议栈的TCP客户端与服务器程序,源自ALIENTEK战舰STM32开发板第52章,面向使用STM32与ENC28J60进行嵌入式网络通信的开发者。资源包含完整工程与配套文档,共223个文件,以C语言源文件(76个.c&…

2026/10/14 18:22:46 阅读更多 →
JavaScript sort排序原理与常见陷阱解析

JavaScript sort排序原理与常见陷阱解析

先说个我自己的真实经历。有次帮同事排查一个列表排序问题,数据是几组数字,他写了 arr.sort() ,结果排出来是 [1, 10, 2, 22, 3] 这种完全看不懂的顺序。他盯着屏幕看了半天,第一反应是"sort排序坏了"。其实不是坏了…

2026/10/14 18:21:46 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →