非运行时分配解决方案——ArrayList

发布于 2024-10-07 04:08:02 字数 1277 浏览 5 评论 0原文

我正在用 Java 制作一个游戏。我需要一些针对当前运行时分配的解决方案,这是由我的 ArrayList 引起的。每隔一分钟或 30 秒,垃圾收集器就会开始运行,因为我正在通过该收集调用绘制和更新方法。

我应该如何实现非运行时分配解决方案?

提前致谢,如果需要,我的代码将在下面从我的 Manager 类发布,其中包含对象的 ArrayList 。 :

一些代码:

@Override
public void draw(GL10 gl) {
  final int size = objects.size();
  for(int x = 0; x < size; x++) {
    Object object = objects.get(x);
    object.draw(gl);
  }
}

public void add(Object parent) {
  objects.add(parent);
}

     //Get collection, and later we call the draw function from these objects
public ArrayList<Object> getObjects() {
   return objects;
}

public int getNumberOfObjects() {
   return objects.size();
}

更多解释:我与此混合的原因是因为(1)我发现ArrayList实现很慢并且导致滞后,(2)我想要将对象/组件合并在一起。当从我的线程类触发更新调用时,它会遍历我的集合,使用管理器的更新函数将内容发送到树/图。

查看开源项目Replica Island时,我发现他使用了他自己编写的替代类FixedSizeArray。由于我不太擅长 Java,所以我想让事情变得更简单,现在我正在寻找另一种解决方案。最后,他解释了为什么他要参加这个特别班:

FixedSizeArray 是标准 Java 集合(如 ArrayList)的替代方案。它旨在提供固定长度的连续数组,可以访问、排序和搜索该数组,而无需需要任何运行时分配。此实现区分了数组的“容量”(它可以包含的最大对象数)和数组的“计数”(插入到数组中的当前对象数)。 set()和remove()等操作只能对已显式add()添加到数组的对象进行操作;也就是说,大于 getCount() 但小于 getCapacity() 的索引不能单独使用。

I'm making a game in Java. I need some solution for my current runtime allocation, caused by my ArrayList. Every single minute or 30 seconds the garbage collector starts to runs because of I am calling for draw and updates-method through this collection.

How should I be able to do a non runtime allocation solution?

Thanks in advance and if needed, my code is posted below from my Manager class which contains the ArrayList of objects.:

Some code:

@Override
public void draw(GL10 gl) {
  final int size = objects.size();
  for(int x = 0; x < size; x++) {
    Object object = objects.get(x);
    object.draw(gl);
  }
}

public void add(Object parent) {
  objects.add(parent);
}

     //Get collection, and later we call the draw function from these objects
public ArrayList<Object> getObjects() {
   return objects;
}

public int getNumberOfObjects() {
   return objects.size();
}

More explanation: The reason I mix with this is because (1) I see that the ArrayList implementation is slow and causing lags and (2) that I want to merge the objects/components together. When firing an update call from my Thread-class, it goes through my collection, send things down the tree/graph using the Manager's update function.

When looking at an Open Source project, Replica Island, I found that he used an alternative class FixedSizeArray that he wrotes on his own. Since I'm not that good at Java, I wanted to make things easier and now I'm looking for another solution. And at last, he explained WHY he made the special class:

FixedSizeArray is an alternative to a standard Java collection like ArrayList. It is designed to provide a contiguous array of fixed length which can be accessed, sorted, and searched without requiring any runtime allocation. This implementation makes a distinction between the "capacity" of an array (the maximum number of objects it can contain) and the "count" of an array (the current number of objects inserted into the array). Operations such as set() and remove() can only operate on objects that have been explicitly add()-ed to the array; that is, indexes larger than getCount() but smaller than getCapacity() can't be used on their own.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

再可℃爱ぅ一点好了 2024-10-14 04:08:02

我发现 ArrayList 实现很慢并且导致滞后......

如果您看到这一点,那么您就误解了证据并得出了不合理的结论。 ArrayList 并不慢,也不会导致延迟......除非您以特别次优的方式使用该类。

数组列表唯一分配内存的时间是创建列表、添加更多元素、复制列表或调用 iterator() 时。

  • 当你创建数组列表时,会创建2个java对象;一种用于 ArrayList,另一种用于其支持数组。如果您使用initialCapacity参数并给出适当的值,您可以安排后续更新不会分配内存。

  • 当您添加或插入一个元素时,数组列表可能分配一个新对象。但只有当后备数组太小而无法容纳所有元素时,才会发生这种情况,并且当这种情况发生时,新后备数组的大小通常是旧数组的两倍。因此,插入 N 个元素将导致最多 log2(N) 分配。此外,如果您使用适当的 initialCapacity 创建数组列表,则可以保证添加或插入

  • 当您将一个列表复制到另一个列表或数组(使用 toArray 或复制构造函数)时,您将获得 1 或 2 个分配。

  • 每次调用iterator()方法时都会创建一个新对象。但您可以通过使用显式索引变量 List.size()List.get(int) 进行迭代来避免这种情况。 (请注意,for (E e : someList) { ... } 隐式调用 List.iterator()。)

(外部操作,如 Collections.sort< /code> 确实需要额外的分配,但这不是数组列表的错误,任何列表类型都会发生这种情况。)

简而言之,使用数组列表获得大量分配的唯一方法是创建大量的数组 列表。数组列表,或者不明智地使用它们。

您找到的 FixedSizedArray 类听起来像是浪费时间。听起来它相当于创建一个具有初始容量的ArrayList...但有一个限制,如果初始容量错误,它将破坏。写它的人可能不太了解 Java 集合。

I see that the ArrayList implementation is slow and causing lags ...

If you see that, you are misinterpreting the evidence and jumping to unjustifiable conclusions. ArrayList is NOT slow, and it does NOT cause lags ... unless you use the class in a particularly suboptimal way.

The only times that an array list allocates memory are when you create the list, add more elements, copy the list, or call iterator().

  • When you create the array list, 2 java objects are created; one for the ArrayList and one for its backing array. If you use the initialCapacity argument and give an appropriate value, you can arrange that subsequent updates will not allocate memory.

  • When you add or insert an element, the array list may allocate one new object. But this only happens when the backing array is too small to hold all of the elements, and when it does happen the new backing array is typically twice the size of the old one. So inserting N elements will result in at most log2(N) allocations. Besides, if you create the array list with an appropriate initialCapacity, you can guarantee that there are zero allocations on add or insert.

  • When you copy a list to another list or array (using toArray or a copy constructor) you will get 1 or 2 allocations.

  • The iterator() method creates a new object each time you call it. But you can avoid this by iterating using an explicit index variable, List.size() and List.get(int). (Be aware that for (E e : someList) { ... } implicitly calls List.iterator().)

(External operations like Collections.sort do entail extra allocations, but that is not the fault of the array list. It will happen with any list type.)

In short, the only way you can get lots of allocations using an array list is if you create lots of array lists, or use them unintelligently.

The FixedSizedArray class you have found sounds like a waste of time. It sounds like it is equivalent to creating an ArrayList with an initial capacity ... with the restriction that it will break if you get the initial capacity wrong. Whoever wrote it probably doesn't understand Java collections very well.

只是一片海 2024-10-14 04:08:02

目前尚不清楚您要问什么,但是:

如果您在编译时知道集合中应包含哪些对象,请将其设为数组而不是 ArrayList 并将内容设置在初始化块中。

Object[] objects = new Object[]{obj1,obj2,obj3};

It's not quite clear what you are asking, but:

If you know at compile time what objects should be in the collection, make it an array not an ArrayList and set the contents in an initialisation block.

Object[] objects = new Object[]{obj1,obj2,obj3};
请你别敷衍 2024-10-14 04:08:02

是什么让您认为您知道 GC 正在回收什么?您对您的应用程序进行了概要分析吗?

What makes you think you know what the GC is reclaiming? Have you profiled your application?

如此安好 2024-10-14 04:08:02

“非运行时分配”是什么意思?我真的不知道在这种情况下“分配”是什么意思......内存分配?显然,这是在运行时完成的。显然,您也没有引用编译时已知的任何类型的固定对象池,因为您的代码允许以多种不同的方式将对象添加到列表中(并不是说您能够在编译时为它们分配任何内容)即使你是)。

除此之外,您发布的代码中的任何内容本身都不会导致垃圾回收。仅当程序中没有任何对象对对象有强引用时,对象才能被垃圾收集,并且您发布的代码只允许将对象添加到 ArrayList 中(尽管可以通过调用 getObjects() 来删除它们) 并从中删除,当然)。只要您不从 objects 列表中删除对象,就不会重新分配 objects 以指向不同的列表,并且包含它的对象不是它本身当它符合垃圾回收条件时,它包含的任何对象也将不再可用于垃圾回收。

所以基本上,您发布的代码没有任何具体问题,并且您的问题按照要求没有意义。也许您可以提供更多详细信息,或者对您的问题到底是什么以及您想要什么有更好的解释。如果是这样,请尝试将其添加到您的问题中。

编辑:

FixedSizeArray的描述和我在其中查看的代码来看,它似乎很大程度上相当于用特定的初始化的ArrayList数组容量(使用采用 int initialCapcacity 的构造函数),但如果在数组已满时尝试添加内容,则在运行时会失败,其中 ArrayList 将扩展本身可以容纳更多并继续正常工作。老实说,它看起来像是一个毫无意义的类,可能是因为作者实际上并没有理解ArrayList而编写的。

另请注意,它关于“不需要任何运行时分配”的声明有点误导......它当然必须在创​​建数组时分配一个数组,但如果其初始数组已满,它只是拒绝分配新数组。您可以使用 ArrayList 实现同样的效果,只需为其提供一个至少足够大以容纳您将添加到其中的最大对象数量的 initialCapacity 即可。如果这样做,并且实际上确保永远不会向其中添加超过该数量的对象,那么它在创建后将永远不会分配新数组。

但是,这些都与您提到的有关垃圾收集的问题没有任何关系,并且您的代码仍然没有显示任何会导致大量对象被垃圾收集的内容。如果存在任何问题,则可能与实际调用 addgetObjects 方法的代码及其正在执行的操作有关。

What do you mean by "non-runtime allocation"? I'm really not even sure what you mean by "allocation" in this context... allocation of memory? That's done at runtime, obviously. You clearly aren't referring to any kind of fixed pool of objects that are known at compile time either, since your code allows adding objects to your list several different ways (not that you'd be able to allocate anything for them at compile time even if you were).

Beyond that, nothing in the code you've posted is going to cause garbage collection by itself. Objects can only be garbage collected when nothing in the program has a strong reference to them, and your posted code only allows adding objects to the ArrayList (though they can be removed by calling getObjects() and removing from that, of course). As long as you aren't removing objects from the objects list, you aren't reassigning objects to point to a different list, and the object containing it isn't itself becoming eligible for garbage collection, none of the objects it contains will ever be available for garbage collection either.

So basically, there isn't any specific problem with the code you've posted and your question doesn't make sense as asked. Perhaps there are more details you can provide or there's a better explanation of what exactly your issue is and what you want. If so, please try to add that to your question.

Edit:

From the description of FixedSizeArray and the code I looked at in it, it seems largely equivalent to an ArrayList that is initialized with a specific array capacity (using the constructor that takes an int initialCapcacity) except that it will fail at runtime if something tries to add to it when its array is full, where ArrayList will expand itself to hold more and continue working just fine. To be honest, it seems like a pointless class, possibly written because the author didn't actually understand ArrayList.

Note also that its statement about "not requiring any runtime allocation" is a bit misleading... it does of course have to allocate an array when it is created, but it just refuses to allocate a new array if its initial array fills up. You can achieve the same thing using ArrayList by simply giving it an initialCapacity that is at least large enough to hold the maximum number of objects you will ever add to it. If you do so, and you do in fact ensure you never add more than that number of objects to it, it will never allocate a new array after it is created.

However, none of this relates in any way to your stated issue about garbage collection, and your code still doesn't show anything that would cause huge numbers of objects to be garbage collected. If there is any issue at all, it may relate to the code that is actually calling the add and getObjects methods and what it's doing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文