You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何降低限价订单簿内存占用?解决String.split引发的OOM

问题背景

开发完成的限价订单簿在测试环境(堆内存限制-Xmx128M)运行性能测试时触发OutOfMemoryError,经排查问题出在Main类的String.split操作,需要优化内存占用。当前订单簿基于TreeMap实现,支持更新、查询、市价单三类操作。

核心问题:String.split的内存开销

String.split默认依赖正则表达式解析,会生成大量临时字符串数组和中间对象,在高频性能测试场景下,这些对象会快速填满堆内存,且如果没有及时被GC回收,就会触发OOM。另外,拆分后的字符串数组如果被长期持有,还可能导致内存泄漏。

优化方案
  • 替换String.split为轻量解析方式
    用StringTokenizer代替split,它不依赖正则,直接按分隔符拆分字符串,生成的临时对象更少,内存开销更低。或者手动遍历字符串进行分割,进一步减少对象创建。
  • 复用字符串与常量
    对订单操作类型(如"update"、"query")这类重复出现的字符串,使用字符串常量池对象(直接用字面量,避免new String),或者用枚举类封装操作类型,减少重复创建相同内容的字符串实例。
  • 精简TreeMap存储
    清理订单簿中已完成(成交/取消)的订单,避免无效对象占用内存;用基本类型包装类的缓存(如Integer.valueOf替代new Integer),减少对象实例数量;去掉订单对象中不必要的冗余字段,压缩内存占用。
  • 调整GC策略辅助内存回收
    测试时可调整新生代内存比例(如-XX:NewRatio=1),让临时字符串对象在新生代更快被回收;用jmap、jconsole监控内存使用,确认临时对象的回收情况。
代码优化示例(针对Main类的解析逻辑)

原split实现:

String[] parts = line.split(" ");
String operation = parts[0];
// 后续解析逻辑

优化为StringTokenizer实现:

public class Main {
    private static TreeMap<Long, Order> orderBook = new TreeMap<>();

    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
            String line;
            while ((line = reader.readLine()) != null) {
                StringTokenizer tokenizer = new StringTokenizer(line);
                if (!tokenizer.hasMoreTokens()) continue;
                
                String operation = tokenizer.nextToken();
                switch (operation) {
                    case "update":
                        long orderId = Long.parseLong(tokenizer.nextToken());
                        double price = Double.parseDouble(tokenizer.nextToken());
                        int quantity = Integer.parseInt(tokenizer.nextToken());
                        orderBook.put(orderId, new Order(orderId, price, quantity));
                        break;
                    case "query":
                        long targetId = Long.parseLong(tokenizer.nextToken());
                        Order targetOrder = orderBook.get(targetId);
                        // 处理查询输出
                        break;
                    case "market_order":
                        int dealAmount = Integer.parseInt(tokenizer.nextToken());
                        // 执行市价单成交逻辑
                        break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

内容的提问来源于stack exchange,提问作者Данил Денк

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 02:10:32