Salta al contenuto principale


l’amore 2d e gli oggetti orientifici, ma quello che accade non fa divertire (test e valutazioni prestazioni OOP su Love2D)


Visti gli imprevisti con HaxeFlixel che non ho ancora avuto il tempo di elaborare qui, stavo (ri)considerando il basato Love2D che, ultimamente mi sono (ri)accorta, gira su talmente tante piattaforme da rendere inutile anche fare degli esempi qui. La cosa seccante di quel coso, però, è che non è esattamente un motore di gioco, quanto più un framework multimediale… e quindi, a differenza di Flixel e altri robini, non ha tutte le varie utilità che è bene avere per poter sviluppare qualcosa senza partire dallo zero assoluto… e quindi, l’idea sarebbe di creare una specie di motorino per esso per gestire cose comuni come sprite, fisica, boh, queste cose (non) belle. 🤥

Ovviamente, il problema inevitabile è sorto immediatamente dopo una giornata di lavoro iniziale — a dire il vero, fatta per fortuna con le pinze, perché ero sotto sotto pronta a vedere cose storte accadere — e cioè che, con una dose di OOP in realtà nemmeno troppo grossa per gli standard comuni, le prestazioni sono crollate così tanto a picco che, per un semplice giochino di Breakout (la demo di HaxeFlixel, che ho adattato strada facendo per testare), da un lato su PC l’uso di CPU si aggirava attorno al 10-15% (che è tipo il quintuplo di cosa fa la stessa demo in HaxeFlixel)… mentre, su piattaforme pazzurde come il 3DS era letteralmente ingiocabile, facendo 5 secondi a frame (e pensare che io ho il new, che è più veloce). 💀

Ho fatto un po’ di ricerca e — per quanto fosse a me comunque ovvio che una programmazione ad oggetti basata principalmente sull’ereditarietà rende un programma più lento, perché i sassi elettronici sono fatti per eseguire istruzioni sequenziali e lavorare con memoria quanto più continua possibile, che è il contrario di cosa succede con tutte quelle classi che estendono classi che estendono il mercato che mio padre comprònon immaginavo che su Lua il calo prestazionale fosse tale da essere non solo evidente, ma proprio fuori scala in certi casi. E ora, dunque, i problemi sono grossissimi. 😤

Anche stavolta ho raccolto molti link a riguardo di questa ennesima causa di sofferenza per me, e in realtà ancora non ho capito bene la questione, ma un grande problema sembra essere causato dagli accessi a tabelle nidificate, e alle chiamate di funzioni fatte più del necessario anche per operazioni altrimenti veloci… e nel mio caso certamente una buona parte di overhead in questo senso sarà causata dal fatto di non scrivere Lua nativo, bensì usare Haxe (o in alternativa, TypescriptToLua) per traspilare a Lua, ma sentivo che il problema non poteva essere solo il codice bloattato generato da questi affari… 🧨

E infatti, scrivendo in Lua puro un piccolo benchmark (battezzato al volo solo per dare un titolo al memo: Love2D fucking rectangles, genera innumerevoli rettangoli e li fa muovere calcolando le collisioni), prima in modo classico e poi con un minimo di OOP, ed eseguendolo oltre i limiti del ragionevole, ho visto le cose brutte: la versione OOP è in effetti più lenta. Non tanto più lenta, e comunque dipende dalle opzioni con cui la si fa girare, ma solo perché è comunque molto semplice… a differenza del motorino che tanto vorrei creare per replicare la API di HaxeFlixel in Love2D per quanto possibile (evidentemente, non molto possibile). 😭
Modalità 1 sul PC come descrittaModalità 2 sul PC come descritta, a 4 minutiModalità 2 sul PC come descritta, a 18 minuti circaModalità 2 sul 3DS come descritta, a 1 e 4 minuti circa
Dopo ben 4 (quattro) immagini non so se ho voglia di elaborare oltre… Ma, in sostanza: in una modalità, il programma genera solo X (200mila) rettangoli all’avvio, mentre nell’altra ne genera X (200) a frame, andando all’infinito, calcolando sempre le collisioni… e quindi con la prima si esclude una lentezza dovuta alla continua istanziazione di oggetti, mentre la seconda da modo di vedere come un programma rallenta nel tempo rispetto all’altro (generando meno oggetti a parità di tempo). 💥

Nella prima modalità, il carico è basato principalmente sull’accesso alla chiamata draw, quindi non potevo limitare il numero di quadrati effettivamente visibili, e quindi ho potuto eseguirla solo su PC, dove si nota in media un rallentamento di circa il doppio per la versione OOP, che accede a svariate proprietà nidificate per fare il disegno… Mentre, nella seconda la prova il carico era più il resto, quindi ho deciso di limitare il numero di rettangoli visibili a schermo ad ogni frame agli ultimi X (500), e questo mi ha permesso di eseguire il programma pure sul 3DS senza che crashasse (credo ci siano limiti di VRAM lì), ma sia su PC che su 3DS si vede che la versione non-OOP riesce a generare in media 1,2 sprite in più per delta di tempo, differenza che nel corso di minuti diventa di migliaia di sprite. 😵

Incredibile, spassoso, magicante, ma… e adesso??? Boh! Dovrò ingegnarmi pesantemente per creare un motorino sufficientemente generalizzato da poter essere usato come comoda libreria per molti giochi Love2D, ma che allo stesso tempo sia efficiente… ma qui casca l’asino, perché per implementare concetti come uno sprite, che oltre ai classici dati come posizione X e Y ha un oggetto “disegnabile”, che può essere un’immagine o una forma geometrica, che quindi richiede chiamate della API Love2D completamente diverse dietro le quinte, non vedo alternativa non incasinata se non l’OOP; ma non basterà usare più la composizione che l’ereditarietà, bensì per sconfiggere l’overhead serviranno mosse di design interne talmente scomode che ho davvero tanta paura anche solo a pensare di scriverle… 😱

#benchmark #development #LOVE2D #Lua #test #testing

Questa voce è stata modificata (1 giorno fa)
in reply to minioctt

comunque testare le prestazioni del codice col 3ds è crazy.