Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

Îåêßíçóå áðü ôï ìÝëïò fanisg. Τελευταία δημοσίευση από το μέλος Παναγιώτης Καναβός στις 09-02-2011, 09:33. Υπάρχουν 30 απαντήσεις.
Σελίδα 2 από 3 (31 εγγραφές)   < 1 2 3 >
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  08-02-2011, 12:31 63101 σε απάντηση της 63098

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    Επίσης, τί profiler χρησιμοποιείς? Καταλαβαίνει από .NET ή δείχνει ακόμα και την "ορφανή" μνήμη που δεν διαγράφηκε ακόμα? Όσο για το "κάνεις new" δεν είναι χαζή ερώτηση, προφανώς έχουν φτιαχτεί α * Ν αντικείμενα. Τέλος, μήπως χρησιμοποιείς structs αντί για class αντικείμενα? Στα struct όντως δημιουργούνται αντίγραφα όταν τα περνάς ByVal γιατί θεωρούνται value types όπως π.χ. ένας int. Όχι ότι ακόμα κι έτσι θα έπρεπε να βλέπεις τόση χρήση μνήμης. Κάτι περίεργο γίνεται γενικά στο πρόγραμμα.

    Μάλλον θα πρέπει να μας δείξεις τελικά τον κώδικα σου για να καταλάβουμε τί γίνεται.

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  08-02-2011, 12:38 63102 σε απάντηση της 63100

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    Συνεχίζω να υποψιάζομαι πρόβλημα "ζωντανών" references πάντως. Δυστυχώς δεν μπορώ να αναπτύξω το συλλογισμό μου παραπάνω και να επιβεβαιώσω την υποψία μου χωρίς να έχω source code.

    Ερώτηση - σκέψη (στο μοτίβο σκέψης του flyweight): Ολα τα instances τα χρειάζεσαι ως ξεχωριστά; Μήπως χρησιμοποιείς νέα στιγμιότυπα με εντελώς διπλότυπες τιμές χωρίς να είναι απαραίτητο να το κάνεις; Μήπως ένας "κουβάς" που θα ελέγχει αν το στιγμιότυπο που ζητάς υπάρχει ήδη και θα σου δίνει reference σε αυτό αντί για ένα νέο θα σου μείωνε τον αριθμό; 





    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  08-02-2011, 12:41 63103 σε απάντηση της 63100

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    fanisg:
    1. New γίνεται σε κάθε αρχικοποίηση στιγμιοτύπου (υποχρεωτικά;)
    2. Το Clone το χρησιμοποιώ συνειδητά μόνο σε ορισμένες περιπτώσεις, όπου ακολουθεί με το πέρας εκκαθάριση και =nothing.
    3. Απ'όσο γνωρίζω όχι.

    Δεν χρησιμοποιώ καθόλου unmanaged resources, com objects, dll & activex περασμένων τεχνολογιών. Αλλά πλέον δεν είμαι σίγουρος αν κάνω καλά...!

    Το σφάλμα σου είναι ότι προσπαθείς να περάσεις γνώσεις και συνήθειες ενός τελείως διαφορετικού περιβάλλοντος (VB6) στο .NET. Δεν έχει πρόβλημα το .ΝΕΤ αλλά ο τρόπος (ακόμα δεν μας έδειξες τον κώδικα) που το χρησιμοποιείς. Ο Garbage Collector φτιάχτηκε ακριβώς για να ΜΗΝ χρειάζεται να ψαχουλεύεις που να σβήσεις αντικείμενα. Αν δεν καταλαβαίνεις πως δουλεύει και προσπαθείς να τον "αναγκάσεις" να συμπεριφερθεί όπως νομίζεις, θα έχεις πρόβλημα. Για παράδειγμα, μήπως κοιτάς τη μνήμη πριν προλάβει ο GC να τρέξει? Αν δεν υπάρχει βαρειά χρήση μνήμης στο μηχάνημα ο GC δεν τρέχει (γιατί να το κάνει?) για να μην σπαταλήσει CPU. Όταν χρειαστεί το κάνει. Εδώ που τα λέμε, και σε Java ή σε C++ με garbage collection library αν δούλευες, θα αντιμετώπιζες παρόμοια προβλήματα μέχρι να αφήσεις τον GC να δουλέψει.

    Αντί να προσπαθείς να περάσεις παλιό κώδικα σε νέο περιβάλλον, φτιάξε μερικές απλές εφαρμογές για να δεις πως δουλεύει το .NET. Για να λύσεις τις απορείες σου για το memory deallocation, φτιάξε ένα απλό console app και βάλε μέσα μία λίστα με 800.000 αντικείμενα. Καθάρισε τη και δες πως και πότε καθαρίζεται η μνήμη. Έτσι θα απομονώσεις το πρόβλημα και δεν θα έχεις τις παρεμβολές όλης της υπόλοιπης εφαρμογής.




    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  08-02-2011, 12:44 63104 σε απάντηση της 63101

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    Δεν το θεώρησα χαζή ερώτηση! Απλά δεν ξέρω αν θα μπορούσε να γίνει & αλλιώς. Structures γενικά δεν χρησιμοποιώ. Ο profiler είναι της SCITECH (.NET Memory Profiler).

    Ο κώδικας των συνδεδεμένων κλάσεων είναι >20.000 γραμμές, γενικά "δουλειά" του είναι να παράγει νέες χωρικές οντότητες. Το πρόβλημά μου είναι αν πρέπει ή όχι να κάνω εξ'ολοκλήρου references ή clone. 

    Αν το refernce γεννάει αντικείμενα τότε η μόνη λύση είναι το clone?
  •  08-02-2011, 12:48 63106 σε απάντηση της 63102

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    @cap:
    Ναι, χρησιμοποιώ διπλότυπες τιμές που δεν χρειάζονται, μέχρι αποδείξεως του εναντίον. Π.χ. 2 τρίγωνα που μοιράζονται την ίδια κορυφή. Θα μπορούσε το 2ο να πάρει το σημείο ως reference του πρώτου. Αν στην πορεία όμως έπρεπε τα τρίγωνα να "ξεκολλήσουν" ή ακόμα χειρότερα το 1ο να διαγραφεί; 
  •  08-02-2011, 12:51 63107 σε απάντηση της 63104

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    Ρε παιδιά, μήπως υπάρχει και το απλό ενδεχόμενο να μην φτάνει η μνήμη γιατί μπορεί το κάθε αντικείμενο να είναι μεγάλο σε μέγεθος; Αν είναι το κάθε ένα 10K, τότε μιλάμε για 8 GB μόνο για να μπούνε στην μνήμη! 

    800.000 instances, 20.000 γραμμές κώδικα... bloated κατάσταση μου μυρίζει και μάλλον είναι θέμα ανάλυσης/σχεδιασμού.

    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  08-02-2011, 12:59 63108 σε απάντηση της 63104

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    fanisg:


    Αν το refernce γεννάει αντικείμενα τότε η μόνη λύση είναι το clone?
    Το reference δεν γεννάει αντικείμενα, είναι απλά ένα "pointer" σε μία θέση μνήμης. Αν βλέπεις πολλαπλά αντικείμενα είναι γιατί τα κρατάς εσύ κάπου. Απλά και μόνο ότι μπερδεύεις reference με clone (που όντως δημιουργεί αντικείμενα) σημαίνει ότι πρέπει να πατήσεις φρένο. 

    Απομόνωσε και δοκίμασε τον κώδικα σου για να δεις ποιά είναι η "νορμάλ" συμπεριφορά, και να πεισθείς ότι η γή είναι στρογγυλή και ο ήλιος κίτρινος. Όσο προσπαθείς να βρεις bug στο .NET θα χάνεις το χρόνο σου. Άσε που αν έχεις 20.000 μονολιθικό κώδικα ο οποίος δεν μπορεί να σπάσει, χρειάζεται σίγουρα καθάρισμα.

    Επίσης, ο profiler πρέπει να σου δίνει πληροφορίες για το που έχουν γίνει τα allocations, που υπάρχουν ακόμα references και σίγουρα πόσα αντικείμενα είναι ακόμα στη μνήμη και έχουν ξεφύγει από garbage collections. Τί σου λέει? Σε ποιά generations βρίσκονται τα αντικείμενα? Μήπως έχεις ορίσει destructors? Στην περίπτωση αυτή τα αντικείμενα παραμένουν περισσότερο στη μνήμη γιατί ο GC πρέπει να καλέσει τον destructor, όχι απλά να καθαρίσει τη μνήμη.

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  08-02-2011, 13:03 63109 σε απάντηση της 63106

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    fanisg:
    @cap:
    Ναι, χρησιμοποιώ διπλότυπες τιμές που δεν χρειάζονται, μέχρι αποδείξεως του εναντίον. Π.χ. 2 τρίγωνα που μοιράζονται την ίδια κορυφή. Θα μπορούσε το 2ο να πάρει το σημείο ως reference του πρώτου. Αν στην πορεία όμως έπρεπε τα τρίγωνα να "ξεκολλήσουν" ή ακόμα χειρότερα το 1ο να διαγραφεί; 
    Τί λες, ότι έχεις ένα αντικείμενο-κορυφή το οποίο χρησιμοποιείται από 2 τρίγωνα? Ε τότε, αν δεν ελευθερώσεις και τα δύο τρίγωνα, δεν πρόκειται να διαγραφούν ούτε αυτά ούτε η κορυφή. Από τη στιγμή που κάπου υπάρχει reference στο ένα τρίγωνο, άρα και στην κορυφή του, άρα υπάρχει και στο 2ο τρίγωνο μέσω της κορυφής του. Και αν είναι πολλά αυτά τα "μοιράσματα" θα καταλήξεις με όλα τα αντικείμενα αλληλομπλεγμένα στη μνήμη.



    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  08-02-2011, 13:05 63110 σε απάντηση της 63106

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    fanisg:
    @cap:
    Ναι, χρησιμοποιώ διπλότυπες τιμές που δεν χρειάζονται, μέχρι αποδείξεως του εναντίον. Π.χ. 2 τρίγωνα που μοιράζονται την ίδια κορυφή. Θα μπορούσε το 2ο να πάρει το σημείο ως reference του πρώτου. Αν στην πορεία όμως έπρεπε τα τρίγωνα να "ξεκολλήσουν" ή ακόμα χειρότερα το 1ο να διαγραφεί; 

    Τότε ένας συνδυασμός sharing όπου χρειάζεται και copy όπου πάλι χρειάζεται ίσως σου ελευθέρωνε λίγη μνήμη.


    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  08-02-2011, 13:06 63111 σε απάντηση της 63108

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    απλά να συνεισφέρω και εγω στην ζητήση...

    αν πατε στο performance monitor του λειτουργίκου ( start > run > perfmon ), μπορείτε να προσθέσετε κάτι όμορφους μετρητές (.ΝΕΤ CLR Memory) που υπάρχουν ψηλααα στην λίστα των objects και να διαλέξετε όλους με την αντίστοιχη εφαρμογή... ώστε να δούμε νουμερακια ωραία και χρήσιμα


    Antonios Chatzipavlis

  •  08-02-2011, 13:10 63113 σε απάντηση της 63109

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    Ξεκίνησα σουλούπωμα... δεν θέλω τα αντικείμενα να είναι references, πρέπει να είναι αυτόνομα. Πιστεύω πως τότε θα μπορέσει να γίνει εκκαθάριση.

    Για τα τυπικά, ο κώδικας δεν είναι 20.000 χύμα γραμμές, απλά είναι πολλές κλάσεις οι οποίες κληρονομούν και κληρονομούνται. Η κάθε κλάση προσφέρει τις μεθόδους και τα constructors της αυτόνομα. Θα επανέλθω αν δεν βγάλω και πάλι άκρη, πιθανώς για απόδοση υπεργολαβικά της εκκαθάρισης και τακτοποίησης. 

    Σας ευχαριστώ για το χρόνο σας. Respect & many thanks to all.
  •  08-02-2011, 13:14 63114 σε απάντηση της 63111

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    Αντώνη, αυτά είναι μερικά από τα νούμερα που σου δίνουν και οι profilers. Οι profilers όμως πάνε παρακάτω και σου δίνουν και πληροφορίες για τους τύπους των αντικειμένων, πού και πότε έγιναν allocate και άλλες πληροφορίες. Πέρα από τα performance counters χρησιμοποιούν και το Profiling API για να σου δείξουν περισσότερες πληροφορίες.

    Σωτήρη, δεν νομίζω ότι το caching έχει νόημα. Υποψιάζομαι ότι το μοίρασμα των κορυφών είναι μία προσπάθεια να "σωθεί" μνήμη. Αλήθεια, πόση μνήμη πιάνουν αυτά τα 800.000 αντικείμενα? Γιατί αν π.χ. μιλάμε για τρίγωνα τότε (800.000 τρίγωνα * 3 κορυφές * 3 σημεία * 4 bytes) = 27 ΜΒ! Δεν είναι δα και τίποτε φοβερό. 

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  08-02-2011, 14:26 63116 σε απάντηση της 63100

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    fanisg:
    Πάμε από την αρχή: 
    1. Να χρησιμοποιώ απλή εκχώρηση (=) ή clone;
    2. Τα references στο ίδιο αντικείμενο επιβαρύνουν τη μνήμη αθροιστικά;
     
    Έχοντας πρόσφατες μνήμες παρόμοιου εγχειρήματος - φαντάσου οικοδομικά τετράγωνα που έπρεπε να ομαδοποιηθούν με διάφορα κριτήρια:
    • Φόρτωσα όλα τα οικοδομικά τετράγωνα σε μια λίστα από custom objects - new για κάθε νέο object,
    • στην συνέχεια για καθένα από αυτά, περιείχε μια λίστα από τα γειτονικά του τετράγωνα - το .Add στην λίστα έβαζε το αποτέλεσμα ενός LINQ query με το Id του τετραγώνου
    • Η κύρια εργασία ήταν να φτιαχτούν ομάδες από τετράγωνα (custom object). που και πάλι υπήρχαν .Αdd στην λίστα από κριτήρια αναζήτησης - LINQ query - επάνω στα γειτονικά τετράγωνα κάθε τετραγώνου

    Καταλαβαίνεις ότι για κάθε τετράγωνο, το αντικείμενο είχε από ένα reference σε κάθε γείτονά του, αλλά και στην λίστα της ομάδας που άνηκε. Αν και υπήρχαν διαδικασίες που έβγαζαν οικοδομικά τετράγωνα από τις λίστες των ομάδων και τα έβαζαν σε άλλες ομάδας, δεν αντιλήφθηκα κάπου να έχω πρόβλημα, είτε στο perfomance, είτε στο να μένουν "σκουπίδια" στην μνήμη. Τα references είναι ουσιαστικά counters που χρησιμοποιεί ο GC για να ξέρει αν θα πρέπει να απελευθερώσει την μνήμη όταν ένα object έχει μαρκαριστεί σαν "deleted".

    Θα πρότεινα να ξαναδείς το project σου από την αρχή, ώστε να υπάρχει κάποιο κεντρικό repository των αντικειμένων που είναι το βασικό στοιχείο και όπου αλλού τα χρειάζεσαι, να τα περνάς σαν reference μέσα από το repository σου.

    George J.


    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
  •  08-02-2011, 15:26 63118 σε απάντηση της 63113

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    Συνημμένα: memory.png
    fanisg:
    Ξεκίνησα σουλούπωμα... δεν θέλω τα αντικείμενα να είναι references, πρέπει να είναι αυτόνομα.

    Εξακολουθείς να μπερδεύεις τις έννοιες. Δεν είναι τα αντικείμενα references ούτε υπάρχουν αντικείμενα που δεν είναι αυτόνομα. Αυτόνομα είναι όλα. Όταν όμως χρησιμοποιείς ένα αντικείμενο, ουσιαστικά χρησιμοποιείς ένα reference, ένα pointer στην πραγματική του θέση στη μνήμη. Ακόμα και struct αν είναι το αντικείμενο, μέσω reference του μιλάς. Reference σημαίνει "αναφορά". Αναφέρεσαι σε ένα αντικείμενο, δεν είσαι το αντικείμενο. 

    Επίσης, η έννοια της "αυτονομίας" δεν υπάρχει. Το ότι ο garbage collector ελέγχει τα references μεταξύ των αντικειμένων δεν σημαίνει ότι υπάρχει κάποια εξάρτηση μεταξύ τους, το αντίθετο. ΕΠΕΙΔΗ ΕΙΝΑΙ ΑΝΕΞΑΡΤΗΤΑ πρέπει να τα ελέγξει. Αν υπήρχε σχέση parent child, ένα child δεν θα μπορούσε ποτέ να κρατήσει ζωντανό ένα parent. Η κορυφή δεν θα μπορούσε ποτέ να κρατήσει ζωντανό ένα τρίγωνο. Αυτό όμως δεν συμβαίνει.

    Ακόμα και αν χρησιμοποιήσεις structs τα οποία περνάς στα functions byval (οπότε δημιουργείς αντίγραφα) δεν θα κάνεις τίποτε γιατί το πρόβλημα δεν ήταν το byval αλλά οι σχέσεις μεταξύ των αρχικών αντικειμένων.


    Δοκίμασε πρώτα με καθαρά αντικείμενα και χωρίς πειρασμένες παραμέτρους στις μεταβλητές, χωρίς αντικείμενα που "μοιράζονται", για να δεις πως δουλεύει κανονικά το .NET και μετά δοκίμασε τις βελτιώσεις. Η συμπεριφορά που βλέπεις τώρα δεν είναι ομαλή και οφείλεται στις παρεμβάσεις που έχουν γίνει.

    Τώρα, για να πεισθούμε ότι όντως δεν χάνεται μνήμη και τα references δεν φταίνε, έφτιαξα τις παρακάτω κλάσεις για τρίγωνα:
     public class Point3D
            {
                public int X { get; set; }
                public int Y { get; set; }
                public int Z { get; set; }
            }
    
            public class Triangle
            {
                public Point3D[] Vertices { get; set; } 
            }
    Και έφτιαξα και μία λίστα με 800.000 τρίγωνα, τα οποία πειράζω με τον παρακάτω κώδικα:
     static void Main(string[] args)
            {
                Console.WriteLine("Idle");
                Console.ReadKey();
                
                var triangles = Generate(800000);            
                
                Console.WriteLine("Generated");
                Console.ReadKey();
    
                Move(triangles);
                
                Console.WriteLine("Moved");
                Console.ReadKey();
            }
    
            private static void Move(List<Triangle> triangles)
            {
                foreach (Triangle triangle in triangles)
                {
                    MoveTriangle(triangle);
                }
            }
    
            private static void MoveTriangle(Triangle triangle)
            {
                foreach (Point3D edge in triangle.Vertices)
                {
                    edge.X += 10;
                    edge.Y += 10;
                    edge.Z += 10;
                }
            }
    
            public static List<Triangle> Generate(int count)
            {
                var triangles=new List<Triangle>();
                var r=new Random();
                for(int i=0;i<count;i++)
                {
                    triangles.Add(new Triangle {
                                    Vertices=new [] {
                                            new Point3D{X=r.Next(),Y=r.Next(),Z=r.Next()},
                                            new Point3D{X=r.Next(),Y=r.Next(),Z=r.Next()},
                                            new Point3D{X=r.Next(),Y=r.Next(),Z=r.Next()},
                                        }});
                    
                }
                return triangles;
            }

    Η μνήμη του προγράμματος ανεβαίνει στα 90 MB περίπου μόλις δημιουργηθούν τα αντικείμενα και παραμένει εκεί, παρότι (ή μάλλον επειδή) η λίστα και τα αντικείμενα περνάνε ως references στη Move και τη MoveTriangle. 

    Δοκίμασα επίσης να βγάλω τον κώδικα Generate, Move σε function και να το επαναλάβω 100 φορές. Αυτό που είδα ήταν ότι η μνήμη ανεβοκατέβαινε μεταξύ 90 και 160 MB καθώς ο GC δεν έτρεχε αμέσως μετά από κάθε iteration. Αυτό όμως δεν με επηρέαζε καθώς στο τέλος η μνήμη πάντα καθάριζε.



    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  09-02-2011, 09:24 63131 σε απάντηση της 63118

    Απ: Πρόβλημα με την απελευθέρωση μνήμης στη VB.NET

    Ευχαριστώ πολύ για όλο τον κόπο που κάνετε.
    Καταρχήν δεν μπορώ να χρησιμοποιήσω repository & references (κάτι που προσπάθησα μεν, απλά δεν μου έκανε) διότι πολλά αντικείμενα δημιουργούνται (και πρέπει να διαγράφονται) ως ενδιάμεσα στάδια υπολογισμών. Εκεί έχω βασικά το πρόβλημα (φαντάζομαι). Κατά τα άλλα η λογική είναι θεωρητικά αντίστοιχη με τον κώδικα της παράθεσης, απλά όλες οι διαδικασίες των σύνθετων οντοτήτων, ενώ χρησιμοποιούν ως βάση την απλή οντότητα τύπου Poiint3D, δημιουργούν είτε ως τελικά είτε ως ενδιάμεσα αποτελέσματα άλλα σύνθετα ή απλά αντικείμενα τα οποία πρέπει εν τέλει να αλληλεπιδράσουν με το αρχικό... μπάχαλο...

    Πήρα ωστόσο μια καλή γραμμή από όσα γράψατε. Ελπίζω να έχω καλά νέα σύντομα. 
    Respect
Σελίδα 2 από 3 (31 εγγραφές)   < 1 2 3 >
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems