繁体   English   中英

Java Outofmemory堆空间错误:如何从向量中生成双端队列?

[英]Java Outofmemory heap space error: How do I make a deque from a vector?

我是Java的新手,真的需要你的帮助。

我目前正在使用队列,接收器线程将数据放入此队列,解析器读取此数据。 但问题是接收器可能以惊人的峰值速度接收, 例如。 3000 /秒,而解析器只以100 /秒解析。

编辑:我已经检查过,队列首先停留在100左右,十秒后它开始以每秒100的速度增长,并在2000左右崩溃。 是否可能存在内存泄漏?

我的代码(紧密循环)是

byte[] data = new byte[1024];
System.arraycopy(udpPacket.getData(), 0, data, 0, 1024);
queue.offer(data);

堆填充得太快,我得到一个outofmemory异常。 我想问题是队列是使用链表制作的,所有指针都必须保存在堆中。

我知道一个C版本做同样的事情(使用缓冲区)但性能要好得多,但由于部署问题,我们只能使用Java。

如果你收到3000 /秒,但迟早只能处理100 /秒,你的内存就会耗尽。 我可以建议您使用更多线程来进行解析吗?

关于队列,看看LinkedBlockingDequeLinkedBlockingQueue 有两种高性能的线程安全队列实现。

由于数据的处理速度比处理速度快30倍,因此可以使用扩展HeapSize

java -Xms<initial heap size> -Xmx<maximum heap size>如果在内存耗尽之前完成传输。

  • 或者你自己建议将数据转储到光盘并处理延迟。
  • 否则你必须优化你的解析器

如果生产者生成更多数据然后消费者可以处理,那么数据将开始累积并最终遇到OutOfMemory问题。 这取决于(1)生产者和消费者之间的差异,(2)您必须处理的数据量。

我建议你限制队列中的项目数量。 使用BlockingDeque - > LinkedBlockingDeque来限制队列的容量,并在达到限制时阻止循环。 这样,队列充当解析器的缓存。

我想问题是队列是使用链表制作的,所有指针都必须保存在堆中。

我不这么认为。 我认为真正的问题是系统输入速率与处理系统速率之间的不匹配。 除非您能够以至少平均输入速率进行处理,否则无论您如何表示队列,最终都会耗尽内存。

您必须提高处理速率,降低输入速率或者...丢弃数据。

另一种方法是在队列变得太大时对数据进行采样,并保存采样率,以便我们可以模拟原始数据。

运行java ,可以使用-Xmx参数为虚拟机提供更多可用内存。 例如, java -Xmx512m将允许VM分配高达512Mb的内存。 (默认值相当小)。

但是,如果您正在分配内存并使用数据填充列表并且从不删除它,那么无论您使用哪种语言,最终都会耗尽内存。

我有一个理论, ArrayDeque的实现(至少在Oracle JDK中,我不确定Android的) 似乎从来没有真正解除分配弹出元素。

换句话说,弹出元素的插槽简单地为空。 虽然添加到尾部的元素会使“内部阵列”在永恒中变得更大,这迟早会引起麻烦。

此代码来自Oracle JDK 1.8.0_144:

public E pollFirst() {
    int h = head;
    @SuppressWarnings("unchecked")
    E result = (E) elements[h];
    // Element is null if deque empty
    if (result == null)
        return null;
    elements[h] = null;     // Must null out slot
    head = (h + 1) & (elements.length - 1);
    return result;
}

为我带来麻烦。 :(

如果我的分析是真的,那么似乎ArrayDeque从不打算成为“真正的”FIFO队列,并且不适合这样的目的。 (不幸的是,我现在正需要这样的目的)

我正在调查LinkedList (它也实现了Deque )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM