Xantos ha scritto:
Stavo pensando al fatto che il C e' stato usato e riusato miliardi di volte dalla sua nascita, molto piu' che non altri linguaggi piu' recenti...
Sì, in effetti c'è una larga base di codice C per i Mud non da sottovalutare, anche se troppo spesso poco originali e ripetitivi. Io stesso scelsi lo Smaug anni fa come codice base perché c'era già pronta molta roba, però devo dire a posteriori che probabilmente il tempo di sviluppo che avre speso con lo smaug per implementare le cose che sto implementando e che implementerò con il Python, sarà maggiore nonostante abbia iniziato da zero con un mud in Python, e sono abbastanza convinto di ciò.
Xantos ha scritto:
Riguardo al tuo approccio con il Python, mi sono sempre chiesto: ma il delegare certi meccanismi al garbage collector, o al gestore di stringhe, o ad altri complessi componenti strutturali "invisibili", non rischia di rallentare l'esecuzione del codice stesso?
Vero, python è meno performante del C, dipende dai casi, ma così a naso direi di 10 volte nei miei utilizzi, tuttavia dipende quanto uno se la gioca con i colli di bottiglia che ha, prima scrivi il codice, poi lo profili e poi ne migliori le parti e solo quelle che fanno da collo di bottiglia con algoritmi intelligenti e meccanismi furbi.
Il python ha delle built-in che sono compilate in puro C, utilizzando solo quelle ed evitando chiamate a funzione (che oihmé sono la croce sulle performance dei programmi python in generale) arrivi a velocità comparabili a quelle del C, ovviamente il tutto ciò a discapito della leggibilità e manutenibilità del codice.
Per esempio ho dovuto evitare di utilizzare una funzione con del codice utilizzato più volte in varie parti per motivi di performance, pena: manutenibilità e leggibilità.
[Per completezza aggiungo che il python usa un garbage collector a reference counting, che è più veloce rispetto a soluzioni cicliche; che utilizza delle pool di memoria suddivise per tipologia di dato, queste zone di memoria sono già allocate, quindi se uno crea una nuova stringa essa va ad inseririsi in una di queste zone pronte all'uso, diminuendo il problema di performance di allocazione; infine il python non è interpretato ma semicompilato, proprio come il Java. Insomma ha le sue tecniche interne furbe per essere performante]
Tuttavia devo dire che il consumo di processore di Aarit, il mio mud in Python, non mi preoccupa troppo, invece il consumo della ram sta già raggiungendo livelli interessanti.
Sul server su cui gira la versione che ho rilasciato in open source il processore occupava il 15%, la versione attuale con tante aggiunte ora occupa slo il 9%, questo perché la versione rilasciata non l'avevo mai ottimizzata.
Ho sempre avuto un po' di paura che il mud risultasse lento e ho sempre fatto scelte di caching, di memorizzazione e di memoization per velocizzare il tutto.. e infatti ho esagerato.. avviando il mud da zero già occupa 50 mega, ed è tanto, il mud è appena agli inizi e deve fare un mucchio di cose, vedrò cosa potrò inventarmi, ma sono fiducioso, ho già il mente qualche trucchetto e refactoring.
Xantos ha scritto:
Queste componenti sono state scritte ed ottimizzate per essere massimamente efficienti in condizioni "genericamente favorevoli". Di certo si possono trovare situazioni in cui scrivendo a mano la deallocazione di una certa parte di memoria (ad esempio) si rende quella parte di codice piu' efficente che non lasciando il tutto in mano al GC.
Sì, ma secondo me il gioco non ne vale la candela, cioè è come studiare un manuale tecnico in lingua straniera, se sei bravo con quella lingua, te la cavi, ma se non sei bravo la comprensione del manuale ne risente, e magari non poco.
Cosa simile è l'utilizzo di un linguaggio di programmazione piuttosto di un altro, se vuoi utilizzarne uno di basso livello, cioè uno meno vicino all'astrazione umana, dovrai perdere tempo a pensare a tutte quelle cose tecniche in più (come l'allocazione della memoria e la relativa pulizia) e, a meno che tu non sia bravo bravo, ciò influenzerà sulla soluzione implementata.
Xantos ha scritto:
Probabilmente poi in un mud queste condizioni non si verificano mai, oppure troppo raramente per influire nella velocita' del gioco, ma il dubbio viene... cosi' come il dubbio che l'interpretazione del codice non compilato abbia un certo peso nella velocita' effettiva di ogni game_loop.
In effetti una comunicazione tcp di solito ci mette di più di qualsiasi esecuzione di comando. Riguardo invece alla game loop la trovo una soluzione per certi versi obsoleta e concettualmente errata, tuttavia anche io la utilizzo, per semplicità implementativa, rispetto ad una sistema ad eventi (anche se mi sto spostando in quella direzione).
Difatti la game loop è uno dei miei colli di bottiglia: vi eseguo dei check sui reset, poiché ho i reset a tempo che scattano ad una certa ora rpg, ciclare su tutti i reset delle aree del mud ogni secondo rpg (due secondi reali) quando ben pochi di tali reset si attiverano.. è demoniaco..
Ma alla fin fine, come ho detto all'inizio, di meccanismi furbi se ne possono trovare, per esempio: se si crea una lista di mob, popolata man mano durante il ferimento degli stessi (e che quindi abbisognino di update per ripristinare la salute), il controllo ciclico di tale lista "probabilmente" ha un tempo di esecuzione minore rispetto al controllo cicliclo su tutti i mob del mud, il cui 90% sarà in perfetta salute. So che non è così semplice ed è solo un'ipotesi, però...
Xantos ha scritto:
Sono assolutamente concorde con il beneficio della velocita' di scrittura. Ma se rallentare il coding del doppio (ad esempio) risulta nel velocizzare il gioco del 10%... chi non sceglierebbe questa alternativa?
Ma assolutamente non la sceglierei! E' come chiedermi tra scegliere una macchina che va' a 100 all'ora ed una che va' a 110 all'ora che mi costa il doppio, magari anche più figa eh... Ma...
Cioè.. io personalmente codo 4 volte più velocemente in python che in C, non è sparata lì', ho fatto dei confronti con alcuni pezzi di codice di Mud che ho scritto in C e la translazione in python (verò è anche che ora ho tutta un'esperienza alle spalle.. ma è anche verò che sto implementando da zero alcune cose).
Ecco, ora cosa significa esattamente 4 volte? Significa che io in un anno scrivo un codice con le stesse feature che un coder in C con le mie stesse capacità scrive in 4 anni.
Facciamo che questo codice in C consumi metà risorse, sia processore che memoria.
Ora facciamo caso che io, che ho scritto il mud in python, upgradi il mio server per andare il doppio, quando spendo all'anno? Ok, facciamo 200 euro al posto di 100?
Ora direi che 200 euro * 4 anni < costo di 3 anni della propria vita spesi in coding per un Mud (supponiamo tante ore)
A meno che uno non scriva il mud perché gli piaccia scriverlo in C eh.. per soddisfazione personale, a quel punto ok, il costo dei tre anni si autoammortizza. Tuttavia in quel caso creare un mud non è l'unico, o non lo è affatto, obiettivo.
Considerazioni personali eh.. poi uno può essere due volte più veloce a scrivere in C rispetto a me con il Python e vabbe'.. il punto di vista cambia.
Quello che però ti vorrei far notare è che la tua frase "[...] Ma se rallentare il coding del doppio (ad esempio) risulta nel velocizzare il gioco del 10%... chi non sceglierebbe questa alternativa?" è squisitamente da C-ista, cioè del: performance a tutti i costi; ne riconosco il sapore perché anch'io la pensavo come te.