• [问题求助] 【appcube】脚本中如何实现多线程?
    脚本中如何实现多线程?
  • [问题求助] 【产品】【EXCEL功能】重新安装后无法正常使用控件
    【功能模块】 升级到 3.0.3 以后,发现一些问题, 卸载后,又装了3.0.0, 发现无法正常使用。请帮助。 【操作步骤&问题现象】1、关闭EXCEL 控件发生错误。 日志如下。 2、【截图信息】【日志信息】(可选,上传日志内容或者附件)NOK][2022-07-14 10:09:08]完成执行[原子命令] [playbackScript.xml 第4行] 结束Excel进程 [结束Excel进程] [NOK] [RobotUncaughtError] [系统执行错误: 发生了未捕获异常,详情:ImportError(\"cannot import name 'EXCEL_SUFFIX' from 'com.huawei.antrobot.settings.robot_settings' (D:\\\\Program\\\\Studio\\\\Robot\\\\com\\\\huawei\\\\antrobot\\\\settings\\\\robot_settings.pyc)\")]
  • [技术干货] 鲲鹏性能分析工具基础知识
    鲲鹏性能分析工具工具的目标工具的功能工具的目标用户系统性能分析工具为软件开发人员,系统管理员/POC、人员提供两种维度的性能分析视角软件架构软件部署全景分析全景分析原理CPU重点指标解读内存重点指标解读存储IO重点指标解读网路IO重点指标分析解读重点系统配置解读进程/线程性能分析进程/进程性能分析原理重点指标分析解读热点函数分析热点函数分析原理热点函数分析举例微架构分析微架构处理分析原理微架构分析举例访存分析访存分析-访存统计分析访存分析-访存统计分析原理访存分析-Miss事件分析访存分析-Miss事件分析原理访存分析-伪共享分析访存分析-伪共享分析原理访存分析举例IO分析IO分析原理IO分析举例资源调度分析资源调度分析原理资源调度分析举例锁与等待分析HPC场景内存诊断内存诊断原理调优助手原理调优助手-系统配置调优助手-热点函数调优助手-系统性能调优助手-进程/线程性能Java性能分析
  • [技术干货] 第五讲:鲲鹏性能分析工具基础知识读书笔记-Devkit调优
    系统性能调优简单的说就是综合、全面的了解系统硬件、操作系统和应用软件的相关信息,分析其配置和运行情况,调节各模块之间的系统资源占用关系,实现整个系统的性能最大化,从而不断的满足业务需求。性能分析是一项复杂的系统化的工作,业界有非常多的性能分析小工具,专业分析系统各模块的性能,然而众多工具的使用不仅带来大量的学习成本、分析效率低下,更重要的是数据不能互通,无法全局分析,并且需要依靠非常娴熟的经验才能针对各模块的问题进行调优。开发者亟需更加全面、专业、智能化的系统调优工具。 01、工具简介DevKit性能分析工具正是为了满足上述需求而设计,DevKit性能分析工具是一个工具集,包含:系统性能分析工具、JAVA性能分析工具、系统诊断工具。鲲鹏性能分析工具有以下几点独特功能:1、基于鲲鹏处理器,提供硬件结合分析能力,采集和分析硬件性能指标,以及硬件性能在软件层的表现,让用户更加全面的了解整个系统的运行状况。2、系统化的分析建立各层指标之间的关联关系,并以用户视角呈现这些指标和关系,方便用户更易于发现问题。3、结合华为在鲲鹏处理器上的性能优化经验,给出优化思路和建议,帮忙用户快速定位和修复问题。4、实现分析过程管理,例如:优化结果对比、优化效果标记、优化过程记录等。系统性能分析工具为软件开发人员、系统管理员/POC人员提供两种维度的性能分析视角。 02、工具软件架构工具从软件逻辑上分成Analysis Server和Agent两大部分。Analysis Server,主要实现性能数据分析及分析结果呈现。Agent,主要实现性能数据采集。 03、功能原理系统性能分析工具提供3大模块9大主要功能:通用分析:采集和分析整个系统的软硬件配置信息、识别性能瓶颈,针对异常指标项提供优化建议(包含全景、进程/线程和热点函数分析);系统部件分析:针对系统主要部件(如:处理器、内存、存储等)暴露的硬件指标,结合系统软件运行指标,分析各部件的性能瓶颈(包含微架构、访存和I/O分析);专项分析:针对特定性能问题进行专题分析(包含资源调度、锁与等待和HPC分析)。其中全景分析、热点函数分析、资源调度分析是开发者最常使用的分析场景。全景分析——全面掌握系统配置和整体性能通过采集系统软硬件配置信息,以及系统的CPU、内存、存储IO、网络IO等资源的运行情况,获得对应的使用率、饱和度、错误次数等指标,以此识别系统性能瓶颈。针对部分系统指标项,将根据当前已有的基准值和优化经验提供优化建议。基于USE性能分析方法,针对系统CPU、内存、磁盘IO、网络IO等资源的运行情况,获得它们的使用率、饱和度、错误等指标,以此识别系统瓶颈。综合分析系统性能和系统配置情况,给出检测到的性能瓶颈点,并给出优化建议和修改方法。热点函数分析——直接定位到C/C++程序代码瓶颈点支持分析C/C++程序代码识别性能瓶颈,给出对应的热点函数以及源码和汇编指令的信息。通过冷/热火焰图展示函数的调用关系,发现优化路径。分析给出系统和应用的Top热点函数和热点模块,并给出优化建议,其中针对华为优化或实现的基础库、数据库等会给出详细的优化说明和下载链接。针对热点函数可以关联到它的汇编指令和源码,并且明确标识出热点指令或热点代码块,用户可以直接针对优化。资源调度分析——跟踪CPU核和进程状态切换情况基于CPU调度事件分析系统资源调度情况,包括:CPU核在各个时间点的运行状态、进程/线程在各个时间点的运行状态、进程/线程状态切换情况等,用户根据这些信息可以分析进程/线程是否存在大量的系统调用、不合理的锁或同步等,以此找到优化点。分析进程/线程调度信息,识别线程是否频繁上下文切换、CPU是否能及时调度等性能问题。分析进程/线程在NUMA节点的切换情况,对于频繁切换,给出绑核优化建议。分析CPU核在各个时间点的运行状态,如:idle、running等。如果是running状态,能关联在CPU核上运行的进程/线程信息。支持高亮显示某个线程在各个CPU核上的运行情况。分析进程/线程在各个时间点的运行状态,如:wait_blocked、wait_for_cpu和running,能方便识别频繁上下文切换的线程。
  • [DevKit] DevKit第三次作业-《锁长期等待》大作业
    锁长期等待---- pthread_mutex_long.c一、作业题目通过性能分析工具找出程序中加锁范围不合理的地方并解决二、操作前提在鲲鹏社区申请远程实验室,操作系统选择OpenEulerhttps://www.hikunpeng.com/zh/developer/devkit三、准备工作1、打开网页,找到测试程序 :pthread_mutex_long.c ,复制里面的内容到本地同名的文件里。注意:不要直接下载这个文件,只需要复制网页里面的内容,在本地vim新建一个pthread_mutex_long.c,然后把网页里面的内容拷贝进去。即可https://github.com/kunp e ngcompute/devkitdemo/blob/main/Hyper_tuner/testdemo/lock/pthread_mutex_long.c vim命令新建一个pthread_mutex_long.c然后拷贝网页里面的代码到此文件后,按:wq! 保存退出。2、授权文件:chmod 777 pthread_mutex_long.c3、编译程序:gcc -g pthread_mutex_long.c -o pthread_mutex_long -lpthread -lm && chmod 777 pthread_mutex_long4、绑核启动:taskset -c 0-1 ./pthread_mutex_long四、作业要求1、操作步骤截图越细越好,每张截图最好加上说明。2、通过性能分析工具发现环境中有性能问题的目标程序。3、发现可调优的目标程序后,修改代码,重新使用性能分析工具进行分析,相关指标有变化说明调优成功。五、操作步骤截图关键截图一:全景分析任务结果-性能tab通过cpu的相关指标看出cpu0 或 cpu1的 用户态使用率比较高。关键截图二:进程/线程性能分析任务结果-总览总览页签下查看各进程的CPU使用情况,发现启动命令为 ./pthread_mutex_long 的进程的用户态使用率高,这个正好也是我们启动的测试程序。关键截图三:资源调度分析任务结果-总览关键截图四:资源分析任务结果-进程/线程调度发现在采样期间两个线程之间的调度没有交集,没有平衡的相互交替运行,我们可以推断两个线程可能在抢占某个资源关键截图五:热点函数分析任务结果-总览测试程序的热点函数是 Func关键截图六:热点函数分析任务结果-热点函数源码通过对热点函数的源码分析,发现其中有一段业务逻辑并不涉及并发的场景,并且这块业务逻辑是Func函数中热度最高的,完全可以移到锁的范围之外去。注意:此时查看源码文件,需要执行1亿次循环,还要做N=100000次的平方根,所以就进入了耗时的循环。所以我们将float 字段迁移到循环的外面即可。关键截图七:代码优化前后优化前:优化后:然后重新编译和绑核启动,编译:gcc -g pthread_mutex_long.c -o pthread_mutex_long -lpthread -lm && chmod 777 pthread_mutex_long绑核启动:taskset -c 0-1 ./pthread_mutex_long关键截图八:代码优化后重新启动,资源分析任务结果-进程/线程调度测试程序的两个线程会平稳的进行,不会存在长时间的等待。作业结束!完毕!
  • [技术干货] Java线程池多线程查询数据库提高查询效率[转载]
    需求公司数据统计报表查询,几张大表关联查询,包含跨库查询,数据联查,数据过滤,数据统计。问题主表数据1    主表数据2    …    统计数据1    统计数据2    …数据    数据        数据    数据    报表结构是主表数据+统计数据,只查主表数据速度很快,统计数据需要跨库联查,且表数据量大,拖慢了速度。一开始的做法是,每次分页请求都先获取主表list,再foreach主表list,根据主表字段去查询统计数据并进行计算,再合并到主表进行返回,查询速度不理想。分页查响应时间=1次主表查询时间+10次统计数据查询时间思路复杂的报表数据统计不应全部由DB层面去解决,而是SQL仅负责数据过滤,返回统计所需的字段,SQL尽量简单高效,service层拿到DB返回的结果集,由代码层面去进行较为复杂的数据合并与统计。最总给到前端的是一个分页,那么优化的话是基于分页去进行,分页10条,线程池开启10个线程去并行查询,最总汇总返回给前端。分页查响应时间=1次主表查询时间+1次统计数据查询时间(10条中最慢的一条)代码线程池工具类package com.youxue.weliao.utils;import com.google.common.util.concurrent.ThreadFactoryBuilder;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.Future;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;/** * @Author lhy * @Date 2022/5/13 */@Slf4jpublic class ThreadUtil {    private volatile static ThreadUtil threadUtil;    private ThreadPoolExecutor executor;    /**     * 单例     */    private ThreadUtil() {    }    public static ThreadUtil getThreadUtilInstance() {        if (null == threadUtil) {            synchronized (ThreadUtil.class) {                if (null == threadUtil) {                    threadUtil = new ThreadUtil();                }            }        }        return threadUtil;    }    /**     * 提交任务     *     * @param task     */    public Future<?> submit(Runnable task) {        if (executor == null) {            // 初始化线程池            executor = initialize();        }        // 执行线程        return executor.submit(task);    }    /**     * 初始化线程池     *     * @return     */    private synchronized ThreadPoolExecutor initialize() {        ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 0L,            TimeUnit.MILLISECONDS,            new LinkedBlockingQueue<>(1024),            new ThreadFactoryBuilder()                .setNameFormat("task-admin-getlist--%d")                .build(),            new ThreadPoolExecutor.CallerRunsPolicy());        log.info("===================>ThreadUtil线程池初始化");        return executor;    }    /**     * 关闭线程池     */    public void shutdown() {        if (executor != null) {            executor.shutdown();        }    }}service层实际调用,这里我就不把全部业务代码放出来了,简化后如下    @Override    public IPage<ManageDto> getManageDto(IPage<ManageDto> page, String str, String end, List<Integer> taskAdminIds) {        // 主表查询        IPage<ManageDto> manageDtos = baseMapper.getManageDto(page, str, end, taskAdminIds);        if (manageDtos.getTotal() > 0) {            // 主表查询结果集            List<ManageDto> manageDtoList = manageDtos.getRecords();            // 异步线程Future集合            List<Future<?>> futures = new ArrayList<>();            for (ManageDto manageDto : manageDtoList) {                // 本页有几条数据便开启几条线程去进行统计数据查询                futures.add(ThreadUtil.getThreadUtilInstance().submit(() -> {                    // 统计数据查询                    List<ManageVo> manageVos = groupCyberArmyService.getManageVos(manageDto.getProcessAdminUserId(), manageDto.getTaskAdminId());                    // 业务逻辑运算后合并到主表Dto                }))            }            this.waitFinish(futures);            manageDtos.setRecords(manageDtoList);            return manageDtos;        }        return null;    }        /**     * 线程池内线程是否已全部执行结束     *      * @param futures 异步线程Future集合     */    @SneakyThrows    private void waitFinish(List<Future<?>> futures) {        for (Future<?> future : futures) {            future.get();        }    }解析future.get方法线程池线程是异步提交的,但是返回分页结果是需要同步返回,Future的get是个阻塞方法。只有所有的任务全部完成,我们才能用get按照任务的提交顺序依次返回结果,调用future.get()方法查看线程池内所有方法是否已执行完成,达到线程异步提交,结果集同步返回的效果。线程池工具类单例就不多解释了,这里用的是DCL单例,线程池根据自身需求配置核心线程等参数。————————————————版权声明:本文为CSDN博主「幸福往往是摸得透彻」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/weixin_43840809/article/details/124767908
  • [技术干货] clickhouse--性能优化[转载]
    一、建表优化1.1 数据类型1.1.1 时间字段时间字段建议存储为DateTime类型,不需要经过函数转换处理,执行效率高,可读性好。1.1.2 空值存储类型Nullable类型几乎总是会拖累性能,因为存储Nullable列时需要创建一个额外的文件来存储NULL的标记,并且Nullable列无法被索引。参考:nullable列,clickhouse中Nullable与非空字段的建表与类型互转1.2 分区和索引分区粒度一般按天分区,也可以指定Tuple(),也就是不分区。常规来说,1亿条数据分30个分区比较合适。必须指定索引列,clickhouse中的索引列即排序列,通过order by指定。通常是查询频率大的在前,高级列在前原则。基数大的不适合做索引列(即重复数据特别少的列)。1.3 表参数index_granularity控制索引粒度,默认8192。不保存全量历史数据的可以用TTL。1.4 写入和删除优化尽量不要执行单条或小批量删除和插入操作,因为会产生小分区文件,给后台Merge任务带来巨大压力。不要一次写入太多分区,或数据写入太快,数据写入太快会导致Merge速度跟不上报错。一般建议每秒发起2-3次写入操作,每次操作写入2w-5w条数据。1.5 举例参考:ClickHouse元数据以下例子主要测试两部分内容:一是删除数据时,查看系统表分区情况会发现删除的数据并没有马上删掉;二是使用TTL的效果。CREATE TABLE test.t_null(    id String,    name Nullable(String),    create_time DateTime default now()) ENGINE = MergeTree PARTITION BY id ORDER BY id TTL create_time + INTERVAL 10 minute ;           --默认是delete-- 注意8小时时差insert into test.t_null values('1', 'alice', '2021-12-25 09:41:00'),('1', NULL, '2021-12-25 09:41:00'),('2', 'bob', '2021-12-02 06:41:00'),('3', 'carolin', '2021-12-02 06:41:00');--查询结果select * from test.t_null;--删除某个分区alter table test.t_null delete where id = '3';--系统存储情况,注意观察 name列,删除前后生成的小分区select     partition,     name,    part_type,    active,    marks,    rows,    --bytes_on_disk,    --data_compressed_bytes,    --data_uncompressed_bytes,    remove_time,    --partition_id,    level,    database,    table,    disk_name,    --path,    column,    type,    column_positionfrom system.parts_columnswhere database='test' and table='t_null';--合并数据optimize table test.t_null final;123456789101112131415161718192021222324252627282930313233343536373839404142434445464748491.6 常见配置1.6.1CPU资源config.xml配置项users.xml配置项background_pool_size:后台线程池大小,merge线程就是在该线程池执行,默认16,允许的前提下建议改成cpu个数的2倍(线程数)。background_schedule_pool_size:执行后台任务的线程数,默认128,建议改成cpu个数的2倍(线程数)。background_distributed_schedule_pool_size:设置为分布式发送执行后台任务的线程数,默认16,建议改成cpu个数的2倍(线程数)。max_concurrent_queries:最大并发处理的请求数(包含select, insert等),默认值100,推荐150-300。max_threads:单个查询所能使用的cpu个数,默认是cpu核数。1.6.2 内存资源max_memory_usage:在users.xml中,表示单次Query占用内存最大值,可以设置稍大。比如128G的内存设置为100G。max_bytes_before_external_group_by:一般按照max_memory_usage的一般设置,当group使用内存超过阈值后会刷到磁盘运行。建议50G。max_bytes_before_external_sort:超过时进行溢写磁盘。max_table_size_to_drop:在config.xml中,默认是50GB,建议修改为0,不限制。1.6.3 存储不支持设置多数级目录,为了提升数据io性能,看挂载虚拟券组。二、语法优化规则基于RBO(Rule Based Optimization),参考:RBO优化器下面通过explain语句查看执行计划,来看看不同的查询语句执行效果,其中部分是clickhouse自动帮我们进行优化的,但另一部分是在查看优化的执行语句之后,我们需要手动对查询语句进行修改。2.1 count优化-- 只要加了具体字段就会导致扫描全表explain plan select count(UserID) from hits_v1;-- count(*), count(1)都会优化直接获取count文件explain plan select count() from hits_v1;123452.2 消除子查询重复字段explain syntax select UserID, UserID, VisitID from visits_v1;explain syntax select UserID, UserID as UserID2, VisitID from visits_v1;122.3 谓词下推2.3.1 having当group by有having子句,但是没有with cube, with rollup 或者 with totals修饰的时候,having过滤会下推到where提前过滤。explain syntax select UserID from hits_v1 group by UserID having UserID = '8585742290196126178';--优化后SELECT UserID FROM hits_v1 WHERE UserID = '8585742290196126178' GROUP BY UserID;12342.3.2 子查询优化后过滤条件被移至子查询中。explain syntax select * from (select UserID from visits_v1) where UserID = '8585742290196126178';--优化后SELECT UserIDFROM    (SELECT UserID FROM visits_v1 WHERE UserID = '8585742290196126178') WHERE UserID = '8585742290196126178'12345672.4 聚合计算外推explain syntax select sum(UserID * 2) from visits_v1--优化结果select sum(UserID) * 2 from visits_v11234explain syntax select sum(exp_cnt * 2) from test.test1;--优化结果SELECT sum(exp_cnt) * 2 FROM test.test1;1234需要注意的是clickhouse并不会自动帮我们优化,可以执行两种查询语句查看执行时间:--明显第二种方式结果更快select sum(exp_cnt * 2) from test.test1;SELECT sum(exp_cnt) * 2 FROM test.test1;1232.5 聚合函数消除explain syntaxselect    sum(UserID * 2),    max(VisitID),    max(UserID)from visits_v1group by UserID--优化后的语句SELECT    sum(UserID) * 2,    max(VisitID),        UserID  --去掉无意义的函数FROM visits_v1    GROUP BY UserID123456789101112131415162.6 删除重复2.6.1 删除重复的order by keyexplain syntaxselect UserID, VisitIDfrom visits_v1order by    UserID ASC,    UserID DESC,    VisitID ASC,    VisitID ASC--优化后语句explain syntaxselect UserID, VisitIDfrom visits_v1order by    UserID ASC,    VisitID ASC12345678910111213141516172.6.2 删除重复的limit by key参考:LIMIT BYexplain syntaxselect *from visits_v1order by CounterIDlimit 2 by CounterID, CounterID  --每个单独的CounterID保留两条数据LIMIT 10--优化后的语句select *from visits_v1order by CounterIDlimit 2 by CounterIDLIMIT 1012345678910111213142.6.3 删除重复的USING Keyexplain syntaxselect     a.UserID,    b.VisitID,    a.URL,    b.UserIDfrom hits_v1 AS aleft join visits_v1 as b using (UserID, UserID) --on a.UserID=b.UserID--返回优化后的语句select     UserID,    VisitID,    URL,    b.UserIDfrom hits_v1 AS aleft join visits_v1 as b using (UserID)12345678910111213141516172.7 标量替换如果子查询只返回一行数据,在被引用的时候用标量替换。在本例中,指的是``with (select sum(bytes) from system.parts where active) as total_disk_usage`会被优化为用一个数值代替。explain syntaxwith (select sum(bytes) from system.parts where active) as total_disk_usageselect     table, (sum(bytes) / total_disk_usage) * 100 as table_disk_usage, total_disk_usagefrom system.partsgroup by tableorder by table_disk_usage desclimit 10;--优化结果,WITH语句内容似乎是与查询语句绑定的,不能单独执行,不然结果是不对的WITH identity(CAST(0, 'UInt64')) AS total_disk_usageSELECT     table,    (sum(bytes) / total_disk_usage) * 100 AS table_disk_usage,    total_disk_usageFROM system.partsGROUP BY tableORDER BY table_disk_usage DESCLIMIT 10;123456789101112131415161718192.8 三元运算优化开启参数 optimize_if_chain_to_multiif,则三元运算符会被替换成multiIf函数explain syntaxselect number = 1 ? 'hello' : (number = 2 ? 'world' : 'atguigu')from numbers(10)settings optimize_if_chain_to_multiif = 1;--优化结果SELECT multiIf(number = 1, 'hello', number = 2, 'world', 'atguigu')FROM numbers(10)SETTINGS optimize_if_chain_to_multiif = 1;123456789三、查询优化3.1 单表查询3.1.1 prewhere代替wherewhere是先过滤出满足条件的行,然后再选择需要的列。prewhere只支持MergeTreee族系列引擎的表,首先会读取指定的列数据,来判断数据过滤,等待数据过滤之后再读取select声明的列字段来补全其余属性,这样可以避免整行扫描。当查询列明显多于筛选列时,prewhere可十倍提升查询性能,自动优化执行过滤阶段的数据读取方式,降低io操作。默认情况下,where条件会自动优化成prewhere。关闭自动优化:set optimize_move_to_prewhere=0;explain syntaxselect     WatchID, EventTime, UserID, URLDomain, RefererDomainfrom datasets.hits_v1where UserID = '8585742290196126178'--优化结果SELECT WatchID, EventTime, UserID, URLDomain, RefererDomainFROM datasets.hits_v1PREWHERE UserID = '85857422901961261712345678910不能自动优化的情况:使用常量表达式使用默认值为alias类型的字段包含了arrayJOIN, globalIn, globalNotIn, indexHint的查询使用了主键字段select 查询的列字段和where的谓词相同explain syntaxselect UserIDfrom datasets.hits_v1where UserID = '8585742290196126178';--结果没有优化SELECT UserIDFROM datasets.hits_v1WHERE UserID = '8585742290196126178';1234567893.1.2 数据采样采样可以极大提升数据分析的性能select Title, count(*) as PageViewsfrom datasets.hits_v1sample 0.1where CounterID = 57group by Titleorder by PageViews desc limit 10001234563.1.3 列裁剪与分区裁剪数据量太大时应避免使用select * 操作,尽量只取用到的列,必要时可对分区进行过滤-- 反例select * from datasets.hits_v1;-- 正例select WatchID, JavaEnable, Title, EventTime, EventDate, CounterID, ClientIP, ClientIP6, RegionID, UserIDfrom datasets.hits_v1;-- 分区裁剪select WatchID, JavaEnable, Title, EventTime, EventDate, CounterID, ClientIP, ClientIP6, RegionID, UserIDfrom datasets.hits_v1where EventDate = '2014-03-23';12345678910113.1.4 orderby结合where, limit千万以上数据集进行order by查询时需要搭配where条件和limit语句一起使用。-- 正例select UserID, Agefrom hits_v1where CounterID = 57order by Age desc limit 1000;-- 反例select UserID, Agefrom hits_v1order by Age desc;123456789103.1.5 避免构建虚拟列如非必须,不要在结果集上构建虚拟列,虚拟列非常消耗资源浪费性能,可以考虑前端进行处理,或者在表中构造实际字段进行额外存储。-- 反例select Income, Age, Income/Age as IncRate from datasets.hits_v1;-- 正例select Income, Age from datasets.hits_v1;12343.1.6 uniqCombined替代distinct性能可提升10倍以上,uniqCombined底层采用类似HyperLogLog算法实现,能接受数据误差,可直接使用这种去重方式提升查询性能。-- 反例select count(distinct UserID) from datasets.hits_v1;-- SELECT uniqExact(UserID) FROM datasets.hits_v1-- 正例select uniqCombined(UserID) from datasets.hits_v1;1234563.1.7 其他注意事项1)查询熔断为了避免因个别慢查询引起的服务雪崩的问题,除了可以为单个查询设置超时以外,还可以配置周期熔断,在一个查询周期内,如果用户频繁进行慢查询,超出规定阈值后将无法继续进行查询操作。2)关闭虚拟内存物理内存和虚拟内存的数据交换会导致查询变慢,资源允许的情况下,关闭虚拟内存。3)配置join_use_nulls为每一个账户添加join_use_nulls配置,左表中的一条记录在右表中不存在,游标的相应字段会返回该字段相应数据类型的默认值,而不是Null值。4)批量写入时先排序批量写入数据时,必须控制每个批次的数据中涉及到的分区的数量,在写入之前最好对需要导入的数据进行排序。无序的数据或者涉及的分区太多,会导致clickhouse无法及时对新导入的数据进行合并,从而影响查询性能。5)关注CPUcpu一般在50%左右会出现查询波动,达到70%会出现大范围的查询超时,cpu是最关键的指标,要非常关注。3.2 多表关联3.2.1 准备表和数据# 创建小表create table visits_v2engine = CollapsingMergeTree(Sign)partition by toYYYYMM(StartDte)order by (CounterID, StartDate, intHash32(UserID), VisitID)sample by intHash32(UserID)settings index_granularity = 8192as select * from visits_v1 limit 10000;# 创建join结果表,避免控制台疯狂打印数据# 巧用条件语句复制表结构而不导入数据create table hits_v2engine = MergeTree()partition by toYYYYMM(EventDate)order by (CounterID, StartDate, intHash32(UserID))sample by intHash32(UserID)settings index_granularity = 8192as select * from hits_v1 where 1=0;1234567891011121314151617183.2.2 join优化3.2.2.1 常规join方式表A和表B进行join时,先将B加载到内存中,然后A每一条数据都去内存中查询表B进行匹配。3.2.2.2 大小表join多表join时要满足小表在右的原则,右表关联时被加载到内存中与左表进行比较。clickhouse中无论时left join, right join还是inner join,永远都是拿着右表中的每一条记录到左表中查找该记录是否存在,所以右表必须是小表。小表在右insert into table hits_v2select a.* from hits_v1 a left join visits_v2 b on a.CounterID = b.CounterID;12大表在右insert into table hits_v2select a.* from visits_v2 b left join hits_v1 a on a.CounterID = b.CounterID;123.2.2.3 用in代替join多表联查时,查询的数据仅从其中一张表出时,可以考虑用in操作而不是joininsert into hits_v2select a.* from hits_v1 a where a.CounterID in (select CounterID from visits_v1);1233.2.2.4 谓词下推谓词下推的基本思想即:将过滤表达式尽可能移动至靠近数据源的位置,以使真正执行时能直接跳过无关的数据。join查询时不会主动发起谓词下推的操作,需要每个子查询提前完成过滤操作,需要注意的时,是否执行谓词下推,对性能影响差别很大(新版本不存在该问题,但需要注意谓词的位置不同依然有性能的差异)explain syntaxselect a.* from hits_v1 a left join visits_v2 b on a.CounterID = b.CounterIDhaving a.EventDate = '2014-03-17';# 最后一行变成了PREWHERE EventDate = '2014-03-17'explain syntaxselect a.* from hits_v1 a left join visits_v2 b on a.CounterID = b.CounterIDhaving b.StartDate = '2014-03-17';# 最后一行变成了WHERE StartDate = '2014-03-17'123456789尽量在join前进行where过滤,提升查询效率explain syntaxselect a.* from (    select * from hits_v1     where EventDate = '2014-03-17')a left join visits_v1 b on a.CounterID = b.CounterID;# PREWHERE EventDate = '2014-03-17'1234567on关联条件中不可有过滤条件# 报错,关联条件不可用来做过滤explain syntaxselect a.* from hits_v1 a left join visits_v2 b on a.CounterID = b.CounterIDand a.EventDate = '2014-03-17';12343.2.2.5 分布式表使用global两张分布式表上的in和join之前必须加上global关键字,右表只会在接收查询请求的那个节点查询一次,并将其分发到其他节点上。如果不加global关键字的话,每个节点都会单独发起一次对右表的查询,而右表又是分布式表,就导致右表一共会被查询N的2次方(N是分布式表的分片数量),这就是查询放大,会带来很大开销。可能会减小为N次。3.2.2.6 使用字典表将一些需要关联分析的业务创建成字典表进行join操作,前提字典表不宜太大,因为字典表会常驻内存。3.2.2.7 提前过滤通过增加逻辑过滤可以减少数据扫描,达到提高执行速度及降低内存消耗的目的。3.3 总结尽量不要用join能过滤先过滤,尤其是右表右边放小表特殊场景可以考虑使用字典表可以替换的话,尽量不要用join,比如用In实现参考:https://play.clickhouse.com/http://nicethemes.cn/news/txtlist_i169603v.html————————————————版权声明:本文为CSDN博主「囊萤映雪的萤」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/liuyingying0418/article/details/121618255
  • [问题求助] 华为mrs kafak消费线程报错求助大佬
    【功能模块】kafka消费线程停止,并报错,报错日志在下面【操作步骤&问题现象】1、2、【截图信息】这是我们消费端kafka配置,看报错说group.instance.id问题不知道怎么回事【日志信息】(可选,上传日志内容或者附件)2022-07-04 10:53:51.550 ERROR [] [kafkaTopicNormalConsumer]  com.cloudwalk.portal.config.HwMrsKafkaConfig$1[76] - [kafkaTopicNormalConsumer]: Error due toorg.apache.kafka.common.errors.FencedInstanceIdException: The broker rejected this static consumer since another consumer with the same group.instance.id has registered with a different member.id.2022-07-04 10:53:51.508 ERROR [] [kafkaTopicNormalConsumer]  org.apache.kafka.clients.consumer.internals.AbstractCoordinator[1326] - [Consumer instanceId=mh_id_c, clientId=consumer-1-mh_id_c, groupId=1] Caught fenced group.instance.id Optional[mh_id_c] error in heartbeat thread2022-07-04 10:53:51.461 ERROR [] [kafkaTopicNormalConsumer]  org.apache.kafka.clients.consumer.internals.AbstractCoordinator[1062] - [Consumer instanceId=mh_id_c, clientId=consumer-1-mh_id_c, groupId=1] Received fatal exception: group.instance.id gets fenced
  • [技术干货] 安装tomcat后可能出现的问题介绍【转载】
      1. 没有开tomcat服务        在浏览器的地址栏中输入localhost:8080 回车会出现如下界面         tomcat没有开服务。在cmd中输入startup.bat。不要关闭开启的tomcat窗口。        2.输入url路径错误                在浏览器中输入url显示404,可能是输入的路径不存在或输入错误路径。        3. Java JDK环境变量未设置好         在cmd输入startup.bat时,报错。        如图:        解决方案:        这个是Java jdk的环境变量名设置不规范,将jdk的路径设置变量名必须是JAVA_HOME。        找到系统变量界面,更改错误的jdk变量名。         更改完后:   修改完之后,重新打开cmd在输入startup.bat就可以正常启动了        4.重复开启服务        服务已经开启,不需要重复打开。        5.端口被占用        通过网页访问出现 Access Error错误,端口被占用        打开cmd输入指令:将占用你所指定的端口号进程删掉netstat -ano :查看所有端口信息netstat ano | findstr "8080" :查看端口8080占用信息tasklist :查看所有进程tasklist | findstr "1": 查看某进程taskkill /f /pid 进程号:   删除某进程号到此这篇关于安装tomcat后可能出现的问题介绍的文章就介绍到这了转载自https://www.jb51.net/article/233667.htm
  • [其他问题] 【云服务器】VNC远程连接Xfce图形化界面频频卡死
    【操作步骤&问题现象】为Ubuntu20.04安装Xfce图形化界面,使用VNC连接,出现频繁卡死的情况。“卡死”:鼠标可以移动,但是不能操作界面。而且应用占用的CPU很低,即使kill掉当前进程,进程代表的应用退出界面,但是界面依旧处于卡死、无法操作的状态。目前每次卡死必须重启服务器才能解决问题,几乎无法进行有效的操作,请问这个问题该如何解决?【截图信息】下图展示了卡死时CPU使用情况:下图展示了屏幕卡死时的样子(无法操作):
  • [Atlas200] 未知进程在进行写操作
    【功能模块】Atlas200 emmc/TF【操作步骤&问题现象】1、安装新系统2、iostat命令查看emmc/TF的read和write【截图信息】时间久了容易写坏盘。
  • [java] 一文带你了解J.U.C的FutureTask、Fork/Join框架和BlockingQueue
    >摘要: J.U.C是Java并发编程中非常重要的工具包,今天,我们就来着重讲讲J.U.C里面的FutureTask、Fork/Join框架和BlockingQueue。 本文分享自华为云社区《[【高并发】J.U.C组件扩展](https://bbs.huaweicloud.com/blogs/353871?utm_source=csdn&utm_medium=bbs-ex&utm_campaign=other&utm_content=content)》,作者: 冰 河 。 # FutureTask FutureTask是J.U.C(java.util.concurrent)下的,但不是AQS(AbstractQueuedSynchronizer)的子类。其对线程结果的处理值得借鉴和在项目中使用。 Thread和Runnable执行完任务无法获取执行结果。Java1.5开始提供了Callable和Future,通过它们可以在任务执行完毕之后,得到任务执行的结果。 # Callable与Runnable接口对比 Callable:泛型接口,提供一个call()方法,支持抛出异常,并且执行后有返回值 Runnable:接口,提供一个run()方法,不支持抛出异常,执行后无返回值 # Future接口 对于具体的Callable和Runnable任务,可以进行取消,查询任务是否被取消,查询是否完成以及获取结果等。 Future可以监视目标线程调用call()的情况,当调用Future的get()方法时,就可以获得结果。此时,执行任务的线程可能不会直接完成,当前线程就开始阻塞,直到call()方法结束返回结果,当前线程才会继续执行。总之,Future可以得到别的线程任务方法的返回值。 # FutureTask类 实现的接口为RunnableFuture,而RunnableFuture接口继承了Runnable和Future两个接口,所以FutureTask类最终也是执行Callable类型的任务。如果FutureTask类的构造方法参数是Runnable的话,会转换成Callable类型。 类实现了两个接口:Runnable和Future。所以,它即可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值,这样设计的好处如下: 假设有一个很费时的逻辑,需要计算并且返回这个值,同时,这个值又不是马上需要,则可以使用Runnable和Future的组合,用另外一个线程去计算返回值,而当前线程在使用这个返回值之前,可以做其他的操作,等到需要这个返回值时,再通过Future得到。 Future示例代码如下: ``` package io.binghe.concurrency.example.aqs; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @Slf4j public class FutureExample { static class MyCallable implements Callable{ @Override public String call() throws Exception { log.info("do something in callable"); Thread.sleep(5000); return "Done"; } } public static void main(String[] args) throws Exception { ExecutorService executorService = Executors.newCachedThreadPool(); Future future = executorService.submit(new MyCallable()); log.info("do something in main"); Thread.sleep(1000); String result = future.get(); log.info("result: {}", result); executorService.shutdown(); } } ``` FutureTask示例代码如下: ``` package io.binghe.concurrency.example.aqs; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; @Slf4j public class FutureTaskExample { public static void main(String[] args) throws Exception{ FutureTask futureTask = new FutureTask(new Callable() { @Override public String call() throws Exception { log.info("do something in callable"); Thread.sleep(5000); return "Done"; } }); new Thread(futureTask).start(); log.info("do something in main"); Thread.sleep(1000); String result = futureTask.get(); log.info("result: {}", result); } } ``` # Fork/Join框架 位于J.U.C(java.util.concurrent)中,是Java7中提供的用于执行并行任务的框架,其可以将大任务分割成若干个小任务,最终汇总每个小任务的结果后得到最终结果。基本思想和Hadoop的MapReduce思想类似。 主要采用的是工作窃取算法(某个线程从其他队列里窃取任务来执行),并行分治计算中的一种Work-stealing策略 ## 为什么需要使用工作窃取算法呢? 假如我们需要做一个比较大的任务,我们可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,于是把这些子任务分别放到不同的队列里,并为每个队列创建一个单独的线程来执行队列里的任务,线程和队列一一对应,比如A线程负责处理A队列里的任务。但是有的线程会先把自己队列里的任务干完,而其他线程对应的队列里还有任务等待处理。干完活的线程与其等着,不如去帮其他线程干活,于是它就去其他线程的队列里窃取一个任务来执行。而在这时它们会访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行。 ## 工作窃取算法的优点: 充分利用线程进行并行计算,并减少了线程间的竞争 ## 工作窃取算法的缺点: 在某些情况下还是存在竞争,比如双端队列里只有一个任务时。并且该算法会消耗更多的系统资源,比如创建多个线程和多个双端队列。 对于Fork/Join框架而言,当一个任务正在等待它使用Join操作创建的子任务结束时,执行这个任务的工作线程查找其他未被执行的任务,并开始执行这些未被执行的任务,通过这种方式,线程充分利用它们的运行时间来提高应用程序的性能。为了实现这个目标,Fork/Join框架执行的任务有一些局限性。 ## Fork/Join框架局限性: (1)任务只能使用Fork和Join操作来进行同步机制,如果使用了其他同步机制,则在同步操作时,工作线程就不能执行其他任务了。比如,在Fork/Join框架中,使任务进行了睡眠,那么,在睡眠期间内,正在执行这个任务的工作线程将不会执行其他任务了。 (2)在Fork/Join框架中,所拆分的任务不应该去执行IO操作,比如:读写数据文件 (3)任务不能抛出检查异常,必须通过必要的代码来出来这些异常 Fork/Join框架的核心类 Fork/Join框架的核心是两个类:ForkJoinPool和ForkJoinTask。ForkJoinPool负责实现工作窃取算法、管理工作线程、提供关于任务的状态以及执行信息。ForkJoinTask主要提供在任务中执行Fork和Join操作的机制。 示例代码如下: ``` package io.binghe.concurrency.example.aqs; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.Future; import java.util.concurrent.RecursiveTask; @Slf4j public class ForkJoinTaskExample extends RecursiveTask { public static final int threshold = 2; private int start; private int end; public ForkJoinTaskExample(int start, int end) { this.start = start; this.end = end; } @Override protected Integer compute() { int sum = 0; //如果任务足够小就计算任务 boolean canCompute = (end - start) = threshold; if (canCompute) { for (int i = start; i = end; i++) { sum += i; } } else { // 如果任务大于阈值,就分裂成两个子任务计算 int middle = (start + end) / 2; ForkJoinTaskExample leftTask = new ForkJoinTaskExample(start, middle); ForkJoinTaskExample rightTask = new ForkJoinTaskExample(middle + 1, end); // 执行子任务 leftTask.fork(); rightTask.fork(); // 等待任务执行结束合并其结果 int leftResult = leftTask.join(); int rightResult = rightTask.join(); // 合并子任务 sum = leftResult + rightResult; } return sum; } public static void main(String[] args) { ForkJoinPool forkjoinPool = new ForkJoinPool(); //生成一个计算任务,计算1+2+3+4 ForkJoinTaskExample task = new ForkJoinTaskExample(1, 100); //执行一个任务 Future result = forkjoinPool.submit(task); try { log.info("result:{}", result.get()); } catch (Exception e) { log.error("exception", e); } } } ``` # BlockingQueue 阻塞队列,是线程安全的。 ## 被阻塞的情况如下: (1)当队列满时,进行入队列操作 (2)当队列空时,进行出队列操作 ## 使用场景如下: 主要在生产者和消费者场景 ## BlockingQueue的方法 BlockingQueue 具有 4 组不同的方法用于插入、移除以及对队列中的元素进行检查。如果请求的操作不能得到立即执行的话,每个方法的表现也不同。这些方法如下: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20226/17/1655430690326993865.png) 四组不同的行为方式解释: - 抛出异常 如果试图的操作无法立即执行,抛一个异常。 - 特殊值 如果试图的操作无法立即执行,返回一个特定的值(常常是 true / false)。 - 阻塞 如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行。 - 超时 如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行,但等待时间不会超过给定值。返回一个特定值以告知该操作是否成功(典型的是 true / false)。 ## BlockingQueue的实现类如下: - ArrayBlockingQueue:有界的阻塞队列(容量有限,必须在初始化的时候指定容量大小,容量大小指定后就不能再变化),内部实现是一个数组,以FIFO的方式存储数据,最新插入的对象是尾部,最新移除的对象是头部。 - DelayQueue:阻塞的是内部元素,DelayQueue中的元素必须实现一个接口——Delayed(存在于J.U.C下)。Delayed接口继承了Comparable接口,这是因为Delayed接口中的元素需要进行排序,一般情况下,都是按照Delayed接口中的元素过期时间的优先级进行排序。应用场景主要有:定时关闭连接、缓存对象、超时处理等。内部实现使用PriorityQueue和ReentrantLock。 - LinkedBlockingQueue:大小配置是可选的,如果初始化时指定了大小,则是有边界的;如果初始化时未指定大小,则是无边界的(其实默认大小是Integer类型的最大值)。内部实现时一个链表,以FIFO的方式存储数据,最新插入的对象是尾部,最新移除的对象是头部。 - PriorityBlockingQueue:带优先级的阻塞队列,无边界,但是有排序规则,允许插入空对象(也就是null)。所有插入的对象必须实现Comparable接口,队列优先级的排序规则就是按照对Comparable接口的实现来定义的。可以从PriorityBlockingQueue中获得一个迭代器Iterator,但这个迭代器并不保证按照优先级的顺序进行迭代。 - SynchronousQueue:队列内部仅允许容纳一个元素,当一个线程插入一个元素后,就会被阻塞,除非这个元素被另一个线程消费。因此,也称SynchronousQueue为同步队列。SynchronousQueue是一个无界非缓存的队列。准确的说,它不存储元素,放入元素只有等待取走元素之后,才能再次放入元素
  • [网络迁移] 如何杀死占用训练资源的进程
    910训练过程中出错退出了,但占用了910训练卡的进程却没有退出,重新开始训练显示卡被占用了,请问下该如何查找占用了资源的进程并将进程kill呢?
  • [其他] GaussDB(DWS)【集群故障】build拉起一段时间后退出
    【问题现象】1、现场单实例故障,手动拉起build实例后实例状态显示build failed,反复重试后此问题仍然存在2、某节点所有实例down unkown与starting状态来回切换【原因分析】1、现场查看gs_ctl 日志无报错,异常中断2、现场手动拉起build后发现gs_ctl进程报错退出,查看此节点进程存在停止此节点命令3、查看父进程调用为mpp-stop.sh脚本调起4、此脚本为线下纯软版本慢节点检测特性,现场将此脚本停止节点功能注释后重新拉起注:集群升级补丁等变更会使用此脚本,待build完成后需要回退5、注释以上脚本后重新拉起build正常,待build完后回退即可
  • [技术干货] 【Linux】之【内存】相关的命令&amp;&amp;解析以及内存相关的问题[free......[转载]
    一、内存相关命令1、free – 显示系统内存使用量情况free命令的功能是显示系统内存使用量情况,包含物理和交换内存的总量、使用量和空闲量情况。语法格式free [参数]1常用参数参数    解析-b    以Byte显示内存使用情况-k    以kb为单位显示内存使用情况-m    以mb为单位显示内存使用情况-g    以gb为单位显示内存使用情况-s    持续显示内存-t    显示内存使用总合-h    以易读的单位方式显示内存使用情况参考实例以默认的容量单位显示内存使用量信息:[root@root ~]# free              total        used        free      shared  buff/cache   availableMem:       65353144     8354168    53956676       39716     3042300    56522796Swap:             0           0           0以MB位单位显示内存使用量信息:[root@root ~]# free -m              total        used        free      shared  buff/cache   availableMem:          63821        8154       52696          38        2971       55202Swap:             0           0           0以易读的单位显示内存使用量信息:[root@root ~]# free -h              total        used        free      shared  buff/cache   availableMem:            62G        8.0G         51G         38M        2.9G         53GSwap:            0B          0B          0B以易读的单位显示内存使用量信息,每个10秒刷新一次:[root@root ~]# free -hs 10              total        used        free      shared  buff/cache   availableMem:            62G        8.0G         51G         38M        2.9G         53GSwap:            0B          0B          0B              total        used        free      shared  buff/cache   availableMem:            62G        8.0G         51G         38M        2.9G         53GSwap:            0B          0B          0B字段解析#total:物理内存大小,就是机器实际的内存#used:已使用的内存大小,这个值包括了cached和应用程序实际使用的内存#free:未被使用的内存大小(俗称:空闲内存)#shared:共享内存大小,是进程间通信的一种方式#buffers:被缓冲区占用的内存大小#cached:被缓存占用的内存大小2、cat /proc/meminfomeminfo中包含所有的内存相关信息。[root@root ~]# cat /proc/meminfo MemTotal:       65353144 kBMemFree:        53956672 kBMemAvailable:   56523144 kBBuffers:           49180 kBCached:          2889216 kBSwapCached:            0 kBActive:          7603092 kBInactive:        2691064 kBActive(anon):    7356648 kBInactive(anon):    38800 kBActive(file):     246444 kBInactive(file):  2652264 kBUnevictable:           0 kBMlocked:               0 kBSwapTotal:             0 kBSwapFree:              0 kBDirty:                36 kBWriteback:             0 kBAnonPages:       7360372 kBMapped:           764500 kBShmem:             39684 kBSlab:             306384 kBSReclaimable:     104216 kBSUnreclaim:       202168 kBKernelStack:       22464 kBPageTables:        30644 kBNFS_Unstable:          0 kBBounce:                0 kBWritebackTmp:          0 kBCommitLimit:    32676572 kB #系统中可以申请的虚拟内存最大值Committed_AS:   27883644 kB #系统已经申请的虚拟内存VmallocTotal:   34359738367 kBVmallocUsed:      525916 kBVmallocChunk:   34325372924 kBHardwareCorrupted:     0 kBAnonHugePages:   4573184 kBCmaTotal:              0 kBCmaFree:               0 kBHugePages_Total:       0HugePages_Free:        0HugePages_Rsvd:        0HugePages_Surp:        0Hugepagesize:       2048 kBDirectMap4k:      771124 kBDirectMap2M:    11393024 kBDirectMap1G:    56623104 kB二、内存相关问题1、内存泄漏解析:如果程序运行过程中不能正常回收不用的内存,那么一段时间就会导致内存增长很高,最终导致系统不可以用,这种情况称为内存泄漏。内存泄漏可以使用内存分享工具valgrind进行内存分析。[root@root ~]# yum -y install valgrind[root@root ~]# valgrind --tool=memcheck  ./mem_leak -t==1738== Memcheck, a memory error detector==1738== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.==1738== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info==1738== Command: ./mem_leak -t==1738== ==1738== ==1738== HEAP SUMMARY:==1738==     in use at exit: 4 bytes in 1 blocks==1738==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated==1738== ==1738== LEAK SUMMARY:==1738==    definitely lost: 4 bytes in 1 blocks==1738==    indirectly lost: 0 bytes in 0 blocks==1738==      possibly lost: 0 bytes in 0 blocks==1738==    still reachable: 0 bytes in 0 blocks==1738==         suppressed: 0 bytes in 0 blocks==1738== Rerun with --leak-check=full to see details of leaked memory==1738== ==1738== For counts of detected and suppressed errors, rerun with: -v==1738== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)2、虚拟内存、物理内存内存的最小单位为页(paging),默认情况一页是4K。虚拟内存与物理内存  当进程向操作系统申请10G内存时,操作系统收到请求后先进行自我检查,经过分析后决定给予进程10G内存空间,但是系统此时并没有真正给进程10G,系统会判断进程运行实际需要的内存大小,比如该进程需要300M就够用了,所以系统只划分300M内存给进程运行,这种实际分配的内存称为物理内存。[root@root ~]# ps aux|head -1USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND#VSZ 虚拟内存#RSS 物理内存3、内存溢出内存溢出(out of memory,OOM),当进程运行向系统申请内存时,系统没有更多的进程分配给该进程了,就会出现内存溢出。内存溢出后系统会杀掉系统中的一些进程来释放内存,通常OOM Killer杀死的都是占用内存较多的服务,直到内存够用为止,所以内存溢出的直观现象通常是某些服务异常或宕机。当发生内存溢出后可以通过dmesg命令或者通过/var/log/messages来快速确定。[root@root ~]# dmesg |tail -5[ 3613.796390] [ 1277]     0  1277    28983        1      16      217             0 bash[ 3613.796393] [ 1446]     0  1446    29003        0      16      221             0 bash[ 3613.796395] [ 1546]     0  1546   774216   213712    1439   513149             0 python[ 3613.796396] Out of memory: Kill process 1546 (python) score 912 or sacrifice child[ 3613.796422] Killed process 1546 (python) total-vm:3096864kB, anon-rss:854848kB, file-rss:0kB, shmem-rss:0kB[root@root ~]# cat /proc/sys/vm/panic_on_oom [root@root ~]# echo 1 > /proc/sys/vm/panic_on_oompanic_on_oom该参数的值共有三个选项:0是触发oom killer进行杀进程处理(/proc/sys/vm/oom_kill_allocating_task默认值为0,结束占用内存多的进程;如果设置为1,就杀死当前申请内存的进程)2是直接触发kernel panic(类似于Windows的蓝屏),此时系统开发人员可以连接进行debug,但是对其他人并没有什么用。更多希望系统快速重启(/proc/sys/kernel/panic设置多少秒后重启)1是根据不同情况会有不同处理;4、Overcommit一般情况下,进程并不会一次用光申请的内存,所以操作系统为了提高内存使用率,会向进程“超卖”内存,以便能响应更多的进程内存申请。但是为了保证程序的稳定运行,系统并不会无限制响应内存申请,这样可以防止内存申请过多,导致系统本身内存空间不足而无法正常运行。Linux系统中使用OverCommit的方式控制内存的申请。内核参数overcommit_memory 内存分配策略可选值:0、1、2。0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,引发OOM。1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。2, 表示内核不允许进程申请超过系统设置大小的内存空间。在这种模式下,系统设置的可申请内存空间大小为:Swap+RAM*(“/proc/sys/vm/overcommit_ratio”/100)说明:/proc/sys/vm/overcommit_ratio就是系统最大可以分配内存的百分比,默认是50.总结 相关文章【Linux】之【CPU】相关的命令及解析[lscpu、mpstat]【Linux】之【内存】相关的命令&&解析以及内存相关的问题[free、meminfo、内存泄漏、内存溢出、Overcommit]【Linux】之【磁盘】相关的命令及解析[df、du、iostat、iotop]【Linux】之【网络】相关的命令及解析[ethtool、nload、nethogs、iftop、iptraf、ifstat]【Linux】综合性命令及解析【top、htop、vmstat、dstat、glances、sar】【Linux】系统如何查看服务器带宽及网络使用情况原文链接:https://blog.csdn.net/liu_chen_yang/article/details/125146057