Pokazywanie postów oznaczonych etykietą optymalizacja. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą optymalizacja. Pokaż wszystkie posty

niedziela, 8 marca 2015

[c#] Stopwatch - jak zmierzyć czas wykonywania kodu

Przestawiam klasę stopwatch do mierzenia czasu wykonywania kodu w c#

Czasy kiedy do mierzenia czasu wykonywania kodu używaliśmy:

DateTime now = DateTime.Now;
// KOD
Console.WriteList(DateTime.Now - now);
bezpowrotnie już minęły. W .NET 4.5 otrzymaliśmy bardzo prostą, gotową do użycia klasę Stopwatch. Dostarcza ona większej precyzji niż zbada z DateTime.Now

Najprostsze użycie tego toola wygląda tak:

Stopwatch sw = Stopwatch.StartNew(); // od razu zegar zostaje wystartowany
// KOD
sw.Stop(); // zatrzymujemy zegar
Console.WriteList("Czas wykonywania: {0}ms", sw.ElapsedMilliseconds);

czego chcieć więcej od tak małej i użytecznej klasy? Oczywiście możemy utworzyć instancje Stopwatch i wykorzystać go kilka razy używając metod Reset() - do zresetowania czasu, Restart() - do resetu oraz natychmiastowego puszczenia ponownie zegara.

Stopwatch sw = new Stopwatch();
sw.Start(); // start zegara
// KOD
sw.Stop(); // zatrzymujemy
Console.WriteLine(sw.ElapsedMilliseconds);

sw.Reset(); // zerujemy zegar
sw.Start(); // start zegara
// KOD
sw.Stop(); // zatrzymujemy
Console.WriteLine(sw.ElapsedMilliseconds);

sw.Restart(); // zerujemy zegar i od razu go puszczamy w ruch
// KOD
sw.Stop(); // zatrzymujemy
Console.WriteLine(sw.ElapsedMilliseconds);

Ta klasa się można domyśleć bardzo dobrze przydaje w badaniu wydajności kodu i wszelakich optymalizacjach.

środa, 4 marca 2015

Optymalizacja kodu w ruby

Parę ciekawostek odnośnie optymalizacji kodu w ruby

Czasem warto poznać różne "sztuczki" aby przyspieszyć aplikację napisaną w ruby. Przejdźmy od razu do rzeczy:

1. Zamiast używać begin..rescue podczas zabezpieczenia się przed NoMethodError można użyć Object#respond_to?(:metoda)
Przyspieszenie: 10x

2) Jeśli mamy posortowaną tablicę to użycie Array#bsearch zamiast popularnego Array#find przyspieszy niemalże "diabolicznie" ;) Array#find działa w taki sposób, że sprawdza warunek na każdym elemencie, natomiast Array#bsearch (przeszukiwanie binarne) znajduje środek a następnie sprawdza warunek czy wartość jest większa, mniejsza, równa wtedy podejmuje decyzję czy szukać środka w pierwszej części czy w drugiej. Szczegółowe wytłumaczenie można zobaczyć sobie tutaj: http://en.wikipedia.org/wiki/Binary_search_algorithm

3) Zamiast Hash#merge można zastosować Hash#merge! Działa to szybciej dlatego, że merge! wykona operację bez zbędnego kopiowania siebie samego.
Przyspieszenie: 25x

4) Losowa wartość z tablicy. Array#shufle.first - działa w taki sposób, że najpierw alokuje miejsce w pamięci dla kopii tablicy a następnie kopiuje losowo wartości. Jak widać musi sporo pracy wykonać. Zamiast "szufli", można skorzystać z Array#sample
Przyspieszenie: 17x

Ruby ma więcej takich rzeczy, postaram się wyciągnąć podobne, które rozsiane są po różnych konferencjach.

opracowane na podst. https://www.omniref.com/github/JuanitoFatas/fast-ruby/HEAD/files/Rakefile

niedziela, 1 marca 2015

Jak przyspieszyć inicjalizacje obiektów aby szybciej można było utworzyć listy, słownik danych

Jeśli potrzebujecie przechować jakieś dane np. w cache to najpierw je trzeba pobrać i gdzieś umieścić. Przedstawię mały trick. Większość programistów c# (dane wzięte z kosmosu, ale się domyślam, że tak jest) przechwycone dane zapisuje jako klasę by następnie przechowywać je w jakiejś strukturze danych (lista, słownik, tablica). To w większości przypadków jest OK, lecz wyobraźmy sobie, że mamy do zainicjowania kolekcję złożoną z baaaaaaardzo wielu elementów a zależy nam bardzo na szybkości inicjalizacji. Więc zamiast robić:

Enumerable.Range(0, 10000000).ToDictionary(k => k, v => new X(123));

gdzie X jest klasą

wystarczy utworzyć strukturę
        struct Y
        {
            public int Val;
            public Y(int val) {
                Val = val;
            }
        }


 Enumerable.Range(0, 10000000).ToDictionary(k => k, v => new Y(123));

U mnie wzrost wydajnościowy jest niemal 3-4 krotny.

ps oczywiście tytuł jest trochę mylący bowiem struktura (Struct) nie jest obiektem!

Podstawy optymalizacji w C#. Odszukanie elementu z dużego zbioru danych.

Słowniki danych (dictionaries), są używane gdy potrzebujemy bardzo szybkiego dostępu do danych w pamięci. Standardowo można użyć listy:

List users = new List();

....

list.Single(k => k.UserId == 1);

problem tutaj jest taki, że przepatrujemy cały zbiór do momentu aż natrafimy na element spełniający warunek. Jeśli UserId znajdowałby się na samym końcu to zostanie przepatrzona cała lista. Wyobraźmy sobie, ze potrzebujemy co chwilę wyciągać użytkowników po danym ID. Trochę to wypada kiepsko.

Dobrym rozwiązaniem jest skorzystanie np. ze słownika danych:

Dictionary users = new Dictionary();

users[201]; // zwraca użytkownika z UserId 201

działa to na prawdę bardzo szybko.