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

 

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

Generics vs Regular Collections

Îåêßíçóå áðü ôï ìÝëïò anjelinio. Τελευταία δημοσίευση από το μέλος anjelinio στις 19-11-2005, 19:09. Υπάρχουν 0 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  19-11-2005, 19:09 7196

    Generics vs Regular Collections

    Την τελευταία εβδομάδα παρακολούθησα ένα σεμινάριο της Microsoft, ονόματι "Whidbey Combined Course".
    Βασικά, ήταν ένα γενικότερο introduction στα νέα features του Visual Studio 2005 και του .NET 2.0.

    Ένα απο τα Labs, είχε να κάνει με language enhancements, και επικεντρωνόταν στα Generics.

    Το Lab ήταν απλό. Δημιουργούσες ένα Stack class, χρησιμοποιώντας το γενικό object type σαν τύπο παραμέτρου για τις μεθόδους του Stack ( Push(object obj) & object Pop(); ), και ένα ακόμη Stack implementation, χρησιμοποιώντας Generics.

    Ένα test προγραμματάκι που είχε μαζί, καλούσε τις μεθόδους 2 instances, μια απο κάθε τύπο Stack, και χρονομετρούσε πόσο θα χρειαστεί για να κάνει Push() & Pop() μερικές χιλιάδες int's.

    Το αποτέλεσμα ήταν εντυπωσιακό ! Το Generics implementation ήταν πολύ πιο γρήγορο. Το Lab τελείωνε λοιπόν με τη φράση "the generics implementation is almost an order of magnitude faster than a regular stack". 

    Αυτό που είδα με εντυπωσίασε πάρα πολύ, αρκετά για να το ψάξω λίγο περισσότερο στο διάλειμμα. Παρακάτω έχω τα 2 Stack sources:

     

    using System;

    using System.Collections.Generic;

    using System.Text;

     

    namespace GenericsTest

    {

        class RegularStack

        {

            private int         _size = 0;

            private object[]    _elements = new object[0];

     

            private int _currentIndex = 0;

     

            public RegularStack(int size) {

                this._size = size;

                this._elements = new object[_size];

            }

     

            public void Push(object obj)

            {

                this._elements[_currentIndex] = obj;

                _currentIndex++;

            }

     

            public object Pop()

            {

                return this._elements[--_currentIndex];

            }

        }   

    }

     

    using System;

    using System.Collections.Generic;

    using System.Text;

     

    namespace GenericsTest

    {

        class GenericStack<T>

        {

            private int         _size = 0;

            private T[]    _elements = new T[0];

     

            private int _currentIndex = 0;

     

            public GenericStack(int size)

            {

                this._size = size;

                this._elements = new T[_size];

            }

     

            public void Push(T obj)

            {

                this._elements[_currentIndex] = obj;

                _currentIndex++;

            }

     

            public T Pop()

            {

                return this._elements[--_currentIndex];

            }

        }

    }

    και το main προγραμματάκι που τα χρονομετρεί:

    using System;

    using System.Collections.Generic;

    using System.Text;

     

    namespace GenericsTest

    {

        class Program

        {

            public delegate void TimedMethod();

     

            public static long ExecuteTimer(TimedMethod _method) {

                long startTicks = DateTime.Now.Ticks;

                _method();

                long totalRunTicks = (DateTime.Now.Ticks - startTicks);

     

                return (totalRunTicks / TimeSpan.TicksPerMillisecond);

            }

     

            public static void UseRegular() {

                RegularStack _Stack = new RegularStack(repetitions);

                for (int i = 0; i < repetitions; i++)

                {

                    _Stack.Push(i);

                   

                }

     

                for (int i = 0; i < repetitions; i++)

                {

                    int retVal = (int)_Stack.Pop();

                }

            }

     

            public static void UseGeneric()

            {

                GenericStack<int> _Stack = new GenericStack<int>(repetitions);

                for (int i = 0; i < repetitions; i++)

                {

                    _Stack.Push(i);

     

                }

     

                for (int i = 0; i < repetitions; i++)

                {

                    int retVal = _Stack.Pop();

                }

            }

     

            public static int repetitions = 10000000;

     

            static void Main(string[] args)

            {

                long regTime = ExecuteTimer(new TimedMethod(UseRegular));

                long genTime = ExecuteTimer(new TimedMethod(UseGeneric));

     

                Console.WriteLine("Regular Stack Time {0} - Generics Stack Time {1}", regTime, genTime);

                Console.ReadLine();

            }

        }

    }

     

    Τρέχοντας το πρόγραμα, βλέπουμε:

    Regular Stack Time 2015 - Generics Stack Time 234

    .. πράγματι, φαίνεται οτι το GenericStack είναι όντως 10 φορές πιο γρήγορο. Οπότε αποφάσισα να αλλάξω λίγο τον κώδικα, χρησιμοποιώντας strings σαν παραμέτρους για τα 2 Stacks.

     

    public static void UseRegular() {

                RegularStack _Stack = new RegularStack(repetitions);

                for (int i = 0; i < repetitions; i++)

                {

                    _Stack.Push(i.ToString());

                   

                }

     

                for (int i = 0; i < repetitions; i++)

                {

                    string retVal = (string)_Stack.Pop();

                }

            }

     

            public static void UseGeneric()

            {

                GenericStack<string> _Stack = new GenericStack<string>(repetitions);

                for (int i = 0; i < repetitions; i++)

                {

                    _Stack.Push(i.ToString());

     

                }

     

                for (int i = 0; i < repetitions; i++)

                {

                    string retVal = _Stack.Pop();

                }

            }

    .. τώρα, τρέχοντας το πρόγραμμα, βλέπουμε άλλα :)

    Regular Stack Time 6484 - Generics Stack Time 6812

    Το δοκίμασα με διάφορους τύπους. Εκτός απο αριθμιτικά, το Generics implementation είναι πάντα λίγο πιο αργό απο το απλό. Ο antonch που έκανε το σεμινάριο μου εξήγησε μετά οτι είναι φυσικά πιο γρήγορο το generic implementation γιατί σώζει εσωτερικά στη μνήμη ένα Int32 κάθε φορά, ενώ το regular stack ένα object. Σε κάθε άλλη περίπτωση, οι χρόνοι τους θα είναι παρόμοιοι με το generic παντα λίγο πιο αργό ...  


    Angel
    O:]
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems