question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[IMPROVEMENT] Use of Primitive Stacks/Queues

See original GitHub issue

Hello,

I am working on game and was going to test on Artemis if it was something for my entity system. But being me I am a person who has to understand everything I use so I am cloning it to make a custom version of it.

On the way I found a couple things that were odd to me.

  • Bag allocating 64 entries by default.
  • EntityTransmuter requiring a Builder for a single entry (just make a constructor),
  • Using 3 steps on things that could be done on a single step. (Mostly for the ComponentType related classes)
  • And BitVector not having a fastEquals function even so it would make a lot of sense.

But i found actually something where the performance could be drastically improved. Your EntitySubscription rebuilds the List of Entities everytime it gets changed.

I was thinking how to solve that issue because this is just such a unnessseary performance loss especially if large systems have many changes. And it really needs just a large amount of entities in 1 system to cause a good performance reduction.

So my idea was: Use Queue/Stack for this system and make use of the bitsets, until a certain point. (Like if 35-40% of the size was removed anyway then just rebuild)

This is the logic I was thinking if there were only small changes made. (Would have to be adjusted based on the state the system is in)

Int2IntMap map = new Int2IntOpenHashMap();
IntArrayList list = new IntArrayList();
IntPriorityQueue queue = new IntArrayPriorityQueue();
DynamicBitSet presentEntities = new DynamicBitSet(); // BitVector

public void process(IntList insertions, IntList removals)
{
	//Simulating here changes were already decided to be added & removed
	for(int i = 0, s = removals.size();i<s;i++)
	{
		int id = removals.get(i);
		if(presentEntities.getFast(id))
		{
			remove(id);
		}
	}
	for(int i = 0, s = insertions.size();i<s;i++)
	{
		int id = insertions.get(i);
		if(presentEntities.getFast(id))
		{
			continue;
		}
		insert(id);
	}
	clearEmptyHoles();
}

private void clearEmptyHoles()
{
	//Queue size is just a getter so faster then making a !(size == 0)
	while(queue.size() > 0)
	{
		int nextSlot = queue.dequeueInt();
		if(nextSlot == list.size()) // Last slot is empty so we need to clear it from the Entities too and clear the queue
		{
			list.pop();
			queue.clear();
			return;
		}
		else if(nextSlot > list.size()) // Slot is bigger then the largest index of the list meaning its already of the list and auto cleared.
		{
			queue.clear();
			return;
		}
		int id = list.popInt();
		while(id == 0 && nextSlot <= list.size()) // Finding the next none empty object
		{
			id = list.popInt();
		}
		if(nextSlot > list.size())
		{
			return;
		}
		map.put(id, nextSlot);
		list.set(nextSlot, id);
	}
}

public void remove(int id)
{
	presentEntities.clearFast(id);
	int index = map.remove(id);
	queue.enqueueInt(index);
	list.set(index, 0);
}

public void insert(int id)
{
	presentEntities.setFast(id);
	if(queue.size() > 0)
	{
		int index = queue.dequeueInt();
		list.set(index, id);
		map.put(id, index);
		return;
	}
	map.put(id, list.size());
	list.add(id);
}

This system would allow not to “Constantly on any change” to rebuild the Iteration queue while using a tiny bit more memory. This is only a proof of concept but if having enough large systems would maybe have a performance improvement.

Oh yeah I know I used “FastUtil” and thats not used because its class count is so big but its just there to provide a point of what my idea is.

Edit: My game will be most likely pc only and I know android is a bit different in performance, but that is what I have thought of while building my own system of this implementation, maybe it will help.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:9 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
Speigercommented, Jul 2, 2019

Other thing: The class name “World” is a really bad picked name for the “EntityComponentSystem”. Because some could just use it for “Entities” in their “World.class” which would mean they would have to implement a wrapper just to use your ECS Library (Also a reason why I manually copy it) My suggestion would be to either name the main class that you should use: “EntityComponentSystem” or “ECSWorld” So you have still a good indicator but do not try to conflict with other projects that actually want to use your Library.

A library like this should try not to colide with the most important class with a common class name.

0reactions
Speigercommented, Oct 13, 2019

Yeah fine by me.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Data Structures Stack Primitive Operations - Tutorialspoint
The stack is used in different area for evaluating expressions, call and recursion strategy etc. The stack has some primitive operations.
Read more >
!Stacks && Queues... Stacks || Queues! - DEV Community ‍ ‍
Stacks are a non-primitive data structure (or abstract data type) that have a few methods, .push() and .pop(), being the most used, ...
Read more >
Stack Data Structure - GeeksforGeeks
Stack is a linear data structure which follows a particular order in which the operations are performed. The order may be LIFO(Last In...
Read more >
Difference Between Stack and Queue - Scaler Topics
A stack and a queue are two other data structures that are used to organise ... Stack and Queue are non-primitive, linear data...
Read more >
Algorithms
1.3 STACKS AND QUEUES. ‣ stacks. ‣ resizing arrays. ‣ queues. ‣ generics. ‣ iterators ... Client: program that uses the API operations....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found