Sto lavorando a un emulatore come progetto side/fun, ma sto riscontrando alcuni problemi di prestazioni e non riesco a capire da dove provengano.Le prestazioni misteriose si degradano con il ciclo infinito Open GL +
L'applicazione è composta principalmente da un GLKView per la visualizzazione e da un thread separato con un loop infinito per l'emulazione della CPU. Ecco un esempio con tutto il codice di emulazione effettivo preso fuori che visualizza ancora il problema:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
GLKView *glView = [[GLKView alloc] initWithFrame:self.view.bounds];
glView.delegate = self;
glView.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:glView.context];
[self.view addSubview:glView];
glView.enableSetNeedsDisplay = NO;
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:glView selector:@selector(display)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
dispatch_get_main_queue(), ^{
dispatch_async(dispatch_queue_create("yeah", DISPATCH_QUEUE_SERIAL), ^{
CFTimeInterval lastTime = 0;
CFTimeInterval time = 0;
int instructions = 0;
while(1) {
// here be cpu emulation
if (lastTime == 0) {
lastTime = CACurrentMediaTime();
} else {
CFTimeInterval newTime = CACurrentMediaTime();
time += newTime - lastTime;
lastTime = newTime;
}
if (++instructions == 1000) {
printf("%f\n", 1/(time * 1000));
time = 0;
instructions = 0;
}
}
});
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
// Here be graphics
}
@end
In questo modo, i cicli infiniti è fondamentalmente solo contando E 'iterazioni e la stampa fuori di essa la frequenza in MHz.
Quindi, il problema è che quando l'app parte, il loop gira a circa 9-15 MHz (su un iPhone6), e se guardo il rapporto GPU in Debug Navigator di Xcode, posso vedere che il frame della CPU il tempo è 0.2ms poi, dopo l'esecuzione per un paio di secondi, il ciclo scende a 1-5 MHz, e le lasso di tempo della CPU aumenta a 0.6ms
Se io disattivare gli aggiornamenti GLKView, poi i loop mai diventare più lento
ho anche provato ad utilizzare diversi threading API (GDC, NSThread, pthread), ma che non sembra avere alcun impatto
La mia domanda è, sto facendo qualcosa di sbagliato da qualche parte? È solo un caso di GLKView che non viene inizializzato completamente per un paio di secondi e quindi utilizza meno CPU rispetto al normale e ottengo un aumento di velocità? In qualsiasi altro modo potrei strutturare il codice per ottenere il massimo delle prestazioni nel ciclo?
Aggiornamento ho fatto un po 'di test, e ho notato che il problema è presente anche quando si utilizza un CAEAGLLayer invece di un GLKView, inoltre, che non accade sul simulatore, solo su un dispositivo. Ho provato anche con un'applicazione OS X con NSOpenGLView e non succede neanche ...
Update 2 ho cercato di iniziare la discussione dopo un po ', invece di subito, e se il ritardo è più grande della tempo ci vuole di solito per il calo a verificarsi, il filo inizia già rallentato ... Non proprio sicuro di cosa fare di esso ...
metallo Aggiornamento ho provato ad utilizzare metallo invece di OpenGL, utilizzando semplici il modello di magazzino da Xcode, e sta accadendo anche con esso ...
non si dovrebbe creare un ciclo infinito su qualsiasi thread . È necessario pianificare un'operazione che viene eseguita una volta per ogni fotogramma ed eseguirne l'attività una sola volta per ogni fotogramma. Ci sono molti modi per farlo, ma per prima cosa controlla se c'è qualcosa incorporato in glkit prima di usare qualcosa come link update update/delegate o nstimer. Possibili indicazioni: http://stackoverflow.com/questions/13653113/multithreading-glkview-drawing – LearnCocos2D
Scusa, ma ho bisogno di un ciclo infinito, è così che funzionano gli emulatori. Eseguendo un'attività ogni frame mi darebbe al massimo 60 "operazioni" ogni secondo, ho bisogno di molto più di quello (circa 1000000 volte circa ...) Per gli aggiornamenti dello schermo va bene, ma non per l'emulazione della CPU –
penso che sia necessario leggere molto di più su come funzionano l'emulazione, il multithreading e la sincronizzazione. Supponiamo che la CPU della macchina emulata venga eseguita a 1 mhz e che ci sia una coda di comandi, ognuno dei quali richiede un numero noto di cicli di CPU da eseguire. Dovresti quindi eseguire quelli, diciamo 1500, comandi che la cpu potrebbe eseguire in un dato intervallo di tempo ed emularli sulla macchina host. Quindi inizi un nuovo ciclo. Questo è un modello molto semplificato. Non avrai bisogno di un ciclo infinito e dovrai disporre di punti di sincronizzazione (tipicamente alla frequenza vsync della macchina emulata). – LearnCocos2D