记一次性能优化 reclaim

本文深入探讨了一个项目在处理大量数据时遇到的问题,包括性能瓶颈、SQL优化策略以及避免常见错误的方法。通过调整业务逻辑、改进SQL语句结构、合理使用批处理和内存管理,作者成功提升了数据处理效率。文章还总结了优化大数据处理的六大关键点,为同类问题提供了实用的解决方案。

项目的开发终于只剩了我一个,自己瞎搞终于抠完了,发现将近100万的数据量根本跑不动,页面就剩一个圈圈在转,于是只能改代码优化.

逻辑中有先把符合规则的数据select 出来,然后处理一下再一条条update和insert.

首先把update 写成batch update

//                for(Match match:updateMatchList){
//                    executor.update("MATCH.updateMatch", match);
//                    batch++;
//                    if(batch==500){
//                        LOG.info(""+i);
//                        executor.executeBatch();       
//                        batch=0;
//                        i++;
//                    }
//                }

 

把insert into 写成insert into ()values(...),(...),(...)的形式, 改善很小没啥用

 

2.然后想到改sql, 希望把n个sql并成一条

于是把select的记录把id取出拼成数组,写成update ... where id in(...)的形式,但这样由于id太多,sql太长,结果超出了mysql的允许大小.并且一次取出超过100000条数据在内存会out of menory,后来又把这些每50000条记录拆分操作,没报错但还是很慢.

 

    <insert id="saveMatchClassfication" parameterClass="java.util.List">
        insert into matchClassfication (
            match_id,
            class_id,
            priority,
            created_at
        )values
       
        <iterate conjunction =",">
            <![CDATA[
            (#matches[].id#, #matches[].classId#, #matches[].priority#, now())
            ]]>
        </iterate>
       
    </insert>
   

    <update id="updateMatchClassIdBatch" parameterClass="java.util.HashMap">
        update matchedVideo
        set class_id=#classId#
        where id in
              <iterate close=")" open="("   conjunction="," property="idList">
                <![CDATA[ 
                 #idList[]#  
                ]]>  
            </iterate>        
    </update>

 

3.后来受同事启发一开始就不应该把记录先取出再处理,而应该直接用sql处理, 这样既不需要update上万次也没有out of menory的风险.于是稍微调增额业务处理的顺序,然后用两句sql搞定.然后发现数据量大sql的效率极低,甚至低于修改前.后来检查了一下sql,发现在where 中用了 is null,这样不会走索引,百万级数据会直接卡死.于是又修改了业务处理的顺序,避免这种问题.

 

4. 总结 :

  a.能优化逻辑先优化逻辑,避免把表中大量数据一次取出的情况

  b.避免一大批数据要一条一条update/insert的情况

  c.写sql时避免关联很大的表,最好能用表中的一部分数据取出成一个新表再做关联

  d.对于索引失效的情况得注意

  e.适时用存储过程等做优化

  f.对于读操作数据量大时要用缓存,避免每次都和数据库打交道

  g.若还是很慢无法忍受,只能改成异步操作,每次用户点完直接返回并加上恰当的提示不至于让用户一直等在那无法操作.

<think> 首先,用户的问题是如何使用systrace分析mm_vmscan_direct_reclaim出现的原因。从引用中,我有一些相关信息,特别是引用[1]和[^2],它们讨论内存回收和监控事件。 引用[1]提到如何监控内存问题:通过抬高watermark、提高回收效率,以及监控IO使用率、读写速度、D状态进程堆栈信息等。它还提到使用ftrace监控vmscan和writeback事件。 引用[^2]列出了一些事件,包括vmscan相关的事件,如nr_vmscan_write、nr_vmscan_immediate_reclaim等,以及其他内存相关事件。 用户的问题是针对systrace分析mm_vmscan_direct_reclaim,这是一个Linux内核事件,表示直接内存回收(direct reclaim),通常发生在内存分配时,内存不足,需要直接回收页面。 我的回答需要: - 使用中文。 - 结构清晰,逐步帮助用户解决问题。 - 确保真实可靠。 - 在行内数学表达式使用$...$格式,但在这个上下文中,可能不需要数学表达式,除非涉及公式。 - 独立公式使用$$...$$格式。 - 生成相关问题。 - 在引用段落末尾添加引用标识,如[^1]。 步骤: 1. **理解用户需求**:用户想用systrace来分析为什么mm_vmscan_direct_reclaim发生。systrace是一个Android性能分析工具,基于ftrace。 2. **关键点**: - mm_vmscan_direct_reclaim是内核事件,表示直接内存回收。 - 原因通常包括内存压力、页面缓存不足等。 - 使用systrace捕获相关事件来诊断。 3. **从引用中提取信息**: - 引用[1]:提到监控vmscan事件,使用ftrace启用writeback和vmscan监控。 - 引用[^2]:列出事件,包括vmscan相关事件。 4. **结构化回答**: - **引言**:解释mm_vmscan_direct_reclaim是什么。 - **步骤**:如何设置systrace来捕获这个事件。 - **分析**:在systrace输出中如何识别原因。 - **常见原因**:列出可能的原因。 - **生成相关问题**:在末尾添加相关问题。 5. **确保真实可靠**:基于Linux内核和Android systrace知识。 - systrace命令:`systrace.py --time=10 -o trace.html sched freq idle am wm gfx view binder_driver irq workq ss vmscan mmc sync`,其中vmscan是需要的类别。 - 事件:mm_vmscan_direct_reclaim可能在vmscan事件中。 6. **引用处理**: - 在回答中适当引用[^1]和[^2],例如当提到监控方法或事件列表时。 - 引用标识加在段落末尾。 7. **数学表达式**:在这个主题中,可能不需要太多数学,但如果有公式,如内存使用公式,使用正确格式。 8. **相关问题**:在末尾生成3-4个相关问题,使用§§相关问题§§格式。 完整回答大纲: - **什么是mm_vmscan_direct_reclaim?** - 解释:直接内存回收发生在内存分配时,当系统内存不足,需要回收页面。 - **如何使用systrace捕获这个事件?** - 设置systrace命令,启用vmscan类别。 - 示例命令:`systrace.py --time=10 -o trace.html vmscan` - 引用[1]提到启用tracing:`echo 1 > /sys/kernel/debug/tracing/events/vmscan/enable` 等。 - **在systrace输出中分析** - 查看事件发生时间点,关联其他事件如IO、CPU负载。 - 常见原因:高内存使用、低内存水印、频繁内存分配。 - **常见原因和解决方案** - 如引用[1]所说,抬高watermark或优化回收效率。 - **相关问题生成** 生成相关问题: 1. mm_vmscan_direct_reclaim对系统性能有什么影响? 2. 如何优化内存以减少直接内存回收的发生? 3. systrace中还有哪些其他事件与内存回收相关? 确保回答清晰、逐步。 </think> ### 使用systrace分析mm_vmscan_direct_reclaim出现的原因 `mm_vmscan_direct_reclaim` 是Linux内核中的一个事件,表示系统在直接内存回收(direct reclaim)过程中触发的页面扫描。这通常发生在内存分配请求时,系统无法从空闲列表获取足够页面,必须直接回收内存以释放空间[^1]。以下是逐步分析原因的方法,基于systrace(一个基于ftrace的Android性能分析工具)。整个过程需在设备上启用root权限。 #### 1. **设置systrace捕获vmscan事件** - **启用vmscan追踪**:在设备上通过ADB执行命令,激活内核的vmscan事件监控。这包括`mm_vmscan_direct_reclaim`事件。 ```bash adb shell "echo 1 > /sys/kernel/debug/tracing/events/vmscan/enable" adb shell "echo 1 > /sys/kernel/debug/tracing/tracing_on" ``` 此步骤确保systrace能录内存回收相关事件[^1]。 - **运行systrace命令**:在主机端使用systrace捕获数据。示例命令: ```bash systrace.py --time=10 -o trace.html vmscan mmc sync workq sched freq ``` - `--time=10`: 捕获10秒数据。 - `-o trace.html`: 输出到HTML文件。 - 类别选择:`vmscan`(核心)、`mmc`(存储IO)、`sync`(同步)、`workq`(工作队列)、`sched`(CPU调度),这些关联事件帮助分析内存回收原因[^2]。 #### 2. **在systrace输出中识别事件** - **打开trace.html**:用浏览器加载文件,搜索`mm_vmscan_direct_reclaim`事件。 - **分析事件上下文**: - **时间线视图**:观察事件发生的时间点。如果事件密集出现(如每秒多次),表明内存压力高。 - **关联事件**: - 检查是否有高IO事件(如`mmc_read`或`writeback`),这可能表示回收因IO瓶颈而卡顿(例如,存储速度慢导致页面回写延迟)[^1]。 - 查看CPU调度:如果`sched`事件显示进程频繁处于`D-state`(不可中断睡眠),可能阻塞回收过程。 - 监控内存水印:事件附近如有`nr_free_pages`(空闲页面数)低于水印值,触发直接回收。 - 示例:在trace中,若`mm_vmscan_direct_reclaim`与`nr_dirty`(脏页数)峰值同步,说明脏页过多导致回收压力。 #### 3. **常见原因分析** 基于systrace数据,`mm_vmscan_direct_reclaim`的常见原因包括: - **内存不足**:空闲页面低于水印值(公式:$nr\_free\_pages < watermark\_min$),系统被迫直接回收。可通过`nr_free_pages`事件验证[^2]。 - **IO瓶颈**:存储性能差(如`mmc`延迟高),导致页面回写慢,回收效率低下。引用[1]提到,IO使用率监控可辅助诊断[^1]。 - **内存泄漏或过度分配**:应用频繁分配大内存(如`nr_alloc_batch`事件激增),超出系统承载。 - **回收效率低**:`vmscan`事件中如有`pgsteal_kswapd`(kswapd回收失败),可能因碎片化或算法问题。 #### 4. **优化建议** - **抬高内存水印**:修改`/proc/sys/vm/min_free_kbytes`增加空闲页面缓冲,减少直接回收触发频率[^1]。 - **优化IO**:使用更快存储或减少脏页(如调整`/proc/sys/vm/dirty_ratio`)。 - **监控工具补充**:结合`ftrace dump`和`kernelshark`解析微观过程,如抓取D状态进程堆栈[^1]。 - **代码级诊断**:在内核中添加tracepoint,输出更多回收细节(例如,回收页面类型)。 通过以上步骤,您可以在systrace中定位`mm_vmscan_direct_reclaim`的根本原因。实践中,建议在复现问题场景(如高负载测试)时捕获数据以提高准确性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值