wiatrace.log – SSD killer

Zauważyłem przycinanie się Windowsa i duży strumień zapisywanych informacji. Winowajcą okazał się jakiś driver od drukarki EPSON, którego poskromienie  nie przyniosło rezultatów.

Skorzystałem więc z poniższego skryptu aby przekierować nichciane śmieci do /dev/null

Zatrzymanie serwisu musi się odbyć z poziomu administratora

Być jak Haskell

Historia kołem się toczy, więc po raz kolejny zabieram się do programowania bardziej funkcyjnego. Obejrzałem film  Refactoring to Functional. a ponieważ jego autor Hadi Hariri pracuje obecnie dla JetBrains, to uznałem, że temat trzeba potraktować poważnie.

W C# mamy dobrodziejstwa Linq, jednakże istnieje, że jego uniwersalność jest okupiona dużym narzutem. Unikam zatem Linq w miejscach, gdzie może on być źródłem kłopotów wydajnościowych. Ponieważ nic nie może przebić piękna i prostoty pętli FOR, stosowałem ją tam gdzie podejrzewałem, że Linq może nie dać rady. Stąd też poniższy, przykładowy kod.

W pętli obliczana jest sumaryczna długość linii łamanej określonej przez tablicę punktów Points . Może nie ruszyłbym tego kodu, gdyby nie druga inspiracja, film Michała Bartyzela,  Jak zniszczyć swój kod — podstawy lingwistyki dla programistów.

Postanowiłem wykorzystać zalety programowania funkcyjnego ale nie w oparciu Linq, zwłaszcza że obliczenia bazują nie tyle na kolejnych elementach kolekcji co na parach sąsiadujących elementów. Zapytanie Linq zamieniające sekwencję elemntów na sekwencję par mogłoby być karkołomne i zaciemnić kod zamiast go uprościć, t.j.

Powyższy kod zainspirowany http://stackoverflow.com/questions/1624341/getting-pair-set-using-linq.

Kod własności Length zamieniłem na taki.

z użyciem ExtensionMethod

Wadą tego rozwiązania jest to, że nie sprawdzam czy w trakcie działania metody FoldPairs lista źródłowa się nie zmieniła. Klasa List<T> posiada prywatne pole _version, które jest skrupulatnie wykorzystywane przez iterator. Pole to jednakże nie jest – poza mechanizmami refleksji – możliwe do uzyskania. Istnieje jednak bardzo wiele scenariuszy, w których rozwiązanie takie jest wystarczające. Zawsze można dopisać alternatywną wersję metody, która wykorzystując enumerator będzie czuwała nad niezmiennością listy.

Zaleta jest taka, że czytelność kodu jednak się poprawiła. W środku mam swoją pętlę for, więc nie korzystam z iteratorów, enumeratorów i innych elementów.

Węsząc za pętlami for

Przy okazji starałem się w prosty sposób przeszukać kod źródłowy w poszukiwaniu pętli for zaczynających się od zera. Prosty (choć nie wolny od wad) regexp, którego używłem wygląda tak:

Odnośniki

Dependency Injection według Microsoftu

Kto się boi zastrzyków?

Na wskazanej poniżej stronie można dokładnie przeczytać o co chodzi z całym Dependency Injenction. Mówiąc w skrócie chodzi o to, aby pisząc program dostarczać małych kawałków kodu, które są łatwiejsze w tworzeniu, testowaniu i serwisowaniu zamiast monolitycznych gigantów przerośniętych gęstwiną splątanych zależności.

Relacje pomiędzy komponentami powinny być realizowane przy użyciu wzorca Strategy, co pozwala w praktyce zachować niezależność komponentu od implementacji innego komponentu zastępując ją zależnością od interfejsu czyli abstrakcyjnej definicji.

Dlaczego to takie ważne? W praktyce tworząc większy moduł realizujący pewną funkcjonalność rozwiązujemy wiele aspektów problemu, np. obliczenia matematyczne, eksport i import danych do różnych formatów wymiany, zapis do bazy danych oraz plików itp. Dla przykładu moduł może wykonywać obliczenia belki stalowej, pobierać dane norm technicznych przez webserwisy i dodatkowo wykonywać rysunki techniczne zapisywane w formacie AutoCAD. Moduł będzie miał w związku z tym zależności do bibliotek związanych z komunikacją sieciową, tworzeniem plików w formacie DXF/DWG, bibliotek matematycznych ułatwiających obliczenia macierzowe itp. Jeśli zatem inny moduł programu, np. realizujący zamówienia wymaga jakiejś usługi realizowanej przez moduł obliczeń to przy prostej referencji do tego modułu jednocześnie uzależnia się od bibliotek np. związanych z generowaniem rysunków AutoCAD co jest w sposób oczywisty szkodliwe.

Alternatywą dla tego rozwiązania jest zdefiniowanie modułu INTERFEJSY, gdzie poprzez definicję interfejsu (np. IBeamCalculator) pokazane zostanie czego oczekujemy od usługi obliczania a nie jak ona jest zrealizowana, co z punktu widzenia usługobiorcy jest zwykle wystarczające. Obydwa wyżej wskazane moduły nie muszą i nie powinny wiedzieć o swoim istnieniu o ile posiadają referencję do tego samego zbioru interfejsów, które gwarantują poprawność ich wzajemnej komunikacji.

Powstaje jednak pytanie w jaki sposób moduł B skorzysta z usługi z modułu A skoro nie są pomiędzy sobą powiązane. I tutaj wkracza kontener IoC oraz Dependency Injection. Kontener IoC jest dostarczycielem implementacji dla usług. Zatem moduł B prosi IoC „daj mi implementację dla usługi IBeamCalculator” zamiast wprost znać położenie konkretnej klasy, która realizuje usługę obliczeń.

Czas napisać kod

Wstęp okazał się dłuższy niż miałem na to ochotę więc czas na kodowanie. Do eksperymentu użyjemy Microsoft.Extensions.DependencyInjection, który jest dostępny w postaci pakietu Nuget.

W wyniku tego zabiegu dostaniemy właściwą referencję oraz zależność do 33 innych pakietów. Grubo na samym początku. Dla porównania TinyIoC jest dostarczany jako pojedynczy plik cs.

Korzystanie z IoC dzieli się na 2 etapy

  1. Definiowanie zależności
  2. Rozwiązywanie zależności

Definiowanie zależności

Na tym etapie używamy obiektu implementującego IServiceCollection  do rejestrowania usług. Rejestracja pojedynczej usługi może odbywać się na wiele sposobów w zależności od wielu czynników, np. czasu życia obiektu realizującego usługę.

Zdefiniujmy 2 interfejsy

oraz dwie stosowne implementacje

W przykładzie uzależniamy implementację MyCircleService  od interfejsu  ILogService . Zatem MyCircleService  i ConsoleLogService  nie muszą wiedzieć o swoim istnieniu o ile współdzielą tę samą definicję interfejsu ILogService .

Teraz rejestracja

Kilka uwag:

  • Tworzymy własną kolekcję serwisów, ale korzystając z rozmaitej maści frameworków możemy zauważyć, iż posiadają one własne kolekcje inicjowane w specyficzny dla nich sposób. Dla przykładu ASP.NET Core MVC używa do tego celu metody ConfigureServices  z klasy Startup .
  • Usługi obliczeń i logowania są zarejestrowane jako singletony. Obydwa są bezstanowe, więc nie ma potrzeby aby tworzyć więcej niż jedną instancję każdego z nich.
  • Klasa MyCircleService wymaga w konstruktorze dostarczenia instancji ILogService – to zadanie dla kontenera IoC, aby wstrzyknąć odpowiedni obiekt jako parametr konstruktora
  • Po zdefiniowaniu zależności wykonujemy metodę BuildServiceProvider, która dostarcza obiektu IServiceProvider

Wykorzystanie serwisu

Przykładem wykorzystania serwisu może być użycie ICircleService  do wykonania obliczeń.

Po uruchomieniu kodu na konsoli pojawi się poniższa treść:

Co się zdarzyło?

Otóż w momencie wywołania GetService  kontener IoC podjął się wykreowania obiektu MyCircleService . Zorientował się, iż wymaga to posiadania obiektu implementującego ILogService . W sposób dla nas niewidoczny wykonał GetService<ILogService>  i uzyskany tą drogą obiekt przekazał do konstruktora MyCircleService .

Czy warto korzystać z Dependency Injenction?

Odpowiedź jest jednoznacznie twierdząca. Oczywiście w zależności od implementacji kontenera IoC dostajemy pewien spadek wydajności aplikacji, jednakże w praktyce jest on niezauważalny. Zyskiem jest natomiast znacząca poprawa architektury aplikacji i zmniejszenie ilości relacji pomiędzy komponentami, klasami i modułami.

Osobnym aspektem jest wpływ zastosowania kontenera IoC na testowalność usług. Tutaj dzięki wstrzykiwaniu innych implementacji można realizować zaawansowane scenariusze testowe. Dla przykładu usługa pobierająca normalnie kursy walut z serwisu internetowego może – dla scenariusza testowego – zostać podmieniona przez usługę dostarczającą stałych wartości kursów walut z predefiniowanego zbioru danych testowych.

Czy warto korzystać z Microsoft.Extensions.DependencyInjection?

Moim zdaniem odpowiedź nie jest jednoznaczna, o czym świadczą argumenty

  • Tak bo:
    • Czasem nie ma wyjścia. Jeśli piszemy aplikację ASP.NET Core MVC to zwykle nie ma rozsądnych argumentów, żeby skorzystać z innego kontenera niż „jedynie słusznego”.
    • Używany jest w wielu frameworkach, jak wspomniany ASP.NET Core MVC lub Entity Framework Core. Wspólne mechanizmy IoC napewno są tutaj zaletą.
  • Nie bo:
    • Nie jest to demon prędkości. Osobiście preferuję TinyIoC i skłaniam się do poważnego przetestowania DryIoC
    • Nie obsługuje kontenerów potomnych, które w niektórych przypadkach pozwalają prosto rozwiązać bardziej zaawansowane zależności.

Odnośniki

Prosty API Controller

Kontynuuję zabawę z AspNetCore. W poprzednim artykule zrobiłem szkielet aplikacji, który udało się uruchomić.

Rozgrzewka

Czas na prosty kontroler API, który zwraca dane w postaci np. JSONa, które mogą zostać użyte np. w architekturze AJAX.

W katalogu Controllers  należy utworzyć nową klasę  SimpleApiController, która dziedziczy z  Controller. Do tej klasy dodajemy metodę Indeks zwracającą  IActionResult.

Po skompilowaniu i uruchomieniu można zaryzykować wpisanie do przeglądarki adresu http://localhost:5555/SimpleApi. Wynikiem powinno być coś w rodzaju

Czego nie widać w kodzie?

Kilka słów wyjaśnienia. Po pierwsze jakie jest powiązanie nazwy klasy, nazwy metody i URLa, który jest powiązany z wywoływaną metodą. Definicje tych zależności znajdują się w metodzie Configure klasy Startup. Definicja wygląda tak:

Domyślny szablon routowania czyli wyszukiwania klas i metod na podstawie adresu URL składa się z trzech elementów oddzielonych ukośnikami

  1. Nazwa kontrolera (jeśli zostanie pominięta to użyty będzie HomeController). Suffix „Controller” będzie dodany automatycznie stąd „SimpleApi” w przykładzie routuje na „SimpleApiController”
  2. Nazwa akcji (jeśli zostanie pominięta to będzie użyta akcja Index). W przykładzie powyżej wystąpił właśnie przypadek, gdzie Index został użyty jako domyślny.
  3. Nazwa parametru, który może być przekazany do metody.

Metoda z parametrem

Aby przetestować pkt 2 i 3 z powyżej opisanej reguły routowania możemy dopisać metodę

Test pierwszy to użycie adresu http://localhost:5555/SimpleApi/PowerOfPi/ . Została w nim wskazana metoda w dosłownym brzemieniu nazwy. Parametr został pominięty, więc zostanie przyjęta wartość domyślna. Dla int jest to 0. Wynik jaki otrzymamy to

Drugi test to użycie adresu http://localhost:5555/SimpleApi/PowerOfPi/3 . Tutaj jawnie podajemy wartość 3. Rezultat na wyjściu to :

Ważne

  1. Nazwa parametru musi być zgodna z nazwą użytą w szablonie a więc „id”. Przemianowanie nazwy argumentu metody spowoduje, że nie zostanie wstrzyknięta wartość rozpoznana w URLu
  2. Podanie wartości niezgodnej z oczekiwanym typem spowoduje zignorowanie wartości. Zatem wywołanie http://localhost:5555/SimpleApi/PowerOfPi/3.4  spowoduje, że metoda zostanie wywołana z parametrem 0. Oczywiście można zmienić typ danych z int na double. Wtedy będą akceptowane wartości z separatorem dziesiętnym w postaci kropki

AspNetCore, pierwsze starcie

Postanowiłem zabrać się w końcu za przetestowanie AspNet Core. Po pierwsze stworzyłem nowy projekt

aspnetcore-choose-project-type

Dlaczego .NET Framework? Otóż .NET Core uważam w tej chwili za mocno niedojrzały. Miałem pod górę w kilku projektach więc pomyślałem „jeszcze nie tym razem”.

Kolejny krok to wybór szablonu. Wybrałem zwykłą „Web application”

aspnetcore-choose-project-template

Po kilkudziesięciu sekundach projekt się stworzył, ściągnęły się pakiety Nuget i można było rozpocząć zabawę. Na rozgrzewkę odpalenie pustego projektu. Za pierwszym razem dostałem „Unable to Start Debugging”. Restart IISa oraz restart VisualStudio rozwiązał szybko ten problem, ale i tak żółta kartka za robienie pod górkę.

Jak uruchomić

Domyślnie aplikacja może być uruchomiona z użyciem IIS lub jako samodzielnie. Profile są zdefiniowane w pliku launchSettings.json. Pierwsza z opcji wymaga działania serwera IIS. W przypdaku drugim korzystamy z wbudowanego serwera Kestrel. Przy dalszych testach będę się posługiwał drugim sposobem uruchamiania.

aspnetcore-change-url-3

Zmiana URL

 

Na początek można wymusić na którym porcie będzie pracować aplikacja. Ściślej rzecz biorąc można zdefiniować konkretny, pełny URL. W tym przypadku jednak jest to aplikacja testowa, która działa jedynie na localhost. W tym celu trzeba dopisać następującą linijkę w pliku Program.cs

aspnetcore-change-url-1

Ponadto trzeba zmodyfikować plik launchSettings.json i wskazać nowy URL, który będzie używany do uruchomienia przeglądarki:

aspnetcore-change-url-2

Po pierwsze trzeba znaleźć wpis związany z uruchomieniem aplikacji w trybie samodzielnym. Domyślnie nazwa klucza jest taka sama jak nazwa projektu, czyli w tym przypadku AspNetCoreTest. Po udanym odszukaniu trzeba zaktualizować lauchUrl.

Przy uruchomieniu aplikacji z użyciem Kestrela pojawia się okienko konsolowe, w którym można śledzić logi działania aplikacji.

aspnetcore-change-url-4

 

W kolejnym wpisie zajmę się prostym kontrolerem API.

Pożeracze pamięci

Wstęp

Zauważyłem ostatnio dużą ilość pamięci zużywanej przez proces ID=4, t.j. System

pozeracze-pamieci-menadzer-zadan

Bywa, że ilość pamięci sięga granicy grubo ponad gigabajt

Jak znaleźć łakomczucha?

Zabrałem się do poszukiwania winowajcy. Na początek pobrałem pakiet Windows Driver Kit (WDK), który zawiera narzędzie poolmon.

Po uruchomieniu i kliknięciu „B” (sortowanie po ilości bajtów) ukazał się pełen obraz:

pozeracze-pamieci-poolmon

Lista znanych (ale nie wszystkich) tagów jest tutaj:

Kilka wpisów:

Brak w tym spisie np. CM31 oraz AvN.

CM31

Jak wygooglowałem, CM31 jest związany z „Configuration Manager (registry)”.

MmSt

Jak wyczytałem w internecie:

Most Common Root Causes for high MmSt pool usage

  • The Memory Manager cannot trim paged pool memory quickly enough before allocations start failing
  • Heavy file I/O because too many files or large files are opened simultaneously
  • Outlook .PST/Lotus Notes .NSF files being stored on the server and opened over the network
  • VSS (Volume Shadow Copy) snapshots aren’t dismounting
  • Large $MFT due to fragmentation or many files on the volume

porządkowanie $MFT

użyłem

ale nie dało to szczególnie dużych efektów.

Wnioski?

Na chwilę obecną szukam sposobu wykrycia i usunięcia.

Linki

Magiczne async

W sieci jest wiele materiałów na temat konstrukcji async-away. Postanowiłem zbadać kilka ciekawostek.

Użycie async bez away

Rozważmy kod

Metoda „Pierwsza” jest napisana zgodnie ze sztuką. Budowa metody „Druga” budzi sprzeciw kompilatora:

Użyłem strony http://tryroslyn.azurewebsites.net aby obnażyć prawdę. Oto prawdziwy „kod pod spodem” (fragment)

Zabawa w „znajdź różnice” skutkuje tylko tym, że różnią się nazwy metod. Różnica natomiast jest w konstrukcji maszyny stanu dla każdej z metod. W pierwszym przypadku to:

W drugim znacznie krócej:

 

Azure Quota Exceeded

Zaliczyłem „Quota Exceeded” na bazie MsSql w Azure. Ponieważ była to aplikacja testowa, to usunąłem wszystkie dane, z tabel. Zrobiłem rebuild indeksów i oczekiwałem odblokowania dostępu. Tymczasem ku mojemu zdziwieniu:

Azure Quota Exceeded 2

Żadne 'refresh’ nie pomaga. Najciekawsze jest to, że na jednej stronie Azure podaje sprzeczne informacje.

Azure Quota Exceeded 1

Roslyn-rozpoznawanie typów wyrażeń

Pochylmy się nad następującym kodem

Łatwo odgadnąć, że zmienna x jest typu int, natomiast podczas przypisania wartości x do zmiennej y następuje niejawne rzutowanie do typu decimal. Jak robi to Roslyn? Napiszmy testowy kod

Na konsoli otrzymamy wynik:

Co jednak gdybyśmy chcieli dowiedzieć się czegoś więcej o rzutowaniu typów. Rozważmy kod:

Klasa XNumber posiada operator niejawnego rzutowania na tym int. Tym samym można wartość typu XNumber przypisać zarówno do zmiennej typu int, jak i do zmiennej typu decimal. W tym drugim przypadku nastąpią dwa rzutowania: XNumber => int => decimal.

Rozbudujmy nieco kod Roslyn aby pobrać więcej informacji o dokonywanych konwersjach. Poniższy kod należy wstawić ZAMIAST poprzedniej wersji „Console.WriteLine”

Parsowanie nowego kody da wynik:

Wyrażenie przypisania wartości do zmiennej y zawiera 2 ukryte konwersje: ImplicitUserDefined oraz ImplicitNumeric.

Dodajmy kolejne linie do metody analizującej kod aby uzyskać dalsze informacjie

i wynik

W przypadku kiedy konwersja jest typu ImplicitUserDefined to własność MethodSymbol zawiera symbol związany z użytym konwerterem, tutaj: System.Int32 XNumber.op_Implicit(XNumber src).

Uwagi końcowe

Powyższych strategii użyłem w projekcie konwertera kodu C# do PHP. Użycie operatora op_Implicit jest opisane w artykule
Operator overloading simulation for PHP.

Raspberry PI i Arduino – bezprzewodowo

Po udanym połączeniu dwóch jednostek Arduino poprzez moduł nRF24L01+ narobiłem sobie apetytu na połączenie bezprzewodowe Arduino z Raspberrym i uczynienie z RPI koncentratora zbierającego rozmaite dane.

Krok po kroku podążałem za artykułem Communicating from low power Arduino to Raspberry Pi via NRF24L01 . Po drodze potknąłem się kilka razy i o tym jest ten post.

Strona Raspberry

Aktualizacja firmware…

…przebiegła poprawnie. Niestety po restarcie nie były widoczne urządzenia /dev/spidev0.0 oraz /dev/spidev0.0 . W związku z tym dodałem do /etc/modules 2 linijki:

i po kolejnym restarcie było już tak jak być powinno.

Drutowanie

Tutaj nie natrafiłem na żadną pułapkę. Użyłem 7 kolorowych przewodów i całość prezentuje się tak:

nrf24l01 połączony z raspberry pi

Instalacja biblioteki i uruchomienie przykładowego programu

Aby uruchomić przykład należy zmodyfikować plik rpi-hub.cpp. Po pierwsze – czego nie znalazłem w przewodniku – należy prawidłowo skonfigurować linie CE i CSN. Zgodnie ze schematem połączeń powinno to wyglądać tak:

Reszta zmian w pliku to modyfikacja metody main a nie setup jak przewodniku. Osobiście wybrałem kanał 2 zamiast 70.

Po skompilowaniu i uruchomieniu pojawiły się jakieś sensowne wartości, więc ogłaszam sukces tego etapu.

Strona Arduino

Biblioteka RF24

W sieci znalazłem wiele odmian biblioteki do komunikacji. Początkowo używałem biblioteki Mirf wspomnianej na Arduino Playground, ale we wspomnianym powyżej przewodniku autor używa RF24.

Biblioteka używana po stronie RPi okazała się nieco inna od tej, której potrzebowałem. Jej autor, Stanley Seow opublikował także wersję dla arduino jednakże jest to zmieniona wersja Mirf. W końcu odnalazłem https://github.com/gcopeland/RF24 i było to to, czego mi potrzeba…. Prawie. W testach okazało się, że znalazłem drobne nieścisłości. Oto moja wersja biblioteki: https://github.com/isukces/RF24 .

Instalacja: Po pobraniu źródeł, cały folder RF24 należy przenieść do katalogu bibliotek Arduino, np. C:\Program Files (x86)\Arduino\libraries.

 Przykładowy program

Przykładowy szkic, którego kod zamieszczam poniżej ruszył praktycznie od pierwszej kompilacji.