sobota, 5 grudnia 2009

Ubuntu - wrażenia po instalacji

Tytułem wprowadzenia - jestem posiadaczem laptopa Toshiba Satellite Pro L300. Kiedyś była na tym Vista, ale wyleciała po 30 minutach użytkowania, znalazł się XP - znaleziony w pudełku z laptopem. Próbowałem odpalać różne linuxy, ale zazwyczaj albo zawieszały się podczas odpalania, albo nie wykrywały poprawnie sprzętu - ot taki urok.
Jako, że jestem leniwy zdecydowałem, że poczekam na jakiegoś linuxa, który zaskoczy za pierwszym podejściem.

Po kilku podejściach (bootowane z usb, lista na http://www.pendrivelinux.com/) okazało się, że warunki spełnia najnowsze Ubuntu 9.10.

W tak zwanym międzyczasie znalazłem wpis o możliwości dostania darmowej płytki z Ubuntu. Dostałem 4 dni po premierze - co spowodowało bardzo miłe zaskoczenie.

Dziś nadszedł dzień instalacji - płytka w napęd, reboot...

Odpalił się Live CD, potwierdzając wcześniejsze obserwacje - cały sprzęt wykryty, działa poprawnie, nawet kółko kontroli dźwięku zostało poprawnie obsłużone.
Wpisałem hasło do WLAN'a - też zadziałało od razu.

Potem poszło już z górki - gparted zmniejszył jedną z partycji, wolne miejsce użyłem na 2 partycje - ext4 i swap. Odpaliłem program instalujący Ubuntu - kilka pytań dotyczących języka, czasu i partycji, na których ma się zainstalować system, dalej, dalej, dalej... - prawie jak w Windows ;)

System instalował się, a ja oglądałem kolejne odcinki LFG.

Reboot - i zawiodłem się. Poprzednio używane sytrybucje - takie jak OpenSuse przyzwyczaiły mnie do ładnie wyglądającego menu startowego, łatwego w konfiguracji i łatwym sposobie wyboru systemu domyślnego (komputer użytkuje również żona, więc domyślnie Windows).
Domyślnie instalujący się grub jest ohydny.... Czarne, wyświetlane za pomocą BIOS'u menu - całe szczęście, że w 0x13h.

Pogodziłem się z sytuacją - chciałem ustawić Windowsa jako system domyślny:
su xterm, mc, cd /etc/grub2 i kolejny szok - z czegoś co było łatwe proste i przyjemne zrobiono coś zrozumiałego tylko dla maszyny.

Idę czytać dalej...

poniedziałek, 5 października 2009

Optymalizacja wydajności - przypadek szczególny

Cel:
Traf chciał, że jakiś czas temu powstał kawałek systemu, którego celem było zapamiętanie migawek większej ilości powiązanych tabel (powiązania można określić jako dwa drzewa, połączone za pomocą 2 gałęzi). Głównym powodem powstania była konieczność "zamrożenia" stanu danych na dany moment, możliwością odczytu (za pomocą SQL) kolejnych wersji.

Baza danych
AS400 - IBM - stosowana przez banki, NFZ i mafię kolumbijską. Konkretnie w wersjach od 5.2 do 6.1 (najnowsza)

Struktura:
Tabela główna A z kluczem głównym na 1 polu,
Tabela z historią H - klucz główny na 1 polu - typu DEC(12, 0)

Relacja A <- H (1 do wielu)
Zapis wszystkich danych do tabeli M



Podejście 1:
Realizacja:
Procedura składowana zrzuca dane do jednej tabeli M, gdzie pamiętamy:
a) identyfikator kolejnego uruchomienia procedury
b) typ elementu - wyliczeniowy, definiowany na zewnątrz
c) identyfikator elementu A
d) identyfikator tabeli z historią H

Problemy:
Ilość danych przerosła oczekiwania - w przypadku równoległego uruchomienia 60-100 kopii procedury ilość danych zapisywanych do 1 tabeli osiągała 1 milion rekordów na minutę - baza dawała radę, ale wszystko dookoła zdychało.

Próba rozwiązania:
Ograniczenia w ilości uruchomień, osobna pula połączeń dla procedury generującej.

Wynik:
Z powodu liniowego narastania ilości danych wydajność spadała (również liniowo) - czas wykonania jednej procedury osiągał do 2-3h.



Podejście 2.
Realizacja:
Rozbicie tabeli, do której zapisywane są dane M na wiele tabel - głównie w celu rozbicia obciążenia dysków.

Wynik:
Skok wydajności, ale o wiele mniejszy od oczekiwanego - spowodował powtórne osiągnięcie wydajności takiej jak kilka miesięcy wcześniej.

Problemy:
Ciągle liniowy spadek wydajności z czasem.

Po długiej analizie okazało się, że wiele równolegle puszczonych zapytań typu:

SELECT * FROM H
WHERE H.ID = (SELECT MAX(ID) FROM H WHERE H.ID_A = ID_A)

generuje zdumiewająco duże obciążenie procesora (wszystko po indeksach).



Podejście 3.
Realizacja:
Do tabeli A zostało dodane pole ID_H przechowujące wartość ostatniego rekordu historii.
Podczas zapisu do tabeli H pole A.ID_H jest aktualizowane.

Wynik:
Skok wydajności o około 10 000%... Uśmiechnięty i zadowolony klient, baza danych w końcu odciążona, można realizować kolejne pomysły klienta.




Fanfary, oklaski dla projektanta X (autora pomysłu 3.) , baty dla projektanta Y (autora pierwszego pomysłu), a dla programisty skrzynka piwa - za to, że musiał to wszystko kodować...

piątek, 10 lipca 2009

Delegacja...

Nadejszła...
Po ponad miesiącu olewania i udawania, że te maile wcale nie przyszły, doszło do ostatecznego aktu desperacji:Kilent zaprosił nas do siebie.
Kilent ma dosyć ciekawą specyfikę: zarządzany jest przez osoby zmieniające się okresowo, niekoniecznie posiadające wystarczającą (jakąkolwiek) wiedzę merytoryczną dotyczącą zakresu działani Klienta. Czasem pomysły zarządu niewiele mają wspólnego ze zdrowym rozsądkiem, a czasem porażają przejrzystością idei i dalekowzrocznością wizji. Klient posiada kilkanaście jednostek podrzędnych, które kiedyś były niezależne i chciałyby do tego stanu wrócić.

Doszło do tego, że realizujemy jeden z pomysłów Jednostki Nadrzędnej.
Realizacja ciągnie się od kilku miesięcy - głównie z powodu konieczności dokładnego testowania i sprawdzania poprawności. Klient chce, żeby działało poprawnie od pierwszego kliknięcia - jego prawo, ale efekt jest taki, że testerzy ledwo zipią...
Jak dotychczas wszystko szło poprawnie, ale pojawiły się "nowe cele biznesowe", które spowodowały "realokację zasobów ludzkich na nowe pola".

Efekty:
1. Napisana w ciągu 12 dni roboczych procedura wymiany danych z raportami błedów (kilka poziomów logowania, sprawdzanie poprawności w trakcie działania, dodatkowe zabezpieczenia) (około 40-50k lini) (java, xml) - działa, przetestowane, łatwe w serwisowaniu.
2. Procedura o długości ponad 5k lini (tak, kocham programowanie proceduralne...) (sql)
3. Około 30 procedur o długości ok. 200-1500 linii. (sql)

Wnioski:
1. Nauczyć się w końcu zarządzać czasem i produktywnością.
2. Cele realizować tak, żeby nie przekraczać terminów.
3. Uczynić cud - dzień będzie miał 48h
4. Uczynić drugi cud - będę miał 6 palców u rąk
5. Uczynić trzeci cud - nauczyć się pisać na trzech klawiaturach jednocześnie
6. Zmienić pracę?

środa, 1 lipca 2009

Klient telneta

Moja chęć pomocy innym doprowadzi mnie do zawału.
Podjąłem się napisania klienta graficznego do obsługi Killer'a.

Wszystko wygląda różowo poza kilkoma sprawami:
- nie mam porządnego, darmowego środowiska
- mam Turbo Delphi
- nie mam porządnych, darmowych komponentów do TCP/IP
- mam TTcpClient i TTcpServer
Kto używał, ten wie "o so chodzi". Żal i rzucanie kredkami - w skrócie...

Główne powody marudzenia:
1. Brak jakiegokolwiek działającego przykładu obsługi TTcp*
2. W necie ilość informacje jest tak skąpa, że szukanie poprawnego kodu przypomina szukanie wszy w majtkach.
3. Pozornie oczywiste metody (TTcpClient.Receive i TTcpServer.Accept) nie działają tak, jakbym chciał. Wysłać dane owszem - da się, ale co z tego, skoro nie widać informacji zwrotnej.

Tak coś mi sie wydaje, że skończy się na DevC++ i FLTK. Niezbyt proste, niezbyt efektywne, ciężkie w obsłudze, ale jak już działa, to działa, a nie stroi fochów ;)

Ironia losu polega na tym, że Delphi używam na codzień, a C++ raz na 2 lata ;)

środa, 10 czerwca 2009

Historia

Dzisiejszy dzień upłynął pod znakiem odgrzebywania starych śmieci i przypominania sobie jak to wszystko działało.

Po pierwsze - jakiś tam kod, pisany tylko przeze mnie od 2006-12. Kod poprawny, założenia do kitu - ale jakoś działało ;) Ciekawostką jest fakt, że dwaj uzytkownicy z Poznania i Szczecina w tym samym dniu odkryły błąd, który mógł wystąpić od 2 lat, a ja odkryłem go tydzień wcześniej...
Poprawione szybko i bezboleśnie.

Po drugie - inny kod, pisany przez 5 osób, tez brałem udział, powstał ok 2007-04. Kod poprawny, założenia też, ale niestety w międzyczasie zmieniły się wymagania. Kod zdezaktualizował się, ktoś coś poprawił, ktoś inny poprawił poprawkę.
Po 4 godzinach analizy okazało się, że "wystarczy" zmienić 10 znaków w zapytaniu SQL i wszystko działa poprawnie...

Wnioski na przyszłość - komentujmy kod! Opisujmy założenia jakie nam przyświecały, a nie działanie. Jak coś działa widać od razu - przecież kod czytają tylko programiści, więc po co pisać:
// przygotowanie zapytania zliczenia liczby wyszukanych rekordów
sb = new StringBuffer();
sb.append("SELECT COUNT(S1.IMWU) \n");

skoro można napisać
// Liczba miejsc wykonywania świadczeń, użytych w zestawie produktów
sb = new StringBuffer();
sb.append("SELECT COUNT(S1.IMWU) \n");

Niestety druga opcja wymaga zrozumienia tego, co się pisze.
Zauważam ze smutkiem, że niektórzy (większość?) programiści mają tendencje do pisania mechanicznego, bez próby zrozumienia przyczyny powstania kodu. Dostają projekt i bezmyślnie walą w klawisze. Efektem jest kod nieodporny na zmiany (wynikające z naturalnego rozwoju i tematyki zagadnienia) w którym brak jest podstawowych walidacji.

Z innej beczki. Może by tak spróbować skompilować Killera na g++? Jeśli się uda, to otworem stoi droga do obiektów, klas i czystego mięska pt. RTTI.

poniedziałek, 8 czerwca 2009

Pisania sens

Od 2 tygodni nie napisałem nic, co nie miałoby związku z pracą. Dobrze mi z tym.

Projekt Słabiaka na odpalenie nowego muda powoli umiera - zamysł niezły (link), ale nie potrafię się z nim dogadać - ot "nie zaiskrzyło".

Killer rozwija się, może nie tak szybko jak kiedyś, ale nowa-stara krew, czyli Drake, Agron, Gurthg i inni Lordowie pchają całą lokomotywę do przodu. Nie idzie to zbyt szybko, lecz nie ma się co dziwić - ludzie dojrzeli do tego, że komputer jest tylko narzędziem, a narzędzia można zawsze odłożyć, wyłączyć i zająć się życiem.

Zajmuję się rzeczami ważnymi, na które wcześniej szkoda było mi czasu, albo nie wpadłem na to, że można. Wszyscy wokół na tym zyskują. Przede wszystkim żona - najbardziej ją zaniedbywałem, mam wreszcie czas, żeby z nią pogadać o pierdołach i innych takich. Można swobodnie snuć plany na przyszłość, w końcu dokończyć "niekończącą się opowieść" - remont pokoju.

W tak zwanym międzyczasie odkryłem nowego konika - jazdę na rowerze po różnych wertepach. Po płaskim mnie nudzi...
Pomimo swoich 120 kg dotarłem na metę maratonu mtb w Szczawnicy i Międzygórzu - było ciężko, obyło się bez wywrotek i awarii. Sprzęt nie zawiódł, pożyczone opony zrobiły swoje.
Już niedługo Złoty Stok - być może z przejazdem przez kopalnię. To będzie coś - sztolnie na rowerze!

czwartek, 28 maja 2009

MS Visio

Wrrrr!!!!!!
Ktoś, kto napisał MS Visio powinien za karę używać go do końca życia. Dawno nie używałem równie nieintuicyjnego i nieefektywnego oprogramowania. Z rozrzewnieniem wspominam czasy pracy na Sparx'ie...
Mogę polecić, szczególnie architektom oprogramowania, jest świetny. Proponuję pobrać wersję trial i używać. Program nie jest (nie był -używałem 4 lata temu) pozbawiony wad, ale te są na tyle nieistotne, że można pominąć je milczeniem.
Visio - moja zmora, muszę używać, jestem ograniczony terminami, a program zamiast pomagać - przeszkadza. Robię diagramy stanów i sekwencji wg UML - ratunku!!!
Przeciąganie obiektów - da się zrozumieć, czasem warto zobaczyć proporcje elementów.
Przeciąganie strzałek, które łączą elementy - totalna głupota.

Jak to określił jeden z kolegów: "Przez studentów - dla studentów". Całkiem nieźle sprawdza się przy małych bazach i niewielkich projektach. Przy naszej zachaczającej o 1500 tabel ( średnio po 30-40 pól) bazie visio wymięka. Synchronizacja bazy to czas na kawę. Najbardziej potrzebna funkcjonalność - odczyt komentarzy do pól z bazy nie istnieje (nie działa na iSeries/AS400). Kończy się na ręcznym przepisywaniu. Wrr!!!

Kodowanie

Udało się! Po 2 tygodniach przerwy znów siadłem do kodu. Na całe 2h. Jak dla mnie sukces.
Poprawiłem wkurzający błąd z przekręcaniem się złóż - polegał na sprawdzeniu przekroczenia operatorem == zamiast <=. Błąd poprzednika, mnie przyszło poprawić. Na przyszłość: nie popełniać takich błędów...

Na dokładne testy czeka riding - szef chciałby zakodować możliwość jazdy kilku osób. Niby proste, ale wymaga ingerencji w wielu miejscach kodu (głównie spadanie po czarach) i poważnego przegrzebania sterowania i zsiadania.

Zaczynam marzyć o obiektach - takich z prywatnymi polami, mozliwością kontroli dostępu i okodowania zewnętrznego interfejsu. Wtedy zmiana byłaby w jednej klasie i tyle. W proceduralnym ANSI C jest cała masa grzebania, zastanawianie się, czy aby dobrze i czy czasem jak w jednym miejscu popuszczę trochę walidację, to czy w innym nie będzie siało po pamięci.

Trzeba pamiętać o innych koderach - czy zrozumieją kod? Czy będzie im się chciało poczytać komentarze? Jak zmienić ich przyzwyczajenia?

czwartek, 14 maja 2009

Mining, znaczy kopanie

Po raz kolejny przekonałem się, że po przejęciu czyjegoś kodu należy wszystko wyciąć w pień i napisać od nowa, albo spędzić 100% więcej czasu sprawdzając "obcy" kod i szukając błędów. Dotyczy to szczególnie sytuacji, gdy pisze się w Ansi C, z użyciem wszystkich możliwości tego języka.
Zgłoszenia błędów przyszły z różnych stron, kilka błędów w starym kodzie, kilka w moim (a co, też się mylę).

Nauczyłem się czegoś po przejrzeniu kodu kolegi. Nie należy od razu pisać, ale najpierw zastanowić się nad działaniem - i to bardzo dokładnie zastanowić. Potem rozrysować przebiegi czasowe, zastanowić się jak spiąć przebiegi kilku pętli w jedną i dopiero wtedy zaczynać kodowanie.

środa, 6 maja 2009

Wstępniak

Koduję.
Kodowanie polega na ustawicznym spieraniu się, jak widzielibyśmy efekt końcowy. Czasem wynik dyskusji podoba mi się, a czasem nie. W tym blogu pojawiać się będą przemyślenia na temat kodowania w ogóle, kodowania w określony języku, a także kodowania muda o nazwie Killer MUD.