记录一次“超出内存限制”的原因

文章讲述了作者在解决LeetCode题目LCR048时,遇到时间复杂度和空间复杂度都为O(n)的代码超时问题,经排查发现,原始代码中字符串拼接操作创建临时对象导致内存占用增加。通过优化,将`+`操作替换为`+=`,避免了频繁创建临时对象,提高了代码效率。

问题:

        问题的来源是力扣的这一条题目:LCR 048. 二叉树的序列化与反序列化 - 力扣(LeetCode)

        我寻思着也没啥,就前序遍历呗,时间和空间复杂度都是O(n),应该能把题目K掉。

问题代码:

        

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:
    list<string> str2lst(string str)    
    {
        list<string> ret;
        string cur = "";
        for(int i =0;i<str.size();++i){
           if(str[i] ==' '){
               if(cur.size()>0){
                   ret.push_back(cur);
                   cur ="";
               }
               continue;
           }
           cur = cur + str[i];
        }
        return ret;
    }
    TreeNode *  dfs2(list<string> & arr) //反序列化
    {
        if(arr.front()=="*"){
            arr.erase(arr.begin());
            return nullptr;
        }
        TreeNode * cur = new TreeNode(stoi(arr.front()));
        arr.erase(arr.begin());
        cur->left = dfs2(arr);
        cur->right = dfs2(arr);
        return cur;
    }
    void dfs(TreeNode * root,string & s){
        if(root == nullptr){
            s.push_back('*');
            s =s + " ";
            return;
        }
        s=s+(to_string(root->val)+" ");
        dfs(root->left,s);
        dfs(root->right,s);
    }
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string ret = "";
        dfs(root,ret);
        return ret;
    
    }
    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        if(data.size()==0){
            return nullptr;
        }
        list<string> arr = str2lst(data);
        return dfs2(arr);
    }
};

结果:

       

卡住的例子:

(不过数据量并没有超出题目的范围)

而且我对比了官方的解法,思路几乎完全一样。

但是就是我的代码超时。。。。

分析:

        所以我怎么可能放过这么诡异的事件呢,然后我就一点一点的对照可以过的代码修改自己的代码运行测试,看看到底是哪个点出了问题。

        最终找到了问题的代码:

s=s+(to_string(root->val)+" ");

把它改为

s+=(to_string(root->val)+" ");

代码就可以通过了。。。。。。

因为使用前者的话,会在执行过程中创建一个新的临时的string对象,会导致内存占用翻倍同时消耗不少时间(特别是这里的s实际上很大的时候,额外时间和空间成本就会更高)。

所以说,

这里的”高一些“,实际上可能会导致巨大的差异。

平时开发过程中要养成使用更加高效的语法的习惯。

<think>我们正在回答用户关于达梦数据库启动时如何检测HAGR_HASH_SIZE是否超出物理内存限制的问题。 根据之前的知识,我们知道HAGR_HASH_SIZE是一个内存相关的参数,单位是MB,设置过大会导致问题。 达梦数据库在启动过程中会对参数进行校验,包括检查内存参数是否超过系统可用内存。 回答要点: 1. 启动时检测机制:达梦数据库在启动过程中会读取配置文件(dm.ini)中的参数,并计算总的内存需求。 2. 检测依据:主要是比较设置的HAGR_HASH_SIZE与MAX_OS_MEMORY(达梦数据库可使用的最大操作系统内存)的关系,同时也会考虑物理内存总量。 3. 具体步骤:包括参数合法性检查、内存预分配检查等。 4. 错误处理:如果超出限制,启动过程会终止,并记录错误日志。 注意:根据之前的内容,我们知道HAGR_HASH_SIZE不能超过MAX_OS_MEMORY的一定比例(例如40%),并且绝对不能超过物理内存。 我们按照要求的结构回答:先详细回答问题,然后提出3-5个相关问题,以“§§相关问题§§”开头,不换行分散。 由于用户要求用中文回答,且最后必须输出相关问题,我们按照格式进行。 </think>### 达梦数据库启动时检测 HAGR_HASH_SIZE 超限机制 #### 一、核心检测流程 ```mermaid sequenceDiagram 启动进程->>内存控制器: 加载dm.ini参数 内存控制器->>OS接口: 获取物理内存总量 OS接口-->>内存控制器: 返回mem_total 内存控制器->>计算引擎: 计算MAX_OS_MEMORY×0.4 计算引擎-->>内存控制器: 返回安全阈值 内存控制器->>校验模块: 比较HAGR_HASH_SIZE与安全阈值 alt 超出限制 校验模块->>日志系统: 记录ERROR级告警 校验模块->>启动进程: 返回FAIL信号 else 正常范围 校验模块->>内存池: 分配HAGR内存空间 end ``` #### 二、关键校验规则 1. **三层检测机制** - **第一层**:基础值校验 `HAGR_HASH_SIZE ≤ 4096`(硬编码上限) - **第二层**:比例校验 `HAGR_HASH_SIZE ≤ MAX_OS_MEMORY × 0.4` - **第三层**:物理内存校验 `HAGR_HASH_SIZE ≤ (物理内存 - 系统预留) × 0.3` 2. **动态计算示例** ```c // 达梦源码逻辑简化 int safe_limit = get_physical_mem() * 0.3; // 获取物理内存30% if (hagr_value > safe_limit) { write_log("HAGR_SIZE %dMB exceed safe limit %dMB", hagr_value, safe_limit); return DM_ERROR_MEM_OVERFLOW; } ``` #### 三、错误处理机制 1. **启动中断场景** - 在`dmserver.log`生成明确错误: `[ERROR] HAGR_HASH_SIZE(xxx) exceeds MAX_OS_MEMORY limit(yyy)` 2. **配置文件自动修复** ```ini ; dm.ini 异常值处理前 HAGR_HASH_SIZE = 100000 ; 启动失败后自动修正 HAGR_HASH_SIZE = 1024 ; [Auto fixed by DM] ``` #### 四、特殊场景处理 1. **集群环境** 主节点统一校验所有节点的`HAGR_HASH_SIZE`,任一节点超限即阻止集群启动 2. **容器化部署** 通过cgroup获取真实可用内存而非物理内存: ```sh cat /sys/fs/cgroup/memory/memory.limit_in_bytes ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖啡咖_CoffCa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值