netric.io - lightweight ASP.NET profiler

Over the last year on my spare time, I’ve been working on profiler for ASP.NET apps - netric.io. This small tool instruments methods from chosen assemblies and visualizes statistics of their execution times. It has got lower priority for me for a long time because of “Daj Się poznać” and other things but I think this project is worth to finally shed some light on it.

Right now, the tool does just one thing: for every HTTP request, it generates methods time visualization like this (click to enlarge):

Flamegraph

Before I go into more details, let me quickly introduce it with some short sample usage.

Profiling eCommerce application

Let’s say we have a site deployed on IIS, called NOP:

IIS configuration

I’m using nopCommerce here (open source e-commerce platform written in .NET stack) as an example of an e-commerce store. I have an instance with sample database, so we will have some real work to do here when the landing page is requested:

nopCommerce sample

Let’s try to profile it via netric. The application itself you can get from here. Download and unpack build.zip from the latest release. Once the package is downloaded, we need to install netric_x64.msi (it just registers profiler COM component and adds a bunch of entries in the registry) and then configure it by apm.exe, which can be found in downloaded zip. Two things are to be done:

  • Hook up profiling to NOP site by running following command:
$ apman -i NOP
  • Choose assemblies to be instrumented. There is no need to instrument all loaded assemblies at first, only those from our application, in this case, nopCommerce assemblies. All of them begin with “Nop.” prefix:

NOP assemblies

So we select them like this:

$ apman -asm Nop.*

That’s it. The last step is to reset IIS to apply changes above.

Now we can run netric.exe and then hit the landing page again. After a while, new “Flames” subfolder will be created under the path where netric.exe has been extracted. It is the place where all visualizations are saved. Once the request is completed, netric will add new SVG file with the interactive graph I showed you at the beginning.

How to read a flamegraph

Flamegraph will contain all methods (from Nop.* assemblies) called in a given request, which is marked here simply by URL in the chart title. In our case ,it is “/” which tells us it’s just a request for the home page or root. The easiest way to read the chart is from the bottom to the top: every level indicates (relative) stack depth which starts from the lowest part. So for example, during request execution when something called our custom attribute method, CustomerLastActivityAttribute.OnActionExecuting(), this method called CustomerService.UpdateCustomer() which called EfRepository'1.Update(). At the same time, we can quickly see that this is actually the slowest part because these 3 bars are the widest among all instrumented methods. This is the greatest benefit of visualizing execution time in this way - we can easily compare proportions of bars width in various places in the stack and assess which parts are time-consuming.

Flamegraph is interactive. Some methods will be quite fast, so they will be rendered as very small bars. If you want to examine some, just click on it and the graph will be zoomed to the selected part:

Zooming sample

Different colors don’t mean anything, they are just for readability. They could be leveraged of course in some way, for example for grouping similar methods, but it is not the case in the current version. Flamegraph charts have been invented by Brendan Greg and they are not limited to methods instrumentation. You can find more information on his site.

Why netric?

Basically, today we have several options when it comes to deal with measuring methods time:

  1. Standard profilers - dotTrace, ANTS profiler, Visual Studio. They are mature and developer friendly tools but they are not free and add overhead.
  2. Manual instrumentation with tools like Miniprofiler or some other DIY solution. This is a cheap way to log method execution but still you need to instrument them manually.
  3. Full featured APMs like AppDynamic or New Relic. They are great but costly and of course not comparable with such a simple tool like mine, however, instrumentation solution is pretty similar.

So netric is a kind of merge of those worlds: you can instrument methods of your choice with minimal overhead without the need of introducing changes in the code, for free. Like this, despite typical developer ad-hoc profiling it can be a part of automated performance tests on separate servers (which is the case in the place I work right now).

How it works

All the magic is done thanks to native ICorProfiler API. Netric contains COM component written in C++ that injects special IL code on the runtime which emits metrics through ETW to the agent, netric.exe. This is quite fast solution: the cost of sending metric of one method call was about 400 nanoseconds (yes), on average, on my desktop. Single agent can profile many sites on the same IIS, and of course, multiple requests can be run in parallel.

What’s next?

Ok, this is just the beginning. This is still a prototype and there is a lot of work with this tool. It needs a decent storage and web interface instead of simple SVG files. It would be nice to have better and more flexible configuration. I also have plans to add SQL execution times to flamegraph. But you can say it is already MVP, sort of:)

Source code is on github.

Writing D3.js apps in Purescript

I’m evaluating Purescript recently. It is a statically typed, pure functional language that compiles to Javascript as such it allows to create front-end stuff.

Why bother with yet another Javascript transpiler? Well, the reason is simple: because it’s almost Haskell. Despite a few differences like strict evaluation, writing objects in more JSON style, it has also higher kinded types, typeclasses and the same simple and elegant syntax as its predecessor. How awesome is that?

Application starter

So I’m going to rewrite some DSP charts to Purescript. Fortunately, there is no need to give up on D3.js as Purescript nicely integrates with existing libraries and there are D3.js bindings already. First off, I created application starter, very similar to that one I prepared initially for Javascript. The idea is the same: having small app stub already configured for browser auto-refresh every time source code changes. It actually contains also the same sample code, translated to PS. The project is in this repo. Just download, install npm and bower dependences, run gulp and that’s it.

You can check gulpfile.js to see how it is configured. I use Atom and it runs make step automatically on file save that’s why browserSync watches only for output changes to make a bundle. If you want to have whole build to be done automatically you may want to change watched file(s) to 'src/Main.purs' instead of 'output/Main/index.js' and change dependency for js-reload from bundle to build, so the bottom part of gulpfile.js should looks like this:

gulp.task('serve', ["build"], function() {
  browserSync({
    server: {
      baseDir: 'dist'
    }
  });
	gulp.watch(['dist/**/*.html'], {cwd: '.'}, browserSync.reload);
  gulp.watch(['src/Main.purs'], {cwd: '.'}, function(){
      return gulp.start('js-reload')
  });
});
gulp.task('js-reload', ["bundle"], browserSync.reload);
gulp.task("default", ["serve"]);

Statystyki dziesiątego tygodnia DSP

Jutro kończy się dziesiąty tydzień konkursu, a więc teoretycznie ostatni potrzebny do spełnienia warunków regulaminu, przy założeniu, że ktoś nie wziął sobie w międzyczasie “dziekanki”. A ja, tak jak obiecałem, znów powracam ze statystykami projektów i blogów Daj Się Poznać. Tym razem w nowej, ulepszonej odsłonie, którą opublikowałem tutaj.

Statistcs

Na stronie podzielonej na dwie części zebrałem informacje o blog postach oraz o tym, co działo się na GitHubie. Zasadniczo wykresy zdają się potwierdzać to, co było już trochę widać miesiąc temu, czyli trend spadkowy oraz niedzielne maratony. Na górnym wykresie można zawęzić przedział czasu, jaki nas interesuje, co spowoduje odświeżenie wszystkich liczników z uwzględnieniem tego zaznaczonego zakresu. Dzięki temu można prześledzić to, jak zmieniały się te wskaźniki tydzień po tygodniu.

Jeśli chodzi o statystyki blogów, to dotyczą one, jak poprzednio, wszystkich publikowanych postów, a nie tylko tych związanych z konkursem. Dane zostały zebrane w sobotę, 7 maja. Zaktualizuję je jeszcze raz po zakończeniu konkursu.

Jest to na razie pierwsza wersja strony statystyk DSP. W przyszłości chciałbym ją wzbogacić o analogiczne agregaty, jakie otrzymałem po pierwszym tygodniu oraz listy najbardziej aktywnych projektów/blogów, podobnej do tej z kwietniowego posta.

D3 i Crossfilter

Skrypt grafu przelicza jednocześnie cztery agregacje dla ponad 8 tysięcy elementów przy każdej zmianie zakresu dat. Gdy dodam jeszcze inne wykresy, czy tabelę z rankingiem oraz odświeżę dane na koniec konkursu, ilość liczb do skalkulowania jeszcze się zwiększy. Dobrą wydajność zapewnia tutaj map-reduce, na którym bazuje biblioteka crossfilter. Ta mała biblioteczka, w której macał palce również autor D3, Mike Bostock, stworzona jest z myślą o przetwarzaniu (stosunkowo) dużej ilości danych w przeglądarce. I jest w stanie “łyknąć” nawet więcej niż te 8k wierszy. Crossfilter i D3 pasują do siebie jak barbie i ken, to połączenie świetnie nadaje się przede wszystkim do tworzenia webowych dashboardów BI dla wielowymiarowych danych.

Skrypt wykresów można podejrzeć tu.

Sieć Twittera

Bazując na wcześniej pobranych kontach uczestników konkursu stworzyłem wykres prezentujący sieć połączeń na Twitterze. Wizualizację można zobaczyć na podstronie projektu dsp-meta, tutaj.

twitter network

Pokazane osoby podzielone są na dwie grupy. Pierwszą stanowi lista kont 73 uczestników konkursu, którą opublikowałem w tym tygodniu. Druga grupa, w prawej górnej części to osoby najczęściej przez nich obserwowane. Te popularne konta są posortowane według liczby obserwujących. Tak więc idąc od dołu, najwięcej obserwujących ma (nie ma zaskoczenia) konto Maćka, potem jest Gutek, Andrzej Krzywda itd.

Gdy najedziemy kursorem na daną nazwę użytkownika, podświetlają się jego połączenia. Czerwone linie prowadzą do obserwowanych przez nią kont, zielone wskazują na obserwujących. Fioletowy kolor wskazuje parę osób, które obserwują się wzajemnie.

Dane o obserwowanych użytkownikach pobrałem przez Twitter API i klienta w Pythonie. Opublikowałem je, jak zawsze, na GitHubie tu i tu. Kod grafu znajduje się w tym branchu.

Twitter DSP

Po krótkiej odskoczni, czyli budowania wykresów w D3.js, wracam ponownie do statystyk konkursu, a dokładnie danych z Tweetera. Tag #dajsiepoznac żyje i ma się dobrze, więc warto spróbować skorzystać i z tego źródła.

Pierwszym krokiem będzie znalezienie wszystkich kont uczestników na Twitterze. Na stronie konkursu są tylko podane adresy blogów i repozytoriów na GitHubie, więc trzeba znaleźć na to jakiś sposób. Zakładając, że aktywni uczestnicy tweetują opublikowane posty z tagiem #dajsiepoznac, moim pierwszym pomysłem było:

  1. Pobrać wszystkie tweety #dajsiepoznac
  2. Odfiltrować te, które nie są tweetami podanymi dalej.
  3. Pobrać linki z tweetów, ewentualnie rozwijając ich skrót z “http://ury.ty/erturwy” do rzeczywistego adresu.
  4. Jeśli link pasuje do adresu bloga, to autor tweeta prawie na pewno jest uczestnikiem konkursu.

Twitter API

Do pobrania szczegółów tweetów użyłem API Tweetera i jego klienta w Pythonie. API zwraca każdego tweeta w bardzo przystępnym formacie JSON, zwalniając użytkownika z parsowania hashtagów, linków i napomknień o użytkownikach (w nomenklaturze API te elementy są nazywane encjami). Problematyczne pozostaje pobranie WSZYSTKICH tweetów, ponieważ API szukajki indeksuje tweety za ostatnie 6-9 dni i nawet w tym przedziale nie gwarantuje zwrócenia każdego tweeta.

Rozwiązanie tego problemu było dość łopatologiczne. Jako że search zupełnie inaczej działa przez UI i na stronie wyszukanie po hashtagu zwraca poprawnie wszystkie wpisy, zwyczajnie zescrapowałem wszystkie tweety ze strony wyszukiwania i stworzyłem na tej podstawie listę ich identyfikatorów. Sposób prymitywny, ale skuteczny, bo pozwolił na pobranie tweetów od samego początku, nawet tych dotyczących poprzedniej edycji z 2010 roku i bez ryzyka pominięcia któregoś z nich. Mając identyfikatory, wystarczyło skorzystać metody API, lookup, aby pobrać resztę danych tweeta, w tym wyodrębnione z tekstu linki.

Na dzisiaj, tweetów z hashtagiem #dajsiepoznac dotyczących tylko drugiej edycji (tj. od daty ogłoszenia konkursu, 1 lutego 2016) jest 726. Dzięki nim udało mi się znaleźć 73 konta uczestników. Lista dostępna jest tutaj.

Ciąg dalszy nastąpi.