Visualizzazione dei risultati da 1 a 6 su 6

Discussione: [C#] Pulire la memoria

  1. #1

    [C#] Pulire la memoria

    Buongiorno a tutti
    per prendere confidenza col linguaggio sto facendo un programma per giocare a scacchi contro il pc. Mi sto sforzando di non utilizzare i puntatori, per creare l'albero delle possibili combinazioni ho utilizzato liste di liste di oggetti.
    Visto che in poche mosse vengono creati miliardi di oggetti, ho la necessità di pulire la memoria quando lo desidero io come si poteva fare in c++, senza dover aspettare il Garbage Collector. Se riesco a pulire la memoria in tempo reale posso aggiungere un paio di livelli all'albero eliminando le combinazioni "inutili".
    Esiste un modo?

    Grazie!

  2. #2

    Re: [C#] Pulire la memoria

    Originariamente inviato da Luciano79
    Mi sto sforzando di non utilizzare i puntatori, per creare l'albero delle possibili combinazioni ho utilizzato liste di liste di oggetti.
    In realtà tutti gli oggetti "class" sono "reference types", per cui ogni volta che crei una variabile del loro tipo in realtà implicitamente stai creando un puntatore; per questo quindi "di nascosto" stai sempre usando puntatori.
    Visto che in poche mosse vengono creati miliardi di oggetti, ho la necessità di pulire la memoria quando lo desidero io come si poteva fare in c++, senza dover aspettare il Garbage Collector. Se riesco a pulire la memoria in tempo reale posso aggiungere un paio di livelli all'albero eliminando le combinazioni "inutili".
    Normalmente non ce n'è alcun bisogno; il GC tiene d'occhio il numero di oggetti creati e la memoria occupata, e si attiva autonomamente quando lo ritiene necessario. In condizioni normali cercare di battere in furbizia il GC risulta solo in prestazioni peggiori.
    Esiste un modo?
    GC.Collect(); ma evita.

    ---

    Tra parentesi, C# è trattato nella sezione "Visual Basic e .NET Framework"; provvedo a spostare il thread.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Grazie MItaly,
    l'oggetto contiene anche variabili di tipo valore. Per il momento ho pensato di impostare gli oggetti da eliminare a null, impostando prima a null tutti gli oggetti di tipo riferimento presenti in esso, ovvero di eliminarne i puntatori.
    Il mio dubbio è: lo spazio dedicato alle variabili di tipo valore (per esempio ho diversi interi), che fine fa? Mi sembra di aver capito che pur impostando a null l'oggetto, la memoria rimane comunque allocata in attesa del GC.
    Uso C# da solo un mese, non mi sono mai posto il problema di dover forzatamente liberare la memoria, ma ora ne uso davvero tanta. Oltre a cercare di aggiungere più livelli possibili non posso pensare di valutare la mossa successiva se non sono sicuro di eliminare del tutto l'albero costruito in precedenza.
    Provo a dare un occhio a GC.Collect().

    Grazie!
    Luciano

  4. #4
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    No. non devi usare GC.Collect()

    se da una collection rimuovi un item con lista.RemoveAt(i) non devi preoccuparti di altro.
    Se internamente ad un metodo o in generale ad uno scope, non usi piu un oggetto (collection comprese), il GC lo rimuoverà all'occorrenza anche se l'ambito dello scope non è terminato e senza bisogno di impostarlo a null. Non si vedono mai programmi in c# dove di tanto in tanto per essere sicuri di non incorrere in un MemoryException si piazzano righe come:

    list1 = null;

    questo non significa che non esistono piu i problemi di performance, anzi...

    1) Stai usando quale collection? List, Dictionary? innanzitutto (cosa molto imprtante) è generic?
    2) I procedimenti di rimozione oggetti dalle collection possono portare a scrivere righe non proprio performanti sia in termini computazionali che in termini di memory-usage. Innanzitutto devi sapere che ci sono collection per ogni occasione e per grosse liste meglio usare qualcosa di specializzato come le dictionary o gli hashset. Gli hashset per esempio gestiscono la rimozione con il metodo RemoveWhere(). Se usi collection piu "classiche" evita di avere una doppia collection per la rimozione ed evita i metodi Remove() e RemoveAt() in favore di RemoveAll(predicate):

    codice:
    list1.RemoveAll(l => Test(l)); //è il modo migliore per ripulire una collection
    comunque tieni a mente che:
    Quando hai a che fare con soli oggetti managed i problemi di mancanza di memoria li hai solo se ti si solleva una OutOfMemoryException e non li risolvi agendo sulla GC ma ottimizzando il codice.

  5. #5
    Purtroppo l'albero (le liste List<> che lo compongono) per comodità è generic, quindi dal punto di vista del GC è sempre in uso. Ho impostato il programma convinto di poterlo eliminare su richiesta, forse ragiono ancora troppo come in C.
    Non posso eliminare le liste per intero, perchè la logica con la quale sto costruendo il programma è la seguente:

    - creo l'albero di tutte le combinazioni possibili fino a N livelli (ora N è fisso, in futuro voglio renderlo variabile in base alla memoria disponibile)
    - do un valore ad ogni nodo dell'albero (num. di pezzi, posizione...)
    - decido qual'e' la mossa migliore per il pc con l'algoritmo MinMax.

    Sono arrivato fin qui, ma voglio implementarlo nel seguente modo:
    visto che valuto tutte le posizioni, anche quelle insensate, la maggior parte dei rami portano ad una posizione evidentemente perdente per il pc (da giocatore di scacchi direi almeno il 90%, le mosse buone sono sempre poche in proporzione alle mosse possibili). Vorrei poter eliminare quei nodi riconoscendoli dal valore molto basso per liberare spazio e aumentare i livelli dell'albero, magari ripetere questa operazione più volte. Questi nodi però fanno parte di liste che contengono anche posizioni buone, quindi devo eliminarli uno ad uno, dando per scontato che se decido di eliminare un nodo allora elimino anche tutti i suoi figli (pur se il valore di essi aumenta nei livelli successivi).
    Da quel che mi dici, mi fa pensare che per questo programma forse conveniva usare i puntatori.

  6. #6
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    Forse non ho scritto con chiarezza ma la collection va benissimo generic.
    Con l'algoritmo in questione non ho affinità però posso aiutarti con il linguaggio.

    se il tuo nodo è questo:

    codice:
    class Nodo
    {
      public int punteggio {get;set;}
      public List<Nodo> Figli {get;set;}
    }
    dal nodo n puoi:

    codice:
    n.Figli.RemoveAt(2); 
    n.Figli.Clear();
    n.Figli.RemoveAll(f => f.punteggio < 10);
    la prima istruzione rimuove il terzo figlio di n
    la seconda istruzione elimina tutti i nodi figli (la lista vuota continua ad esistere).
    la terza rimuove tutti i figli il cui punteggio è minore di dieci.

    in tutti e tre i casi puoi considerare la memoria precedentemente occupata dai nodi eliminati libera fin dall'istruzione successiva.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.