Wielu ludzikom, którzy nie biorą na poważnie optymalizacji lub nie mają z nią potencjalnych problemów na codzień takie pojęcie jak profilowanie bywa długo obce. Mogą tylko się z tego cieszyć, bo w rękach ich bardziej doświadczonych kolegów od profilowania aplikacji spoczywa pewna magiczna moc.
Czasami bywamy pytani o to, jak można coś zrobić szybciej lub napisać tak, aby działało szybciej na tej samej maszynie. W sytuacji w której tematem optymalizacji jest jakiś nieskomplikowany język skryptowy typu Python, PHP, czy Ruby mamy do dyspozycji napisanie modułu w języku C. Zasadniczo te języki są napisane w C (C++) i zakładamy, że moduł napisany w języku źródłowym, w którym napisano dany język będzie szybszy. Sprawa się nieco komplikuje, gdy nie mamy takiego pomostu jak możliwość napisania kodu modułu w kodzie źródłowym języka. Jeszcze częściej nie mamy wpływu na sposób zarządzania pamięcią oraz wielowątkowością w danym języku skryptowym. Posłużę się dla przykładu językiem PHP, który posiada źródłową konwencję nazwaną Zend Engine. Jest to narzucony silnik stworzony poprzez firmę Zend i rozwijany przez deweloperów woluntariuszy na całym świecie. Niestety naleciałości, które ciągną się za nim od wielu lat ograniczają znacząco działanie tak istotnych mechanizmów języka jak wielowątkowość i odśmiecanie pamięci. Język ten w samych swoich źródłach jest pod tym kątem niedojrzały. Inna sytuacja jest w przypadku języka Python i Ruby. Słynna translacja języka Python w samym RPython (Restricted Python) - statycznym podzbiorze Pythona, który można skompilować do kodu bajtowgo Javy, CLR czy C, czyli projekt PyPy. Pozwala na bardzo rozwinięte horyzonty działania, które dla niewiedzących prowadzić mogą do definowania np: własnych zasad odśmiecania pamięci, sposobu działania wielowątkowości i całej gamy innych drobiazgów, które stawiają dość wysoko język Python na podeście :-) Nie znam dokładnie źródeł języka Ruby, ale widziałem, że są czytelne i można po nich wywnioskować, że doruwnuą projektowi takiemu jak Python, ale też zostawiają w tyle PHP Zend Engine.
Rozpisałem się o ogólnym spojrzeniu na źródła powszechnych języków skryptowych, aby naświetlić tylko, że dla niektórych języków temat optymalizacji, czyli profilowania na poziomie źródeł języka jest dość ograniczony. Lecz z kolei są takie języki skryptowe, które można profilować na poziomie wątków oraz zarządzania pamięcią. Projekty w ramach których dość czytelnie to zaprezentowano zawierają materiały dodatkowe. Wspomnę jeszcze, że nasz ulubiony googiel też się podpisuje do takich praktyk i posiada dość spore doświadczenie w tej materii. W soich serwerowniach dobierają procesory oraz z tego co mi wiadomo na farmach maszyn odbywa się również profilowane kompilowanego oprogramowania, aby jak najwięcej wycisnąć. Jest to jedna z nielicznych firm, która używa selekcjonowanych i wygrzewanych partii procesorów Pentium III oraz serwerownie stanowią klastry słabszych maszyn o przewidywalnej mocy obliczeniowej oraz przewidywalnym zużyciu energii. Skoro google udowodniło, że można nie kupować drogich serwerów IBM, czy Suna, czy tez HP jestem zgodny z nimi, że wówczas bez profilowania oraz optymalizacji zarówno hardware a przede wszystkim software nie wiele zdziałamy.
Przechodząc do części praktycznej chciałbym uchylić fragment tajemnicy przyspieszania aplikacji z Google Perftools. Materiał na temat przykładu profilowania znajdziecie tutaj.
Życzę pomyślnej lektury i zapraszam do podzielenia się refleksjami na ten temat.
Materiały dodatkowe:
Mastering the Art of Indexing
High Availability and Scalability Patches from Google
More on using Google Perftools with MySQL
Using the Google Perftools to speed up your MySQL server
Using the Google Perftools to speed up your MySQL server - example
Fast, multi-threaded malloc() and nifty performance analysis tools
Simple HTTP server for use with google-perftools pprof
TCMalloc : Thread-Caching Malloc
prof/PerfTools
This page describes how to setup and use PerfTools.
This CPU profiler used at Google
Spinlock
Practical Concurrency Patterns: Spinlock
Practical Concurrency Patterns: Lock-Free Operations
Spinlock example code
The performance of spin lock alternatives for shared-memory multiprocessors
HP - Spinlock Pool Parameter Summary
.NET Framework Class Library - SpinLock Structure
The Hoard Memory Allocator and Memory Management Studies
Generate Ruby Profiling Charts With Perftools
Profiling Ruby With Google’s Perftools
Distributed Innodb Caching with memcached
InnoDB: Innovative Technologies for Performance and Data Protection
17 czerwca 2009
9 czerwca 2009
Stackless Python - jak zrobić mikrowątki na localhost
Dziś zapraszam do kilku prób zrobienia z naszego lokalhosta maszyny z działającymi w tle mikrowątkami Stackless Python, które potrafią dość wiele zdziałać. Aby dowiedzieć się jak wiele polecam przeczytanie artykułu o grze EVE on-line, która bazuje na tym rozwiązaniu.
Ważnym wprowadzeniem będzie teoria na wikipedii dotycząca Distributed computing. Są różne podejścia do reazlizacji wielowątkowości i jej synchronizajci. Zasadniczo doceniam w tym artykule specyficzne, bo posiadające w API dosłownie kilka funkcji. Zaimplementowanych w taki sposób, że aż się miło testuje i wdraża takie rozwiązanie. Oczywiście porównuję tutaj API systemowe np: WINAPI i POSIX THREADS. Jest z tym nieco zabawy w projektowaniu i kodowaniu, dlatego przedstawiam Stackless Python, który może rowiązać więcej problemów niż tylko wymienione niewygody wielowątkowości w naszym systemie operacyjnym.
Okazuje się, że programowanie wielowątkowe na większą skalę wcale nie musi posiadać skomplikowanego API. Projektanci Stackless Python doskonale o tym wiedzieli i uprościli bazowe elementy API do następujących pojęć:
Zacznę od bazowego przykładu, który pokazuje, jak rozpocząć zabawę z tą technologią. Do wykonania poniższego kodu będzie potrzebna obecność w naszym systemie pypy-stackless.
Tasklets są podstawowym budulcem dla stackless. Możesz utworzyć zadania tasklet przez dodanie zwykle funkcji lub metody klasy. Stworzony w ten sposób tasklet zostaje dodany do harmonogramu zadań. Zauważ, że kolejka taskletów i nie działaja, dopóki nie nastąpi wywołanie metody stackless.run().
Oto prosta demonstracja:
Uruchamianie przykładu oraz rezultaty działania:
Scheduler kontroluje kolejność, w jakiej tasklets są uruchamiane. Jeśli po prostu stworzysz kilka taskletów, będą uruchamiane w kolejności, w jakiej zostały utworzone. W ogólnej praktyce będzie to związane ze stworzeniem i wywołaniem dodanych taskletów za każdą iteracją ogólnego mechnizmu obiegu danych.
Zauważ, że gdy wywołujemy stackless.schedule(), aktywnym tasklet zatrzymuje się i ponownie wstrzykuje się do końca schedulera w kolejce, pozwalając następnemu taskletowi uruchomić się. Gdy wszystkie z aktywnych taskletów zostaną uruchomione, następuje przywoływanie pozostałych. To trwa do zakończenia wszystkich aktywnych taskletów. W ten sposób osiągamy wielowątkowość we współpracy z stackless.
Szybka demonstracja:
Uruchamianie przykładu oraz rezultaty działania:
Channels czyli kanały umożliwiają wysyłanie informacji między tasklets. To realizuje dwie rzeczy:
Pozwala to na wymianę informacji między tasklets.
Pozwala to na kontrolę przepływu egzekucji.
Kolejna szybka demonstracja:
Uruchamianie przykładu oraz rezultaty działania:
Kilkoma słowami chciałbym podsumować opisane rozwiązanie w Stackless Python. Po pierwsze ilość dostępnych funkcji w API oraz sposób ich użycia szczególnie zachęca do zgłębiania i używania (4 - 6 funkcji). Zarazem niesamowitym osiągnięciem jest fakt, że tak wielki projekt gry on-line jak EVE bazuje na tak prostym i wydajnym rozwiązaniu.
Zachęcam do opisania swoich doświadczeń ze Stackless Python w komentarzach, chętnie podyskutuję.
Mariały dodatkowe:
Stackless Python Homepage
why stackless
Is Stackless Python for You?
Introduction to Concurrent Programming with Stackless Python
Wątki
http://www.archivum.info/pl.comp.lang.python/2008-03/msg00119.html
http://forum.gamedev.pl/index.php?action=printpage%3Btopic=6678.0
Kurs Pisania OS
Debug pamięci w Linuksie (pamięć od strony technicznej)
Dynamiczne zarządzanie pamięcią w C bez wycieków
Stackless Python - artykuly
CORBA Guru Steve Vinoski on REST, Web Services, and Erlang
Ważnym wprowadzeniem będzie teoria na wikipedii dotycząca Distributed computing. Są różne podejścia do reazlizacji wielowątkowości i jej synchronizajci. Zasadniczo doceniam w tym artykule specyficzne, bo posiadające w API dosłownie kilka funkcji. Zaimplementowanych w taki sposób, że aż się miło testuje i wdraża takie rozwiązanie. Oczywiście porównuję tutaj API systemowe np: WINAPI i POSIX THREADS. Jest z tym nieco zabawy w projektowaniu i kodowaniu, dlatego przedstawiam Stackless Python, który może rowiązać więcej problemów niż tylko wymienione niewygody wielowątkowości w naszym systemie operacyjnym.
Okazuje się, że programowanie wielowątkowe na większą skalę wcale nie musi posiadać skomplikowanego API. Projektanci Stackless Python doskonale o tym wiedzieli i uprościli bazowe elementy API do następujących pojęć:
- Tasklets
- The Scheduler
- Channels
Zacznę od bazowego przykładu, który pokazuje, jak rozpocząć zabawę z tą technologią. Do wykonania poniższego kodu będzie potrzebna obecność w naszym systemie pypy-stackless.
Tasklets są podstawowym budulcem dla stackless. Możesz utworzyć zadania tasklet przez dodanie zwykle funkcji lub metody klasy. Stworzony w ten sposób tasklet zostaje dodany do harmonogramu zadań. Zauważ, że kolejka taskletów i nie działaja, dopóki nie nastąpi wywołanie metody stackless.run().
Oto prosta demonstracja:
# example1.py
import stackless
def print_x(x):
print x
stackless.tasklet(print_x)('one')
stackless.tasklet(print_x)('two')
stackless.tasklet(print_x)('three')
stackless.run()
Uruchamianie przykładu oraz rezultaty działania:
$ pypy-stackless example1.py
one
two
three
Scheduler kontroluje kolejność, w jakiej tasklets są uruchamiane. Jeśli po prostu stworzysz kilka taskletów, będą uruchamiane w kolejności, w jakiej zostały utworzone. W ogólnej praktyce będzie to związane ze stworzeniem i wywołaniem dodanych taskletów za każdą iteracją ogólnego mechnizmu obiegu danych.
Zauważ, że gdy wywołujemy stackless.schedule(), aktywnym tasklet zatrzymuje się i ponownie wstrzykuje się do końca schedulera w kolejce, pozwalając następnemu taskletowi uruchomić się. Gdy wszystkie z aktywnych taskletów zostaną uruchomione, następuje przywoływanie pozostałych. To trwa do zakończenia wszystkich aktywnych taskletów. W ten sposób osiągamy wielowątkowość we współpracy z stackless.
Szybka demonstracja:
# example2.py
import stackless
def print_three_times(x):
print "1:", x
stackless.schedule()
print "2:", x
stackless.schedule()
print "3:", x
stackless.schedule()
stackless.tasklet(print_three_times)('first')
stackless.tasklet(print_three_times)('second')
stackless.tasklet(print_three_times)('third')
stackless.run()
Uruchamianie przykładu oraz rezultaty działania:
$ pypy-stackless example2.py
1: first
1: second
1: third
2: first
2: second
2: third
3: first
3: second
3: third
Channels czyli kanały umożliwiają wysyłanie informacji między tasklets. To realizuje dwie rzeczy:
Pozwala to na wymianę informacji między tasklets.
Pozwala to na kontrolę przepływu egzekucji.
Kolejna szybka demonstracja:
# example3.py
channel = stackless.channel()
def receiving_tasklet():
print "Recieving tasklet started"
print channel.receive()
print "Receiving tasklet finished"
def sending_tasklet():
print "Sending tasklet started"
channel.send("send from sending_tasklet")
print "sending tasklet finished"
def another_tasklet():
print "Just another tasklet in the scheduler"
Uruchamianie przykładu oraz rezultaty działania:
$ pypy-stackless example3.py
Recieving tasklet started
Sending tasklet started
send from sending_tasklet
Receiving tasklet finished
Just another tasklet in the scheduler
sending tasklet finished
Kilkoma słowami chciałbym podsumować opisane rozwiązanie w Stackless Python. Po pierwsze ilość dostępnych funkcji w API oraz sposób ich użycia szczególnie zachęca do zgłębiania i używania (4 - 6 funkcji). Zarazem niesamowitym osiągnięciem jest fakt, że tak wielki projekt gry on-line jak EVE bazuje na tak prostym i wydajnym rozwiązaniu.
Zachęcam do opisania swoich doświadczeń ze Stackless Python w komentarzach, chętnie podyskutuję.
Mariały dodatkowe:
Stackless Python Homepage
why stackless
Is Stackless Python for You?
Introduction to Concurrent Programming with Stackless Python
Wątki
http://www.archivum.info/pl.comp.lang.python/2008-03/msg00119.html
http://forum.gamedev.pl/index.php?action=printpage%3Btopic=6678.0
Kurs Pisania OS
Debug pamięci w Linuksie (pamięć od strony technicznej)
Dynamiczne zarządzanie pamięcią w C bez wycieków
Stackless Python - artykuly
CORBA Guru Steve Vinoski on REST, Web Services, and Erlang
6 czerwca 2009
Max/MSP + Arduino - udźwiękowienie głuchej maszyny
W wielu wymiarach mikroprocesorowych odkryć jest też taki, który powoduje, że głucha, cicha i stara zabawka leżąca w szuflkadzie jaką może być system mikroprocesorowy nagle ożywa i wydaje przeróżne - w tym niesamowite - dźwięki. Mam na myśli adaptacje Adruino w wersji MaxMSP.
Z materiału Arduino VS Max/MSP wynika, że najlepszym softem do zabawy będzie Maxduino. Zabawa może polegać na tym, że rozrysowujemy w aplikacji Max wykres działania / połączenia z systmem generatorem/syntezatorem dźwięku i uploadujemy program do naszej zabawki. Dodatkowe interfejsy mile widziane. Diody RGB, klawisze, czujniki natężenia światła i całą resztę można powiązać z syntezowaniem bitów, które sprawią, że na pozór cichy i bezduszny sprzęt nabierze niesamowitego wydźwięku i będzie w stanie nas zaskoczyć brzmieniem np: z gatunku ambient :-)
Oto kilka przykładów zrealizowanych pomysłów:
Materiały dodatkowe:
http://www.music.mcgill.ca/~gary/306/week5/serial.html
http://www.tigoe.net/pcomp/code/category/category/MaxMSP
http://www.flickr.com/photos/gudmundsson/3234647715/
http://www.soundplusdesign.com/?p=1305
http://www.soundplusdesign.com/?cat=116
http://www.alimomeni.net/node/204
http://blog.soundsorange.net/2006/08/29/arduino-getting-the-usb-version-up-and-running-on-osx-using-pd/
http://ultranoise.es/blog/?p=213
Z materiału Arduino VS Max/MSP wynika, że najlepszym softem do zabawy będzie Maxduino. Zabawa może polegać na tym, że rozrysowujemy w aplikacji Max wykres działania / połączenia z systmem generatorem/syntezatorem dźwięku i uploadujemy program do naszej zabawki. Dodatkowe interfejsy mile widziane. Diody RGB, klawisze, czujniki natężenia światła i całą resztę można powiązać z syntezowaniem bitów, które sprawią, że na pozór cichy i bezduszny sprzęt nabierze niesamowitego wydźwięku i będzie w stanie nas zaskoczyć brzmieniem np: z gatunku ambient :-)
Oto kilka przykładów zrealizowanych pomysłów:
Materiały dodatkowe:
http://www.music.mcgill.ca/~gary/306/week5/serial.html
http://www.tigoe.net/pcomp/code/category/category/MaxMSP
http://www.flickr.com/photos/gudmundsson/3234647715/
http://www.soundplusdesign.com/?p=1305
http://www.soundplusdesign.com/?cat=116
http://www.alimomeni.net/node/204
http://blog.soundsorange.net/2006/08/29/arduino-getting-the-usb-version-up-and-running-on-osx-using-pd/
http://ultranoise.es/blog/?p=213
Subskrybuj:
Posty (Atom)