The only way of speaking about the offtopic is with numbers.



Code:
-----------------------------------------
| a wait per entity | own scheduler     |
| 1 byte stack      | 1 byte stack      |
-----------------------------------------
| a wait per entity | own scheduler     |
| 128 bytes stack   | 128 bytes stack   |
-----------------------------------------


Notice that the stack memory size has also its impact in the difference.

Click to reveal..

Code:
#include <acknex.h>
#include <default.c>

#define ENT_COUNT    10000
#define STACK_SIZE   1
#define COMPLEXITY   1

ENTITY *ents[ENT_COUNT];

action actWait() {
	BYTE _n[STACK_SIZE];
	while(1) {
		int _i = 0;
		for(; _i<COMPLEXITY; _i+=1)
			_n[random(STACK_SIZE)] = random(256);
		wait(1);
	}
}

var actList(ENTITY *_ent) {
	BYTE _n[STACK_SIZE];
	int _i = 0;
	for(; _i<COMPLEXITY; _i+=1)
		_n[random(STACK_SIZE)] = random(256);
	return -1;
}

void entLoop () {
	while(!key_esc) {
		wait(1);
		ENTITY **_ent = ents;
		ENTITY **_entLast = _ent + ENT_COUNT;
		for(; _ent<_entLast; _ent++) {
			if(*_ent == NULL)
				continue;
			var _result = actList(*_ent);
			if(_result == 0)
				continue;
			switch(_result) {
				case 1:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 2:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 3:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 4:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 5:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 6:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 7:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 8:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 9:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 10:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 11:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 12:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 13:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 14:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 15:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 16:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 17:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 18:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				case 19:
					ent_remove(*_ent);
					*_ent = NULL;
					break;
				default:
					break;
			}
		}
	}
}

void main () {
	max_entities = ENT_COUNT;
	
	void _act ();
	_act = actWait;
//	_act = actList;
	
	level_load("");
	def_debug();
	int _i = 0;
	for(; _i<ENT_COUNT; _i+=1)
		ents[_i] = ent_create(SPHERE_MDL, vector(0, 0, -1000), _act);
	if(_act == actList)
		entLoop();
}



I gived a bit of complexity to the scheduler loop so it can be considered a complete flux manager. The numbers speak by themself. It is clear it gains performance with a single while loop but it is not that much. Take into account that we are speaking about a difference of 3/10000 ms/ent: the time taken by few operations. Bad programming practices will waste more time.

Salud!