dinsdag 8 maart 2011

ScaleMM: fast scaling memory manager for Delphi

I released yesterday a beta version of ScaleMM: http://code.google.com/p/scalemm/.

Scaling!
This memory manager scales perfectly on multi core and multi cpu systems. I made this MM because FastMM does not scale at all!
ScaleMM scales perfectly on a quad core sytem (horizontal line from 1 till 4 threads, x-axis, slowly increases till 16 threads) but execution time (y-axis) of FastMM/D2010 doubles when 2 threads are used (and quadruples if 4 threads are used! etc).

ScaleMM2
I made 2 versions: the first version worked on top of FastMM (or other MM) and only handled small memory (<>1Mb). It take some time however to make this second version, because the medium memory handling was more difficult to make (split one block in dynamic pieces of different sizes).

Speed
The speed of ScaleMM versus FastMM is difficult to say: my own benchmark with mixed sizes and operations shows ScaleMM2 is 3x faster than FastMM/D2010, but in other benchmarks (allocs of same size, first alloc all then free all) ScaleMM2 turns out to be 50% slower than FastMM/D2010.
I hope I can find some time to do some more investigation (why it is much faster in one and slower in another test). Also an ASM optimized version would help of course :-).

Quality
The quality of ScaleMM2 seems good: I made some simple unit tests, and also ran the FastCode MM Benchmark (good and extensive stress test!). I made a lot of internal "CheckMem" procedures which checks for corruption etc. But I haven't done a real life production test yet...

Future
I have many ideas to improve and extend ScaleMM: detailed logging and statistics/usage (overhead, amount cached and over allocated, etc), "GC" thread (delayed release of freed memory, in case same memory is needed in e.g. the next for loop, background handling of interthread memory, etc), "Object Garbage Collection", etc.

However: my spare time is low! So if anyone can help me (or any company to hire/pay me :-) )...

Denomo: GDI handle leak check for Delphi

Last week I had to find an anoying GDI handle leak in one of the touch panel apps of my current customer. After some time it ran out of resources.

I started ProcesExplorer, double clicked on the touch panel process (so I could watch the number of GDI handles) and clicked through some screens of the application. I saw a growing GDI counter...

Next I placed some breakpoints and stepped through the code to find out where it came from. It took me quite some time, but I finally found it (of course: in a place I did not expect :-) a TBitmap was created for a button everytime but never released).

Next day, I got the same bug issue in another application. So I started thinking how to speed up finding these kind of leaks. I knew there was an application that could do it for me, but I could not find it back on internet. But after some googling I found a Delphi project: Denomo. It detours a number of Windows API's, like CreateBitmap, CreateBrush, etc and generates a list of unreleased handles and a stack trace per handle (where it was created) when you close your applicaiton.
However, it was not (unicode) compatible with Delphi 2010, and it needed a dll to run and a remote control app for the logging.

I made some small changes to make it compatible with Delphi 2010 (unicode, at least for the parts I needed) and made it standalone (no dll + remote control needed):
http://code.google.com/p/asmprofiler/source/browse/trunk/EXT/Denomo/
I also made a small demo/test project:
http://code.google.com/p/asmprofiler/source/browse/trunk/EXT/Denomo/gdileaktest/Project7.dpr

Now I can find GDI handle leaks very easy!

vrijdag 5 maart 2010

DxScene = WPF for Delphi

Een van de mooie onderdelen van .Net is WPF: hardware accelerated vector graphics. Ik zat eens te denken of zoiets ook niet mogelijk was voor Delphi. Er bestaat namelijk een open source project genaamd "GlScene": een 3D library voor OpenGL. Deze heeft echter beperkte (?) ondersteuning voor een normale GUI. Via via kwam ik bij "DxScene": deze heeft wel een uitgebreide set aan GUI controls! Hiermee kun je net als WPF mooie GUI's maken.

VxScene en DxScene, en Themes
Op de site staan een aantal onderdelen:

Het mooie is dat je deze eenvoudig kunt combineren. Zo kun je VxScene binnen DxScene gebruiken, bijvoorbeeld een 3d cubus met aan elke kant een invoerveld en een knop etc. Maar ook allerlei 3d effecten zijn mogelijk (transparancy, mirroring, particles(zoals vuur!), glow, etc). Een "cover flow" is bijvoorbeeld eenvoudig te maken:

Cover flow
Cover flow

Hardware accalerated vector graphics

Het voordeel van vector graphics is dat je deze eenvoudig kunt scalen (vergroten, verkleinen), zonder dat dit lelijk (blokkerig) wordt. Met DxScene/VxScene zijn deze ook nog eens hardware accalerated, zodat de CPU niet belast wordt! Ondanks allerlei effecten en transities in bijvoorbeeld de "cover flow" (demo exe) blijft de CPU 0%... Niet alleen video's kunnen met 3d effecten afgespeeld worden, ook flash animaties. Een andere mooie demo is bijvoorbeeld een combinatie van VxScene en DxScene, waarbij de GUI gedraaid en gescaled kan worden (demo exe):
3d GUI
3d GUI

Nog een mooi voorbeeld is deze applicatie die ermee gemaakt is: 3D Image Commander

Design time editor
In tegenstelling tot WPF kun je eenvoudig designtime WYSIWYG de GUI samenstellen. Niet zo RAD als je normaal met Delphi gewend bent, maar je hoeft in ieder geval niet zelf een XAML samen te stellen of via een externe tool als expression blend

Data Binding
Net als WPF kent het ook data binding: je kunt bijvoorbeeld de X-as rotatie koppelen aan een animatie component (lineair of een "path")

3d import
Omdat 3d objecten snel complex kunnen worden, is het handig om te weten dat je allerlei 3d formaten kunt importen: 3d studio max (.3ds), Half-life, Quake en Doom 3 models, maar ook SVG en en WPF Mesh models. Zie hier een demo exe.

Newton: physics engine
Nog leuker wordt het als je het combineert met een "physics engine", oftewel natuurkundige berekening! Een leuke demo hiervoor is de klassieker "Breakout" in 3d met bots berekeningen (demo exe):

3D Breakout met physics
3D Breakout met physics

Multi platform, OpenGl
Zoals de naam al doet vermoeden, gebruikt DxScene op Windows DirectX. Maar het is echter ook multi platform: je kunt met FPC ook native Linux en MacOS X executables maken! Het kan dus ook overweg met OpenGl. Daarnaast kun je ook voor softwarematige versnelling kiezen, maar dit is uiteraard wel CPU intensief en trager.

Commercieel
Enige nadeel is dat het commercieel is, al is 100 euro niet duur voor zoiets moois.

Links

Conclusie

Het is natuurlijk niet hetzelfde als WPF, maar je kunt er wel erg mooie dingen mee maken, die ook nog eens cross-platform zijn! En je hebt alles in 1 exe zitten: geen .Net 3.5 installatie oid nodig :-)

vrijdag 11 december 2009

"External exception C0000006" bij app op WLAN

Als je een applicatie maakt dat moet draaien via een WLAN (Wifi), pas dan even op en lees het onderstaande door:

Windows laadt namelijk niet de gehele executable in het geheugen, maar alleen wat hij op dat moment nodig heeft. Als je bijv. op een knop in je applicatie drukt, dan *kan* Windows een nieuw blok bitjes van je applicatie via het netwerk moeten ophalen (of voor een resource (bijv. een icon) bij een nieuw scherm dat je aanmaakt, etc).
Echter, als je via een WLAN werkt, dan kan natuurlijk net je verbinding weg zijn...
Wat er dan gebeurt? Een "External exception C0000006" :-(
Oplossing? Je moet een flag in je exe zetten, die aangeeft dat je vanaf een removeable medium werkt (USB, Wifi, etc) zodat Windows wel alles inlaadt. In Delphi kun je dit in de .dpr doen:
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}

Dit heeft bij mijn huidige klant nogal voor wat hoofdbrekens gezorgd: we kregen deze exceptions op de meest vreemde plaatsen, zonder aanwijsbare bug in de code. Na wat googlen was de oorzaak gauw gevonden en de fix snel gemaakt :-) Zie originele discussie + oplossing:

woensdag 9 december 2009

Windows tijd: in stapjes van 15ms!

Soms wordt je onaangenaam verrast: je meet de tijd van alle SQL queries in je programma met "MillisecondsBetween" en je krijgt als resultaat: 0, 0, 0, en 15ms...

Hmmm, dit is te mooi om waar te zijn, zo snel is MS SQL Server nou ook weer niet! :-)
Er ging bij mij toen wel een lampje branden, ik eens eerder zoiets gezien met "Sleep" en "GetTickCount".

Thread time slices
In Windows (en andere systemen) worden threads 1 voor 1 op een CPU uitgevoerd. Elke thread heeft een "time slice" van 15ms, waarin hij de volledige CPU tot zijn beschikking heeft. Na 15ms breekt Windows de thread af, slaat de inhoud van de CPU registers e.d. op, en laad en start een andere thread ("context switch"). Een "time slice" kun je afbreken door een wait function aan te roepen, zoals "Sleep", "WaitForSingleObject", etc. Op deze manier kan een andere thread de kostbare CPU tijd gebruiken.


Consequenties
De default time slice van 15ms heeft nogal wat consequenties voor het programmeren: zo gaat een "Sleep(1)" niet 1ms wachten, maar 10 - 15ms! (afhankelijk van andere threads etc). Maar ook andere tijd functies zoals "GetTickCount", "Now" (Delphi) of "GetLocalTime" (Windows) werken in stapjes van 15ms!

Nauwkeurige tijdmeting
Gelukkig zijn er andere manieren om het aantal ms te bepalen:
  • hardware timer gebruiken: met QueryPerformanceFrequency + QueryPerformanceCounter kun je met micro en nano secondes werken!
  • kortere "time slice" instellen met "timeBeginPeriod", bijv een time slice van 1ms met "timeBeginPeriod(1)". Dit heeft echter wel nadelen: veel meer context switches, dus meer overhead!
Zelf heb ik andere "Now" functie in Delphi geschreven, die op basis van QueryPerformanceCounter etc werkt (dan werkt alles in 1x op de ms nauwkeurig, of zelfs op de micro seconde).
Ik vervang ("detour") de oude "Now" functie door mijn "NowExact" door middel van "KOLDetours.pas":
OldNow := KOLDetours.InterceptCreate(@Now, @NowExact);
Anekdote
Ik heb eens bij een bedrijf de RS232 communicatie met een PLC flink versneld: in een loopje werd na elke ontvangen character een "Sleep(1)" aangeroepen. Dit heb ik met een factor 10 versneld door pas na een lege character een "Sleep(1)" te doen, en die door middel van "timeBeginPeriod(1)" ook echt 1ms wacht ipv 10 to 15ms!

vrijdag 23 oktober 2009

Gratis internetbellen!

Tegenwoordig begint internetbellen steeds meer in te komen: goedkoop bellen via internet. Dit in navolging van het succes van Skype op de PC: hiermee kun je gratis onderling bellen, en met soort prepaid kun je ook bellen naar vaste toestellen. Internetbellen is een soort Skype, maar dan met de gewone telefooon en zonder dat je een PC met headset nodig hebt :-). De meeste (alle?) providers hebben tegenwoordig wel een "Internet + bellen" abonnement, ook wel bekend als "SIP" en "Voip" (Voice over IP). Voor een vast bedrag per maand kun je dan gratis naar andere Voip gebruikers bellen (net als Skype) en met een goedkoper tarief naar gewone vast telefoon.

Problemen met Voip

Het is echter niet geheel zonder problemen! Van verschillende mensen hoor ik allerlei verhalen over: slechte bereikbaarheid, irritante echo, niet naar buiten kunnen bellen, bel die niet over gaat, etc. Zowieso ben je volledig afhankelijk van het internet: storing van ADSL of provider? Dan kun je niet bellen... (gelukkig gebeurt dit niet zo vaak, maar wel af en toe).
Daarnaast zit je vast aan een vrij duur abbo (minimaal 30 euro per maand) en moet je nog steeds per tik betalen.

Ik wil het ook...

Toen ik echter laatst de rekening van KPN (vaste telefoon) kreeg, ging ik toch wel even nadenken: dit is toch wel vrij duur voor dat beetje bellen van ons. Nu zou ik ook wel internetbellen willen, maar dan zonder de bovengenoemde problemen. In ieder geval wil ik mijn vaste lijn nog gewoon houden en niet afhankelijk zijn van een bepaalde provider.

Oplossing

Na wat zoeken kwam ik tot een hele mooie oplossing: een kastje van Linksys (SPA 3102, 60 euro) + een online Voip account (bijv. VoipBuster.com) (30 euro per jaar) = gratis bellen! Nou ja, helemaal gratis is 30 euro per jaar natuurlijk niet, maar het is een stuk goedkoper dan normale providers en je betaalt niet meer per tik (dus "gratis" :-) ).
Je sluit het kastje (bijv. Linksys SPA 3102) aan op het internet (bijv ADSL router) EN (!) op je vaste KPN telefoonlijn. Je normale telefoon sluit je uiteraard weer op het kastje aan. Je kunt nu gewoon gebeld worden via de vaste lijn, en als de stroom uitvalt, wordt automatisch overgeschakeld op de vaste lijn (je kunt dus ten alle tijde bellen en gebeld worden via de vaste lijn!). Vervolgens kun je via de webinterface van het kastje de accountgegevens van bijvoorbeeld VoipBuster.com invullen. Vanaf dat moment kun je met je normale telefoon via internet bellen! Daarnaast kun je nog dmv een "dialplan" instellen dat als je bijv. een # voor de telefoonnummer draait, hij via vaste telefoonlijn belt. De Linksys SPA 3102 heeft trouwens onnoemlijk veel instellingen! Je kunt bijvoorbeeld de voltage van de telefoonlijn, de frequentie van de kiestoon instellen etc etc etc. Gelukkig staat default de meeste instellingen gewoon goed :-). Voor een goede uitleg: zie deze handleiding.

Kortom: op deze manier kun je zelf je "internetbellen" c.q. "Voip" regelen, waarbij je onafhankelijk bent van een (duur) abbo bij een provider, en altijd kunt bellen en gebeld worden via de oude vertrouwde KPN telefoonlijn.

Opmerkingen

Zelf gebruik ik VoipDiscount.com (zelfde als VoipBuster maar dan andere tarieven...). Voor 10 euro prepaid kun je 120 dagen gratis bellen (Fair use policy: 300 minuten (5uur) per week). Dus met 3 * 10 euro kun je een heel jaar "gratis" bellen. Alleen naar vast (inclusief sommige buitenlanden) is gratis, naar mobiel is niet gratis (en daar verdienen ze weer op). Er zijn verschillende "betamax" klonen en andere providers: vergelijk eerst de tarieven en voorwaarden (bijv goedkoper bellen naar mobiel maar dan maar 90 ipv 120 "free days").
Van de 10 euro beltegoed heb ik voor 1 euro (!) een nederlands nummer aangevraagd (ander netnummer etc maar goed voor 1 euro mag je niet klagen). Dit is een normaal nummer waarop andere mensen mij ook kunnen bellen: hebben ze ook Voip dan bellen ze gratis (net als bij Skype). Oftewel: men kan mij bellen via 2 nummers: via voip en via kpn :-).
Je kunt ook helemaal overstappen op voip: bij oa Budgetphone.nl kun je je huidige KPN nummer laten overnemen voor 10 euro per jaar (per maand nog wel 10 euro linesharing aan KPN betalen ivm ADSL?).

maandag 7 september 2009

Delphi 2010, Coderage + SDN

Delphi 2010 released!

Vlak na de preview van Delphi 2010 (zie mijn vorige post), verscheen al de RTM versie en is het officieel released. Ondertussen zijn er verschillende interessante blogs verschenen, waarbij verschillende verbeteringen verder uitgelegd worden. Ik zal niet alle verbeteringen bespreken, maar een paar uitlichten. (P.S: zie ook de complete "reviewers" guide!)

Uitgebreide online wiki help (!)
Na de Delphi Prism Wiki is de hele RAD Studio via een mooie online wiki te doorzoeken. Bijvoorbeeld voor het complete overzicht van alle verbeteringen in de 2010 versie:

Voor een handig beginpunt:

Maar ook de complete Delphi Language Guide is beschikbaar, evenals bijvoorbeeld de VCL, etc.

Class constructors
Een mooie uitbreiding (wat nog niet zo nadrukkelijk genoemd is), is de ondersteuning van Class Constructors (net als .Net)

Een voorbeeld hoe je het kunt gebruiken:

RTTI (a la .Net reflection)
Verder is de RTTI sterk verbeterd, meer object georiënteerd zoals .Net Reflection werkt, zonder allerlei pointers, records, etc.

Class attributes
Zoals je ziet, zijn in D2010 verschillende .Net technieken verwerkt. Nu heeft Delphi ook ondersteuning voor class attributes:

TStopwatch
Nog een kleine maar handige uitbreiding is de TStopwacht, voor het meten van tijden (hoe lang een stuk code duurt etc):

Andere handigheidjes:

Datasnap (multitier):

IDE & Source Code:

DBX: Firebird + alle sourcecode (!)
Wat ik zelf erg mooi vind, is de native ondersteuning van de open source database Firebird (compatible (?) met Interbase). Maar ook dat de broncode van alle drivers meegeleverd wordt! Niet alleen van DBX, maar ook (eindelijk!) van Midas.dll (oa bekend van TClientdataset).

Extra's
De eerste extra functies en fixes van "andy" zijn al verschenen voor D2010:

TPL (Task Parallel Library) voor Delphi (!)

Laatst is er een interessante dotNed meeting geweest bij DTS/4DotNet over TPL voor .Net. Gelukkig bestaat voor Delphi zoiets dergelijks al een poosje:

CodeRage 4 & SDN Conference