niedziela, 8 marca 2015

[c#] Entity Framework - Wypisanie wygenerowanych zapytań na ekran

Nie raz podczas pracy z Entity Framework chcemy podejrzeć jak wyglądają wygenerowane zapytania SQL. Może coś nie działa jak tego byśmy chcieli, lub szukamy sposobu optymalizacji zapytania. Na szczęście Entity Framework został bardzo dobrze przemyślany i takie podglądnięcie wygenerowanego/surowego sqla nie stanowi żadnego problemu:

using(var content = new DatabaseContext())

{
  context.Database.Log = Console.Write;
  var user = context.Users.First(); // na ekran trafi wygenerowany select wyciągający pierwszego usera z tablicy
}
 
prawda, że proste? A co jeśli chcielibyśmy zapisywać sobie te zapytania do pliku, aby np. móc przewkleić je do jakiegoś managera SQL w celu analizy? Chłopaki od Entity Frameworka, też o tym pomyśleli:

1) Najpierw trzeba utworzyć swojego Loggera (nic trudnego)

public class Logger
{
  public void Log(string message)
  {
    // w tym miejscu można użyć dowolnej biblioteki do logowania np. log4net, nlog etc
    File.AppendAllText("log.txt", message + Environment.NewLine); 
  }
}

2) Następnie podczepiamy loggera do contextu:

var logger = new Logger();
context.Database.Log = sql => logger.Log(sql);

Gotowe, możemy teraz się cieszyć zapisanym sqlem w logu.

[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.

[c#] Zrozumieć LINQ część 1: Podstawy "czystego" LINQ

Dziś przedstawie podstawy LINQ w .NETcie. Nie ma potrzeby pisać dokładnie co to jest, jak działa, bo na dowolnej stronie poświęconej LINQ można to wyczytać. Bardzo istotną rzeczą jest zrozumienie o co w tym wszystkim chodzi.

Cała zabawa z LINQ polega na wywoływaniu metod/funkcji, aż do osiągnięcia interesuącego nas rezultatu (oczywiście nie jest to całkowita prawda, lecz w tym pierwszym poście wszystko upraszczamy). Schemat działania wygląda mniej więcej tak:

Dane wpadają do metody, która coś z nim robi, następnie wynik przekazuje innej metodzie itd. aż do zakończenia. Można to sobie wyobrazić, iż to działa na zasadzie sekwencji: A -> B -> C -> Wynik

Zobaczmy prosty przykład. Chcemy wygenerować 1000 elementową kolekcję. Bez użycia LINQ zrobilibyśmy zwykłą pętle for z granicą < 1000. To za dużo pisania, wystarczy to zrobić w tak:
Enumerable.Range(0, 1000)

Tak na marginesie w języku ruby (który też zawiera elementy programowania funkcyjnego) bardzo mi się podoba zapis:
5.times {|i| p i}

Znaczy, że to jest w klamrach (bloku) wykona się 5 razy. W csharpie ten sam efekt możemy właśnie osiągnąć przez:
Enumerable.Range(0, 10000000).ToList().ForEach(Console.WriteLine)

Jak widać ruby w tym przypadku (i nie tylko) jest bardzo zwięzły, ale nie o tym języku miało być dzisiaj.. ale wracając do LINQ. Microsoft dał .NETowcom, bardzo potężne i szybkie narzędzie to operacji na wszelakiego rodzaju kolekcjach.

1) Aby wyciągnąć maksymalny element w tablicy wystarczy użyć:
listaIntow.Max(); // jeśli lista zawiera same inty
listaUserow.Max(user => user.Id); // tablica zawiera użytkowników, Max zwróci usera z największym ID

2) Suma:
listaIntow.Sum();
listaUserow.Max(user => user.Id); // suma id

3) Ilość
listaIntow.Count();
listaUserow.Count();

4) Średnia
listaIntow.Average();
listaUserow.Average(user => user.Id); // średnia ze wszystkich wartości user ID

5) Minimum
identycznie jak Max

6) Sortowanie
listaIntow.OrderBy(); // OrderByDescending
listaUserow.OrderBy(user => user.Id); // OrderByDescending(user => user.Id);

LINQ daje nam na prawdę ogromne możliwości, nie wspominając już o PLINQ (paraller linq), ale to temat na osobny post.

Wyobraźmy sobie, że chcemy wygenerować liczby parzyste pomnożone przez 2, a następnie wynik chcemy wypisać w konsoli. Bez LINQ musielibyśmy się trochę upisać aby coś takiego osiągnąć.

Enumerable.Rang(0, 1000).Where(x=> x % 2 == 0).Select(x => x * 2).ToList().ForEach(Console.Write);

Mam nadzieję, że zachęciłem osoby, które jeszcze nie znają świata LINQ do zapoznania się z nim bliżej, w następnym poście spróbuję pokazać praktyczne przykłady użycia.

czwartek, 5 marca 2015

[c# / csharp] Jak zainicjować listę w jednej linijce (inline) w "csharpie"

Inicjowanie listy w inline'owo

C# umożliwia nam zainicjowanie listy w jednej linijce (inline).
Już nie musimy pisać:

List list = new List();
list.Add("a");
list.Add("b");
list.Add("c");

ani robić lekkich haków z array
new List(new string[] { "a", "b", "c"});

wystarczy po prostu napisać:
new List { "a", "b", "c" };

natomiast lista z jakaś naszą klasą po prostu będzie wyglądać tak:

new List {

new User { Id = 1, Name = "UserName1" },

new User { Id = 2, Name = "UserName2"}

});

przyjemnie

ś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.