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

poniedziałek, 2 lutego 2015

ChamberConf wrażenia jako organizator, prelegent i uczestnik w jednym

W końcu się zebrałem, aby napisać relację z ChamberConf. Była to pierwsza konferencja organizowana przez Wrocławski JUG. Sam również po raz pierwszy miałem okazję uczestniczyć w organizacji takiego wydarzenia. Ostatnie 2 tygodnie przed wydarzeniem do łatwych nie należały...

Z założenia konferencja miała być bez sponsorów, czyli bez wszelakich konkursów, stoisk, prezentów itp. Początkowo konferencja była planowana na 65 osób, ale ostatecznie wyszło 80. Miejsce było niezwykłe, bo to były psychiatryk (gdzieś niedaleko jest jeszcze działający oddział), a jednocześnie bardzo ładny zamek, z dala od wielkich miast i cywilizacji. Konferencja trwała dwa dni, ale sporo osób przyjechało już w piątek wieczorem, więc nieoficjalnie zaczęło się trochę wcześniej.

Na pierwszej prezentacji w sobotę Tomka Borka i Jacka Jagieły pt. To nie zawsze wina aplikacji, robiłem za pilot do przełączania slajdów, ponieważ żaden wskaźnik nie chciał akurat współpracować z Ubuntu. Slajdy można sobie przejrzeć na prezi.com, jak i na slideshare. Z prezentacji wynikało, że należy pamiętać o monitoringu aplikacji i infrastruktury, bo często problemy z wydajnością nie leżą w naszym kodzie. Fajne było zadawanie pytań na koniec przez prelegentów do publiczności, czyli w odwrotnym kierunku niż zwykle.

Następnie Adam Warski opowiadał o Reactive Manifesto z użyciem Akki. Było trochę wstępu teoretycznego i sporo kodowania na żywo. Występ się trochę przedłużył, ale zależało nam na tym, aby konferencja nie miała sztywnych ram.

Następnie Konrad Malawski opowiadał o algorytmach głosowania w sieci. Było m.in. o Paxosie (którego prawie nikt nie rozumie), jak i jego uproszczonych wersjach. Początkowo bałem się, że to będzie prezentacja czysto akademicka, ale koniec końców okazało się, że bodajże raft consesus jest gdzieś tam w Akkce zaimplementowany.

Następnie był obiad i ostania prezentacja pierwszego dnia, Michała Bartyzela pt. Z czym mierzą się zespoły? Michał opowiadał sporo swoich doświadczeń i trudności jakie spotykamy w naszej pracy, oraz jak zmieniał się jego światopogląd na przestrzeni lat.

Następnie było unconference, czyli coś co nie wiedzieliśmy czy się uda czy nie. Ale wychodzi na to że się udało. Było sporo pytań do Konrada, rozmów o pracy zdalnej, CQRSie i inne, a to wszystko w luźnej atmosferze. Później całość się przeniosła na kolację i dalsze rozmowy z ludźmi zwłaszcza nowopoznanymi.

Drugi dzień rozpocząłem od zapowiadanego morsowania. Niestety nikt chętny się nie zgłosił, chociaż o 2:00 w nocy ktoś się podobno deklarował. Może za mało przypominałem uczestnikom o tym temacie...


Drugiego dnia udałem się na Archi-Katę do Tomka Borko. Warsztat był na kartkach bez użycia komputerów, ale zmuszał do sporego myślenia, a później dyskusji i oceniania prac innych. Bardzo fajny warsztat.

Równolegle do warsztatów była ścieżka z prezentacjami. Tam frekwencja była mniejsza, ale podobno bardzo sprzyjało to żywej dyskusji.

Po przerwie obiadowej sam prowadziłem warsztaty. Jak się okazało, był to jedyny temat związany z Java, gdyż inne były o Scali, architekturze lub miękkie. Chyba trzeba będzie zmienić Java User Group na JVM User Group. Warsztat był rozszerzoną powtórką z Warsjawy. Sam na początku warsztatu się czegoś nowego nauczyłem, a mianowicie poznałem: Presentation Assistant, dzięki któremu można było wyświetlać wciskane skróty na ekranie. Kiedyś jak szukałem takiego narzędzie pod windę, to każde okazywało się jakieś kiepskie. A wspomniany plugin pokazywał skróty w wersji na Winde i Mac'a.

Implementowaliśmy ten sam problem co na Warsjawie, czyli StringCalculator. I jak doszliśmy do wydarzeń regularnych, to znów zaczeły się schody. Okazje się, że jak "ma się jakiś problem, który rozwiązujemy za pomocą regexpa, to de facto rozwiązujemy dwa problemy". Jakoś w końcu udało się wybrnąć z tego, ale nie było łatwo. Sam kilka dni przed konferencją zaimplementowałem problem, rozwiązanie (pewnie nieidealne) dostępne na githubie: mstachniuk/StringCalculatorKata. A slajdy poniżej:



Szkoda tylko, że nie wszyscy uczestnicy dotrwali do końca, ale wiadomo - niedziela i trzeba było wrócić z tego końca świata do domu. Mój warsztat trochę się przedłużył, ale to ze względu na masę pytań. Na koniec było czuć zmęczenie, ale i zadowolenie.

Podsumowując konferencję wypadła bardzo dobrze. Pierwszy dzień był mocny i miał służyć owocnym rozmowom podczas unconference. Ten cel został osiągnięty. Drugi dzień wypadł już trochę słabiej, więc pewnie można coś w nim poprawić. Można to ewentualnie tłumaczyć znakomitym pierwszym dniem. Mam nadzieję do zobaczenia za rok!

sobota, 14 grudnia 2013

I znów Global Day Of Code Retreat

Kolejny rok mija i kolejny Global Day of Code Retreat już za nami. W tym roku planowałem początkowo uczestniczyć w tym evencie w Wolfsburgu, ale ostatecznie wybrałem Berlin, aby się trochę zorientować, jak wygląda tamtejsza sytuacja projektowa i mieszkaniowa. A CR to zawsze dobra okazja do tego. To już kolejny raz (6ty, jeśli nie licząc jakiś mniejszych, wewnętrznych inicjatyw), kiedy biorę udział w tego typie wydarzeniu, więc widzę jak się ono zmienia w czasie. Rok temu prawie 200 miast na całym świecie organizowało CR, a w tym było 165 lokalizacji. Tendencja więc spadkowa.

Jako że Berlin uchodzi za bardzo Europejskie miasto(o czym wspominałem już kiedyś w poprzedniej relacji), spotkanie było prowadzone po angielsku. Jednak w międzyczasie można było usłyszeć sporo języka niemieckiego, jaki i polskiego:) Zaczęliśmy więc od sortowania uczestników bąbelkowo, aby zorientować się kto jest mocny w TDD, pair programingu, a kto jest kompletnie świeży. No i w ten sposób najlepsi zasiedli do wspólnego stanowiska pracy z kompletnymi świeżakami. Nie ma to jak nauczanie innych:)

W pierwszej sesji dostałem więc niemieckiego studenta, który w javie pisze od święta, studiuje coś tam powiązane z medycyną, a na co dzień klepie w php. Używa do tego Vim’a. Jest on do niego tak przyzwyczajony, że korzysta z ichniejszych skrótów klawiszowych bezpośrednio w Eclipsie. Byłem pod wrażeniem, choć wątpię, aby była to optymalna droga do wykorzystania w pełni możliwości Eclipse’a.

Drugą sesję pokodowałem z przyjacielem Szymonem, z którym wspólnie przyjechałem do Berlina. Pobawiliśmy się trochę Scalą, ale nie szło nam jakoś najlepiej. Na pewno jeszcze sporo czasu trzeba zainwestować w poznawanie tego języka, aby móc z niego swobodnie korzystać. Niestety kiepska pogoda w ostatnim czasie, brak śniegu i gorączka przedświąteczna, nie jest najlepszym czasem do nauki nowych rzeczy. Dlatego kurs na Courserze sobie troszkę odpuściłem:(

Trzecią sesję miałem sposobność spędzić z pewnym Syryjczykiem, który na co dzień jest adminem, ale chciałby robić jakieś przyjemniejsze rzeczy. Ta sesja była dla mnie bardzo wymagająca pod względem komunikacji, ze względu na mój nienajlepszy angielski, ciężki w zrozumieniu angielski partnera i jego trochę słabą wiedzę w zakresie Javy. Myślę, że ziomek się sporo ode mnie nauczył.

Po trzeciej sesji była mała retrospekcja. W grupach 3 osobowych, mieliśmy napisać na kartkach, co się nauczyliśmy i co chcielibyśmy się nauczyć. Kartki przykleiliśmy na szybę i chwilę o tym dyskutowaliśmy.

Później była przerwa obiadowa. Były kanapki, a nie porządny ciepły, pyszny obiad jak to jest w formule tego wydarzenia zapisane. No ale trudno, nie to jest przecież najważniejsze.

Na 4tej sesji znów próbowałem pisać w Scali z innym nowopoznanym kolegą z Wrocławia. Tutaj trochę ciężko było nam dojść do porozumienia, gdyż zmierzaliśmy w innych kierunkach: ja kładłem nacisk na TDD, a kolega na implementację i lukier składniowy, jak to można by lepiej i ładnie zrobić w Scali.

Po czwartej sesji musieliśmy jednak opuścić warsztaty. Podziękowania dla globalnych i kontynentalnych sponsorów wydarzenia, a także dla sponsora w Berlinie: ImmobilienScout24, gdzie odbywał się event. Podziękowania również dla Martina Klose (@martinklose), który jak zwykle stanął na wysokości zadania i dobrze poprowadził kolejny raz to wydarzenie.

A co się zmienia, jeśli chodzi o Code Retreat? W Berlińskiej edycji zastosowano fajny pomysł przy rejestracji. Należało zapłacić 15 Euro, które było później zwracane, gdy uczestnik się pojawił na spotkaniu. Motywowało to ludzi do przychodzenia, gdy już byli zapisani, a gdyby naprawdę coś komuś nagłego wypadło, to strata 15 E jest do przełknięcia. Uważam to za super pomysł.

Ponadto zauważyłem, że osoby bardziej doświadczone w TDD i w formule Code Retreat już nie tak licznie w nim uczestniczą. Może to wynika z braku chęci nauczania innych, lub są już zmęczenie problemem gry w życie? Albo stwierdzają, że już nic nowego nie mogą się nauczyć i wybierają inne, ciekawsze aktywności w tym czasie. Ciężko mi to oceniać, ale wydaje mi się, jakby młodsi niedoświadczeni uczestnicy byli bardziej widoczni na tego typu wydarzeniach. To oznacza, że nadchodzą nowi, pełni zapału i żądzy wiedzy programiści, a więc tym bardziej nie można zostawać z tyłu…

środa, 20 listopada 2013

Drugi tydzień z rekaktywnym programowaniem

Dzisiaj minął pierwszy deadline na zadania z drugiego tygodnia z kursu Principles of Reactive Programming. Niestety nie udało mi się zdobyć maksa, a jedynie 8.15 z 10.00 punktów. Nie ma sensu dalej walczyć z tymi zadaniami, gdyż i tak maksymalna ocena za wysłanie rozwiązania dzień po terminie jest o 20% mniejsza, więc nic tym sposobem nie zyskam. Lepiej zabrać się za nowe wykłady i zadania, a z tego co słyszałem, to są one jeszcze obszerniejsze niż te z drugiego tygodnia.

Czemu poszło mi tak słabo? Dużo czasu straciłem na w pełni poprawną implementację Demultiplexera. Przeglądałem trochę forum kursu, widziałem tam kłótnie, co do tego w jakiej kolejności powinny być uporządkowane piny wyjściowe, a jednoznacznej odpowiedzi i wyjaśnienia nie było. Błąd, jaki popełniłem, to to, że za mało testów napisałem. Ba, nawet nie trzeba by było ich pisać, a jedynie zaadaptować te, które był dostępne na forum. Po skorzystaniu z takiego jednego testu, od razu udało mi się znaleźć błąd i zaimplementować poprawnie damultipleksera. Nie wystarczało naiwnie sprawdzać pin, na którym miał się generować oczekiwany stan wysoki, ale należało sprawdzać wszystkie piny!

W drugiej części zadania również nie do końca było jak dla mnie jasne, od czego należy zacząć i jak są generowane następne stany gry. Jakoś ta główna pętla symulacji była dla mnie zbyt zaciemniona. Ostatecznie nie udało mi się zaimplementować poprawnie na czas wszystkich reguł gry, gdyż nie chciałem nocki zarywać - wolałem się wyspać. No i też wymagania nie były dla mnie do końca jasne. Coś tam działa, kod przeszedł część testów, kilka punktów wpadło. Dla potomnych screenshot z symulacji.


Na cale szczęście limit 5ciu pierwszych punktowanych rozwiązań został zniesiony. Inaczej pewnie nie udałoby mi się osiągnąć takiego wyniku z tego zadania.

No nic, idziemy dalej, nie poddajemy się, miejmy nadzieję, że następnym razem pójdzie łatwiej.

piątek, 15 listopada 2013

Pierwszy tydzień kursu Principles of Reactive Programming na Coursera

Mija właśnie pierwszy (a właściwie to już drugi) tydzień kursu Principles of Reactive Programming na portalu coursera.org. Jest to kontynuacja wcześniejszego kursu (Functional Programming Principles in Scala) na tymże samym portalu, który również był prowadzony przez twórcę Scali: Martina Oderskiego.

Za pierwszy tydzień oczywiście zgarnąłem komplet punktów, mimo że żadnego video z kursu nie widziałem (to tak jakbym nie chodził na wykłady;)). Wystarczyły mi slajdy ze spotkań i trochę dokumentacji ze ScalaCheck. Jednakże nie jestem zadowolony z rozwiązań, jakie wysłałem. Nie można ich publikować, bo zabrania tego Code Honor, ale mam nieodpartą chęć zobaczenia i przedyskutowania innych rozwiązań. 

I tutaj pojawia się pytanie do Was: Czy ktoś byłby chętny na wspólną ustawkę na Google Hangouts, aby podzielić się swoimi rozwiązaniami i je przedyskutować? 

Ostatnio brałem udział (więcej o tym we wpisie: Remote Scalania 7 in Javart) zdalnie w spotkaniu organizowanym przez Jacka Laskowskiego, Scalani i ta forma (tj. Hangout) bardzo dobrze się sprawdziła. Coś podobnego (aczkolwiek bardziej skromnego) i tylko zdalnego chciałbym zorganizować, aby omawiać rozwiązania kolejnych zadań. Są chętni? Jeśli tak, to proszę o informację na priv (mstachniuk gmail com). Oczywiście spotkania muszą się odbywać po Hard Deadlinie, aby nie wpływać na wyniki rozwiązań. 

Czekam na odzew i życzę pomyślności w rozwiązywaniu zadań z kursu.

środa, 30 października 2013

Remote Scalania 7 in Javart

Właśnie się zakończyła pierwsza Remote Scalania 7 in Javart. Scalania, to projekt Jacka Laskowskiego, który polega na cyklicznych spotkaniach ludzi, chcących się wspólnie uczyć Scali. Spotkanie to było wyjątkowe, ze względu na to, że było ono pierwsze, w którym można było uczestniczyć zdalnie. Tak więc nie wychodząc z domu, mogłem się „spotkać” z innymi fanami Scali, wspólnie porozwiązywać zadania, poszerzyć swoją wiedzę i się z nimi scalić.

Generalnie w warsztacie uczestniczyły w sumie 4 osoby zdalne i ileś tam na miejscu, w siedzibie firmy Javart. Jako platformy do takiej konferencji skorzystaliśmy z Google Hangouts. Dodatkowo Jacek zrobił live stream’ing na YouTube’a, czego efektem jest filmik z pierwszej godziny spotkania: Scalania 7 in Javart. Jeśli ktoś się jeszcze waha, czy przystąpić do tej inicjatywy, to mam nadzieję, że ten filmik trochę pomoże i zachęci. Nie widziałem całego nagrania, ale generalnie ta forma Multi Video konferencji zdała egzamin.

Sam miałem wcześniej pewne obawy, czy poradzę sobie z tym kursem, czy wystarczająco znam Scalę, czy powinienem się angażować. Ale przecież w końcu zaliczyłem pierwszy kurs Martina Oderskiego: Functional Programming Principles in Scala, a i teraz szykuje się kolejny: Principles of Reactive Programming. A wiedzę należy odświeżyć. Troszkę przysiadłem wcześniej do rozwiązywanych poprzednio zadań w niedzielę, poniedziałek i wtorek, co okazało się w zupełności wystarczające.

Myślałem również, że na liście, którą rozwiązujemy, są na początku banalne zadania, a później już tylko trudniejsze. Na szczęście nie jest tak, tzn. są najpierw łatwe (z jedną gwiazdką), ale są one przeplatane trudniejszymi (dwie gwiazdki). Tych bardzo trudnych jest już zaledwie kilka. Taki rozrzut pomaga bez przeszkód na dołączenie do inicjatywy nawet od któregoś z kolei spotkania – w moim przypadku od 7mego.

Co do samego przebiegu spotkania, to uważam, że Jacek się bardzo fajnie sprawdza w roli moderatora całego zamieszania, gdzie trzeba rozmawiać z tymi, co siedzą na sali, ze zdalnymi, pokazywać obydwu grupom (miejscowym i zdalnym) kod, omawiać go a i czasem pisać. Pomimo inputu z różnych stron, Jacek był w stanie świetnie ogarnąć całość.

Podczas warsztatu miałem okazję pochwalenia się swoim rozwiązaniem (nie raz) i od razu zebrałem sporo krytycznych uwag. Ale dzięki temu, bardzo szybko się sporo nauczyłem. Pomogło mi również patrzenie na rozwiązania innych uczestników. Jak się widzi inne, dobre rozwiązanie, to się myśli: kurde, przecież to takie łatwe. Zauważyłem wcześniej u siebie (podczas rozwiązywania wcześniejszych zadań), że nauczyłem się jak działa młotek (w tym przypadku funkcje rekurencyjne z akumulatorem) i już niemal każde zdania traktowałem jak gwóźdź (czyli próbowałem każdy problem rozwiązać w ten sposób). Zobaczenie innego rozwiązania (jednolinijkowego), spowodowało u mnie odrzucenie zaślepek z oczu i późniejsze zadania próbowałem rozwiązywać już tylko w ten sposób.

Swoimi rozwiązaniami dzieliliśmy się za pomocą Gitsów. Na szczęście w IntelliJ Idei jest szybka możliwość publikacji takiego Gitsa. Dowiedziałem się też również, dzięki temu spotkaniu, że można swojego Gitsa edytować. Jest to sposób wystarczający do szybkiego podglądu rozwiązań, ale przydało by się je zbierać i wysyłać jako PR do repozytorium Jacka, aby zawsze można było sobie je później przejrzeć. Nie rozwiązaliśmy jednak problemu jak by dokładniej miało to działać.

Generalnie jeszcze na spotkaniach lokalni uczestnicy pracują w parach, ale zdalni pracowali osobno. Po prostu nie mieliśmy na szybko jakiegoś rozwiązania, jak taka pracę zorganizować. Kojarzę, ze kiedyś była możliwość takiej pracy w NetBeansie, ale na szybko nic sensownego nie znalazłem do Idei. Ewentualnie można skorzystać z TeamViewer’a, lub podobnego rozwiązania, ale to będzie dodatkowe obciążenie dla komputerów i mogą one nie dać rady. Jak dla mnie można próbować szukać jakiś możliwości zdalnego paring’u, ale nie jest to konieczne na przyszłych spotkaniach.

No i chyba na przyszłość przydało by się trochę więcej testów przygotować do każdego zadania, z warunkami brzegowymi i z niepoprawnymi danymi itp., choć obsługa tych sytuacji wyjątkowych mogła by sprawić, że 10 min na rozwiązanie problemu to za mało. Po za tym, co do ram czasowych spotkania, nie ma się do czego przyczepić. Jak dla mnie jest to idealnie zaplanowane i wykonane.

Podsumowując, dziękuję Jackowi za zorganizowanie Scalani w ten sposób, mam w zamiarze uczestnictwo w kolejnych spotkaniach. Jest jeszcze parę detali możliwych do dopracowania, ale i tak bez tego jest już super. Trzeba tylko pamiętać, aby zawczasu ściągnąć nowe testy, odpalić kompilator, aby reszta szła już sprawniej. Zachęcam również czytelników do aktywnego udziału w tej inicjatywie.

czwartek, 24 października 2013

Warsjawa 2013

W tym roku jakoś tak biednie u mnie było, jeśli chodzi o konferencje javowe (z różnych względów), ale na szczęście udało mi się zawitać na Warsjawę. Trzeba więc relację z tegoż wydarzenia skrobnąć, aby w przyszłości było gdzie zajrzeć do notatek, gdy przyjdzie mi zmierzyć się z jakimś poważniejszym problemem wydajnościowym lub a Akką.

Warsztat z Profilowania aplikacji JVM prowadzili Kuba Kubryński i Michał Warecki. Na początku było strasznie dużo teorii (właściwie do przerwy obiadowej), no ale nie każdy ma możliwość zmierzenia się z takimi problemami na co dzień, więc należało dużo wytłumaczyć i pokazać, co jest standardowo dostępne wraz z zainstalowanym systemem operacyjnym i JDK.

Zaczęło się od pamięci w Javie. Generalnie można ją podzielić na 3 części:
  • Young Generation
  • Old Generation
  • Permanent Generation

Młoda i stara generacja są przechowywane na stercie, a ostatnia trzecia część pamięci to Perm Gen, gdzie znajdują się załadowane klasy wraz z metodami. Co ważne, to to, że internowane Stringi lądują w Perm Gen i dlatego warto sprawdzać, ile one zajmują. Na szczęście od wersji 7 problem ten znika, gdyż teksty lądują na stercie. Więcej na ten temat tutaj: Java SE 7 Features and Enhancements.

Jest jeszcze coś takiego jak Code Cache, czyli miejsce w pamięci na skompilowany kod natywny naszych aplikacji. Pewnie jeszcze by się coś tam znalazło, ale nie jest to dla nas w tym momencie interesujące.

Następnie było o tym, jaka jest różnica między boolean a Boolean, a właściwie ile to obydwa twory zajmują pamięci. I tak boolean to jeden bit, ale Boolean to 12 bajtów nagłówka obiektu i jeden bit. A że nie można takich dziwnych, nieokrągłych wartości w pamięci używać, klasa zostanie dodatkowo wyrównana do 32 bitów (4ch bajtów) lub ich wielokrotności, w przypadku 32 bitowej maszyny wirtualnej. W przypadku 64 bitowej wersji będzie to zaokrąglenie do 64 bitów (8 bajtów), lub wielokrotności oczywiście.

Tak więc Boolean zajmuje w Javie aż 16 bajtów! Dlatego ze względów wydajnościowych, gdy trzecia wartość wyrażenia logicznego (null) jest nam niepotrzebna, to warto Boolean’a unikać.

Było jeszcze o rozmiarach, jakie zajmują obiekty:
  • shallow – to rozmiar samego obiektu wraz nagłówkiem
  • deep - rozmiar całego grafu obiektów, jaki jest osiągany z danego obiektu.
  • retained - rozmiar definiujący, ile pamięci było by zwolnione, gdyby właśnie wystartował Garbage Collector.

Jeszcze ciekawsze rozwiązanie to odśmiecanie przez kopiowanie, czyli Copying GC. W Young Generation mamy dwa obszary: From (Survivor1) i To (Survivor2). Gdy pierwszy z nich się zapełni i gdy nadejdzie czas na odśmiecanie, to żyjące obiekty zostaną przekopiowane z From do To. Następnie zamienią się role bloków, tzn. blok From stanie się nowym blokiem To, a obecnie zapełniony To stanie się nowym From. Każde takie kopiowanie pomiędzy Survivor1 i Survivor2 zwiększa wiek życia obiektów. Dzięki temu zabiegowi kopiowania do nowej przestrzeni, pamięć jest regularnie defragmentowana. Intensywnie z tego podejścia korzysta The Garbage First Garbage Collector (G1 GC). W tym przypadku pamięć jest podzielona na sporo kawałków, pomiędzy którymi, podczas odśmiecania, są kopiowane elementy.

W JVM są dostępne różne implementacjie Garbage Collectorów. I tak przykładowo domyślnym jest Serial GC (-XX:+UseSerialGC). Działa on jednowątkowo i blokuje inne zdania. Ale przynajmniej nie traci się tutaj czasu na przełączanie kontekstu.

Kolejną implementacją jest Parallel GC (albo jak podaje dokumentacja: throughput collector). Można ją uaktywnić pomocą -XX:+UseParallelGC a cechuje się ona tym, że w przeciwieństwie do Serial GC, używa wielu wątków do przyspieszenia odśmiecania. Domyślnie tylko generacja Young (Minor) jest odśmiecana równolegle. Aby również starą (Old, Major) generację równolegle odśmiecić, należy skorzystać z opcji -XX:+UseParallelOldGC. Te strategie redukują narzut Garbage Collektora na aplikację.

Kolejną implementacją czyszczenia pamięci z nieużytków jest Concurrent Collector (-XX:+UseConcMarkSweepGC), zwany też często CMS. Jest on zalecany tam, gdzie preferuje się krótkie przerwy na odśmiecanie, gdzie jest dużo długożyjących danych, na maszynach z dwoma lub więcej procesorami.

Jest jeszcze G1 GC, oficjalnie dostępny od JDK 7. Dzieli on całą pamięć na bloki, w których są umieszczane nasze dane. Gdy obszar się zapełni, dane są przenoszone do innych bloków, a co jest nie potrzebne - jest usuwane. Docelowo G1 GC ma zastąpić CMS GC.

Następnie były przedstawione Unixowe narzędzia, które mogą nam pomóc podejść do problemu od trochę innej strony (nie koniecznie od dupy strony). I tak za pomocą htop można podejrzeć drzewo procesów, również Javy. Iostat pokazuje utylizację zasobów na poziomie I/O. Dzięki temu można się np. dowiedzieć, że dysk nam nie wyrabia. Free pokazuje ilość wolnej / zajętej pamięci, a dstat przerywania, Contex Switche i inne różne zużycia. Natomiast perf to taki systemowy profiler. Uwzględnia on Contex Switch’e, migracje CPU (przerzucenie wykonywania czegoś na inny procek), ilość instrukcji na cykl CPU, odwołania do cache procesora.

Następnie było o narzędziach dostępnych w JDK. Poniżej opiszę tylko to, czego nie opisałem w relacji z JDD 2012.

Jinfo najczęściej pokazuje komunikat „Error attaching to process...”, ale jeden z prelegentów ma na to 2 obejścia: sudo sh -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
Lub w: /etc/sysctl.d/10-pthrace.conf ustawić kernel.yama.ptrace_scope = 0

Pierwsze jest tymczasowe i każdy admin powinien nam je na chwilę dać, a drugie jest permanentne, ale z jakiś tam względów niebezpieczne. Kolejne narzędzia to:

jstat -class PID 5s - komenda ta zrzuca nam co 5 sekund informację, ile jest załadowanych klas, ile pamięci zajmują i ile jest „odładowanych” klas
jstat -gc PID 5s - daje nam informacje o utylizacji pamięci
jstat -printcompilation PID 5s – pokazuje nam, które metody są skompilowane do kodu natywnego przez kompilator JIT (just-in-time compilation).
jstack PID - pokazuje stacktrace’y wszystkich wątków

Gdy chcemy się pobawić trochę linią poleceń, to możemy w ten sposób: java -XX:+PrintFlagsFinal -server –version wyświetlić sobie wszystkie flagi w Javie i poznać ich wartości domyślne. Niby znaczenie tych flag miało być gdzieś w dokumentacji opisane, ale jedyne co sensownego znalazłem to ten wpis na blogu: Hotspot JVM Options - The complete reference.

Później było jeszcze o Alekseyu Shipilevie i jego projekcie Java Object Layout. Niestety obecnie jest on niedostępny. Udało mi się gdzieś binarkę znaleźć, ale problem jest, jak to podpiąć pod Ideę / Eclipse’a, gdyż wszyscy linkują do strony autora, a ta już nie istnieje. Ale generalnie dzięki temu narzędziowi można podejrzeć wielkości, jakie zajmują w pamięci nasze klasy.

Było jeszcze trochę o Java VisualVM dostępnym standardowo w JDK. Warto do niego doinstalować pluginy, takie jak: MBeans, GC Viewer, Visual GC, Tracer i inne. Dzięki temu będziemy mogli sporo ciekawszych informacji podczas tuningowania naszych aplikacji uzyskać.

Po przerwie było jeszcze o Java Mission Control narzędziu, które jest dostępne JDK od wersji 7u40. Na pewno warto się przyjrzeć bliżej temu narzędziu.

Na koniec było jeszcze trochę o JProfileru i nadszedł czas na trochę praktyki. Za pomocą aplikacji profiling można było zobaczyć jak się zachowują różne implementacje Garbage Collectora, jak wyglądają wycieki pamięci itp. Podpinaliśmy się pod aplikację za pomocą JVisualVM’a i tam było bardzo ładnie widać co jak działa.

Kolejnym warsztatem, w którym uczestniczyłem, była Akka, prowadzona przez Maćka Próchniaka. Było już trochę widać zmęczenie po twarzach uczestników jak i samego prelegenta. No ale cóż, 17 godzina to trochę późna pora, zwłaszcza jak się chwilę wcześniej w innych warsztatach uczestniczyło.

Początkowy wstęp teoretyczny był bardzo klarownie przedstawiony i wszystko wydawało się bardzo jasne i proste. Takie się nie okazało, gdy przeszliśmy do kodu. Tam już było trochę ciężej. Postanowiliśmy, że zamiast osobno rozwiązywać zadania przygotowane przez Maćka, to rozwiąże on je sam, a reszta popatrzy. Tutaj jednak już nic więcej nie napiszę co zapamiętałem, ani czego się nauczyłem, gdyż trochę nie nadążałem / nie funkcjonowałem, a nieużywanie Skali od czasów ostatniego kursu Oderskiego dało mi się we znaki. Na szczęście niedługo startuje kolejna część tego kursu: Principles of Reactive Programming. Trzeba sobie do tego czasu trochę odświeżyć Scalę, aby gładko przez kurs przebrnąć.

Na koniec udało nam się zestawić razem rozproszonych aktorów, którzy komunikowali się ze sobą.

Byłem jeszcze na imprezie powarsztatowej. Udało mi się odnowić parę starych znajomości, trochę nowych nawiązać, dostać opieprz, że nic nie piszę na blogu (a więc jednak ktoś to czyta i niektórym komuś to pomaga), ani że nie występuję na konferencjach (zwłaszcza tych zagranicznych, nie mówiąc już o polskich). No cóż będę się starał zmienić ten stan rzeczy no i mam nadzieję, że się uda.

Na koniec należą się jeszcze wielkie brawa dla organizatorów, wolontariuszy i sponsorów, za super warsztaty (choć sam może nie trafiłem na typowe warsztaty), dobrą atmosferę i możliwość dzielenia się wiedzą jak i jej zdobywaniem. Sieć po kablu bardzo dobrze działała, trochę może brakowało informacji, gdzie, jaka sala się znajduje. Rozumiem też, że wydarzenie było darmowe i budżet był nie wielki, ale zabrakło mi... herbaty. No cóż, nie każdy jest przecież kawowcem (choć w naszej branży to chyba tylko jakieś odosobnione wyjątki), ale w ogólnej ocenie całości można ten detal pominąć. Trzymajmy poziom, aby w przyszłym roku było co najmniej tak dobrze jak w tym.

poniedziałek, 5 listopada 2012

Listy w Scali

Ostatnimi czasy biorę intensywnie udział w kursie programowania funkcyjnego w Scali na portalu Coursera.org. Generalnie kiedyś się zraziłem do tego języka, gdyż jakiś tutorial i aktualnie używana przeze mnie wersja środowiska, powodowała, że przekopiowane przykłady nie działały. Teraz jest już trochę lepiej, aczkolwiek IDE do Scali dalej kuleją.

Na sam kurs zapisałem się zachęcony przez kolegę z pracy – fana Scali. Pomyślałem, że skoro nie będę robił tego sam, a będzie wsparcie w razie czego, to warto się zaangażować. I rzeczywiście jeszcze kilka znajomych robi ten kurs. Ostatnio nawet organizuję cykliczne spotkania w pracy, podczas których prezentujemy i porównujemy nasz kod. Oczywiście omawiamy stare zadania, które są już po deadline, aby nie łamać Honor Code. Jeśli macie taką możliwość, to zachęcam do organizowania podobnych aktywności u siebie.

Czy uczestnictwo w takim kursie coś daje? Nawet jeśli Scala nie trafi do powszechnego użytku, to na pewno uczestnictwo w kursie pomaga w zrozumieniu paradygmatu funkcyjnego i wynikającego z niego konsekwencji. Horyzonty się poszerzają, co ostatnio pomogło mi w lepszym zrozumieniu Java Scripta na darmowym kursie we Wrocławiu. Więcej o tym szkoleniu w innym wpisie.

Dla mnie wielką satysfakcją jest moment, kiedy dostaję olśnienia i nagle całkiem odmiennie patrzę na coś, co używam na co dzień. Podczas tego kursu był już taki moment, podczas rozwiązywania zadań z drugiego tygodnia. Należało wówczas zaimplementować zbiór (Set). Zadanie niby proste, ale nie gdy w kodzie mamy coś takiego:
type Set = Int => Boolean 
Długo nie mogłem zrozumieć, o co chodzi. Czytałem wątki na forum kursu, szukałem w Necie... W końcu zrozumiałem, że w tym przypadku Set został zdefiniowany, jako funkcja przyjmująca wartość liczbową, a zwracająca informację, czy dana liczba należy do zbioru, czy nie. Całkiem odmienne spojrzenie, na coś co zawsze było pudełkiem przechowującym elementy. Jak widać, można inaczej. Co prawda sprawia to parę problemów (możliwy zakres elementów), ale wyjście po za tą ramę było dla mnie niesamowite.

Dobra, koniec tych przemyśleń, czas na konkrety. Listy towarzyszą uczestnikom kursu już od samego początku. Zostały one jednak dokładniej przedstawione, dopiero podczas piątego tygodnia.

Listy w Scali są niezmienne. Co prawda istnieje alternatywna implementacja: MutableList, ale chodzi o to aby używać niezmienników. Wiadomo dlaczego. Nie oznacza to jednak, że jak wrzucimy element do listy (a ściślej mówiąc stworzymy listę zawierającą dany element), to nie możemy zmienić stanu tegoż obiektu. Owszem możemy. W Javie było by to tak:
class Person {
    private final String name;
    public int variable = 0;

    public Person(String name, int variable) {
        this.name = name;
        this.variable = variable;
    }

    public void change() {
        variable = variable + 42;
    }
}

public class Main {

    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(new Person("Jan", 0));
        List immutableList = Collections.unmodifiableList(list);
        System.out.println(immutableList.get(0).variable);
        immutableList.get(0).change();
        System.out.println(immutableList.get(0).variable);
    }
} 

W Scali można analogicznie:
class Person(name: String, var variable: Int) {
  def change() {
    variable = variable + 42
  }
}

object Main {

  def main(args: Array[String]) {

    val person = new Person("name", 0)
    val list = List(person)
    println(list(0).variable)
    list(0).change()
    println(list(0).variable)
  }
} 

Tworzenie list w Skali mocno różni się od list w Javie. Z racji ich nie zmienności, musimy ich zwartość zdefiniować w momencie tworzenia.
val person = new Person("name", 0)
val list = List(person) 

Warto przy tej okazji zobaczyć, do czego będzie w tym momencie ewaluowane wywołanie List(person). Otóż List w Scali to:
  • abstakcyjna klasa List
  • objekt List
Klasa i objekt jednocześnie? Prawie. W Scali słówko kluczowe object oznacza definicję singletona. Po prostu ten wzorzec został wbudowany w język. Z praktycznego punktu widzenia, oznacza to, że możemy mieć tylko jedną instancję tegoż obiektu. Nie trzeba więc używać słówka new w tym przypadku.

Z drugiej strony, możemy przecież wywołać naszego singletona wielokrotnie z różnymi argumentami.
val list = List(person)
val list2 = List(person)
Jakby podejrzeć adresy w pamięci, to się okaże, że nie wskazują one tego samego miejsca. Co się więc dzieje? Jeśli chcemy skorzystać z dobrodziejstwa niepisania new, należy w naszym object’cie zdefiniować metodę apply() zwracającą żądaną instancję. Oczywiście metoda ta może przyjmować argumenty i zwraca żądaną instancję. Pełni wiec to bardziej rolę Fabryki niż singletonu. Jak to jest zdefiniowane dla listy? a no tak:
override def apply[A](xs: A*): List[A] = xs.toList 
Czyli na naszych argumentach (typu WrappedArray) zostanie wywołana metoda toList() i zadnie będzie gdzieś tam daleko delegowane...

No dobra, a jakiego typu listę otrzymamy? Patrząc na List.scala to można zobaczyć, że są dwie klasy rozszerzające tą Listę:
  • case object Nil extends List[Nothing]
  • final case class ::[B](...) extends List[B]

Pierwsza konkretna implementacja to element końcowy listy, za którym nic już nie ma. Natomiast dwukropek dwukropek, to nazwa klasy! Trochę się zszokowałem, gdy to zobaczyłem – rozumiem nazwać tak metodę, ale klasę? Jak widać można. Klasa ta tak naprawdę skleja głowę z ogonem. Implementacja jest bardzo prosta:
final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B] {
  override def head : B = hd
  override def tail : List[B] = tl
  override def isEmpty: Boolean = false 

A samego operatora używamy zazwyczaj w bardziej czytelnej formie
val person = new Person("name", 0)
val person2 = new Person("name2", 0)
val list = List(person2)
val list2 = person :: list 

A jak za pomocą :: utworzyć jednoelementową listę? Należy skorzystać ze wspomnianego już Nil’a:
val list3 = person :: Nil 
Analogicznie jak :: działa +: Ten drugi operator (a właściwie metoda) dodatkowo tworzy kopię bazowej listy. Możemy również dodawać elementy na końcu listy, ale raczej nie jest to optymalne. W tym celu używamy :+. Przykład:
scala> val text = List("Ala", "ma")
text: List[java.lang.String] = List(Ala, ma)

scala> val text2 = text :+ "kota"
text2: List[java.lang.String] = List(Ala, ma, kota) 

Można również sklejać listy. Do tego używamy potrójnego dwukropka ::: Przykład:
scala> val numbers = List(4, 6, -3, 1)
numbers: List[Int] = List(4, 6, -3, 1)

scala> val numbers2 = List(2, 3)
numbers2: List[Int] = List(2, 3)

scala> val numbers3 = numbers2 ::: numbers
numbers3: List[Int] = List(2, 3, 4, 6, -3, 1) 

Operator ten dokleja nowe elementy na początku istniejącej listy. Podobnie działa dwuplus ++, który dodatkowo tworzy kopię Listy:
scala> val numbers4 = numbers2 ++ numbers
numbers4: List[Int] = List(2, 3, 4, 6, -3, 1) 

Nie wiem jak by to można było na przykładzie przedstawić (a debugować mi się nie chce), po prostu musimy ufać dokumentacji.

Uff przebrnęliśmy szczęśliwie przez te ‘śmieszne’ operatory. Muszę przyznać, że dla początkującego adepta Scali, są te operatory trochę niejasne i mylące, dlatego warto poświęcić im chwilę. Istnieje jeszcze kilka metod produkujących listy:
xs.reverse - zwraca odwróconą listę
xs updated (n, x) - zwraca listę zawierającą to samo co xs, ale w miejscu o indeksie n wstawia x’a
xs.toList – metoda dostępna w wielu innych typach

Co jeszcze ciekawego mamy w listach w Scali?

Mamy 3 fundamentalne operacje:
head – zwraca pierwszy element
tail – zwraca wszystko poza pierwszym elementem
isEmpty – zwraca true dla :: i false dla Nil

Ponadto lista zawiera sporo innych już mniej wydajnych operacji (last, init, take…), jak i takie które znamy dobrze z Javy (contains, indexOf…).

Scala udostępnia nam trochę więcej operacji na listach, niż mamy to w czystej Javie. I tak na przykład przekształcenie listy w listę zawierającą inne elementy. W Javie zazwyczaj piszemy petlę:
List<String> names = new ArrayList<String>();
for (Person person : persons) {
    names.add(person.getName());
} 

W Scali można to wykonać prościej za pomocą map():
val names = persons map (p => p.getName) 

Czyli dla każdego elementu p z listy persons wywołaj getName i zwróć to wszystko opakowane w listę i zapisz w names. Czy jest to czytelniejsze? Jak się pamięta co robi metoda map() i jeśli jest się w stanie sobie wyobrazić co oznacza p, to tak. O ile jak czytam własny kod to jestem w stanie przeanalizować co się dzieje, ale jak bym miał to zrobić z czyimś kodem, to bym się pewnie musiał dłużej zastanawiać, o co kaman.

Tą, jakże krótką i zwięzłą definicję, można jeszcze zapisać na kilka sposobów:
val names = persons map (p => p getName)
val names = persons map (_.getName)
val names = persons map (_ getName) 

Następną przydatną operacją jest filtrowanie, czyli pobranie podzbioru listy. W Javie to by było jakoś tak:
List<Person> personsStartsWithJ = new ArrayList<Person>();
for (Person person : persons) {
    if(person.getName().startsWith("J")) {
        personsStartsWithJ.add(person);
    }
} 

W Scali można to zapisać na jeden ze sposobów:
val personsStartsWithJ = persons filter(p => p.getName.startsWith("J"))
val personsStartsWithJ = persons filter(_.getName.startsWith("J")) 

Dodatkowo mamy metodę filterNot(), która zwraca elementy niespełniające podanego warunku. Można również wykonać te dwie operacje (filter i filterNot) jednocześnie:
val personsPart = persons partition(_.getName.startsWith("J"))
println(personsPart._1)
println(personsPart._2) 

Przykładowy efekt działania:
List(Person(Jan))
List(Person(Stefan), Person(Emil), Person(Dominik)) 

Czyli bardzo sensowne użycie tuple’a, pomagające zwrócić dwa wyniki z metody. Nie kojarzę żadnych standarowych metod z Javy zwracających dwa wyniki. Tak wiem że SRP, ale jak akurat potrzebujemy obydwie listy, to dwukrotna iteracja może rzutować na performance. W Javie trzeba to na piechotę robić:
List<Person> personsStartsWithJ = new ArrayList<Person>();
List<Person> personsNotStartsWithJ = new ArrayList<Person>();
for (Person person : persons) {
    if(person.getName().startsWith("J")) {
        personsStartsWithJ.add(person);
    } else {
        personsNotStartsWithJ.add(person);
    }
} 

To na razie chyba tyle co chciałem przedstawić, zapisać, zapamiętać i podzielić się tym z Wami na temat Scali. Czas wrócić do oglądania kolejnych wykładów...

sobota, 22 września 2012

Kolejny Code Retreat

Dzisiaj wziąłem po raz kolejny udział w imprezie spod znaku Code Retreat. Tym razem odbył się on w Wolfsburgu – czyli mieście największego europejskiego koncernu samochodowego. Zorganizowany został on przez znajomych z pracy, a sponsorem była firma T-Systems on site.

Podczas początkowych sesji mogłem podzielić się swoją wiedzą z zakresu programowania w parach, TDD, baby steps, pisania dobrych testów i znajomości IDE. Nie ma się tu co rozpisywać, bo ciekawsze działo się później.

Postanowiłem wykorzystać obecność fanatyków Scali i trochę się poduczyć tegoż języka. Zdobyta wiedza przyda się przy realizacji kursu: Functional Programming Principles in Scala. Kto się jeszcze nie zapisał, ma jeszcze szansę. Więcej o kursie można poczytać na scala.net.pl. Podczas mojej pierwszej scalowej sesji, udało mi się sporo samemu napisać i odświeżyć jakieś stare wiadomości na temat tego języka. Część wymagań nawet działała. Szkoda jednak, że Eclipse dalej kuleje w tym temacie. Mam nadzieję, że z Ideą będzie lepiej.

Podczas mojej drugiej sesji skalowej programowałem razem z jeszcze większym wyjadaczem (fanatykiem) tego języka. Było więc co chłonąć. Podczas tej sesji (w ogólności) ćwiczyliśmy pisanie bez pętli, co w Scali nie jest jakimś utrudnieniem. Udało nam się całą logikę zakodować wraz z testami i bez pętli, w czasie krótszym niż 45 minut i z wyjaśnieniem mi, jak działa ta cała magia! Co chwilę wlepiałem swoje ślepia w ekran, dziwiąc się, co ‘to’ lub ‘tamto’ robi, oraz próbując zrozumieć, czy to aby na pewno pokrywa wszystkie wymagania. Jestem pod bardzo dużym wrażeniem tej sesji. Teraz trzeba na spokojnie (albo pod wpływem ;) ) poznać wykorzystane mechanizmy tegoż języka, aby móc je później efektywnie stosować.

Wyniesione doświadczenie z tej sesji, pozwoliło mi jeszcze podczas ostatniego sparowania, ponownie zakodować wszystkie reguły gry. Czasem lubię się droczyć, z moimi partnerami podczas Code Retreat. Zwłaszcza przy ping pongu staram się tak odbić piłeczkę, aby się później dużo nie narobić, a jedynie obserwować, jak ktoś się męczy. Tym razem coś poszło nie tak, gdyż sam musiałem się napocić. O dziwo udało się po raz drugi dojść do końca, bez większych problemów, że coś nie działa i nie wiadomo dlaczego. Dodatkowo nie można było rozmawiać podczas tej sesji, co stanowiło dodatkowe utrudnienie. Spotkałem się z nim po raz pierwszy i przekonałem się, ile rzeczy można przekazać niewerbalnie.

Podsumowując wypadło super. Był to mój 6ty CodeRetreat (licząc te oficjalne jak i te zamknięte). Obiad był na wypasie, ciepły z dużymi możliwościami wyboru dania i z deserem. Również było sporo owoców (zamiast ciasteczek) i możliwość zjedzenia śniadania (jak ktoś nie zdążył rano). Ważnym punktem (który był strzałem w dziesiątkę) była Club Mate. Pomogła ona zebrać siły na ten jakże wyczerpujący wysiłek intelektualny, jakim jest Code Retreat. Nieźle się naYerbałem, a w ogólnym rozrachunku, to cała skrzynka poszła. Uważam, że napój ten, powinien wejść do formuły Code Retreat ;)

Teraz pozostaje już tylko czekać, na drugi Global Day of Coderetreat, który w tym roku przypada 8 grudnia. Rok temu 94 miasta wzięły w tym udział, a cel na ten rok to 200 miast. Zobaczymy czy się uda i jak spędzę ten dzień.