Friday, May 29, 2009

Better smart-linking through class construction

Singletons, global services, and initialization. Most Delphi folks (myself included) don't really think about the impact of these things on how much code is being linked into their application. How many of you have your own stable of utility functions scattered throughout some number of units? You rely on these things everyday and would tend to feel naked without them. Even when you bang out that little test or utility app, those units are the first thing that goes into your uses clause. Have you ever stopped to think what impact they may be having the size of your little app? Long time Turbo Pascal and Delphi programmers have always taken for granted the smart-linker and its ability to ensure that only the code that was "touched" is what is actually linked into your final application. However, there are a lot of things we unwittingly do that can undermine the linker's "smartness." Try this little experiment; create a new console application, add all your favorite utility units to the uses clause and compile,  making sure building with packages is off. Now look at the size of your resulting executable. OMG! It does nothing, yet it is > xxxxK! Let's look at something we're working on to help you (and us) out.

As was mentioned at Delphi Live! several weeks ago, we're currently working on adding what we're calling "Mouse/Touch Gesture support" to VCL. This will eventually evolve into full multi-touch as the OS services and hardware becomes available. Initially we've been building our own "gesturing engine" and adding it throughout the VCL. From the outset, we knew that baking this support into the core of VCL was going to be key to its acceptance. At the same time we also know that there are many of you that don't need or want all that extra code slathered throughout core VCL. We also wanted to make sure this new gesturing support was "pluggable" at many levels. I'm not going to cover details about how this whole subsystem works, but simply want to use it as an example of something else we're looking at adding to the Delphi language.

Traditionally, if you had some set of classes that required some kind of global initialization or a class that was a singleton, you would place this startup code into the unit initialization section. Unfortunately, this has the side effect of dragging into the resulting binary all code and data that is directly and indirectly touched by the initialization code. Simply "using" the unit will drag in the code. Sometimes that is what you want, but what if all you wanted to do was use some other class or call some disconnected utility function within that unit? You have to pay the size and startup performance costs associated with initializing classes and data that you never even use in your own code.

Over the years, there are some "tricks" we've all played to try to get around this. The most common is in the case of singletons, where we "hide" the singleton instance behind a global function that will initialize the instance when it is first called. The problem is that everyplace you use the singleton, you incur a function call. Other tricks include injecting into each public method of an object, code that calls a helper method that does the global initialization. This also has the side-effect of incurring this call for each method. The interesting thing is that the compiler already has mechanisms in place to figure whether or not you're "touching" a given class or not. Why not just trigger on that and call an initialization method, if and only if that class is referenced someplace in code your. This really means whether or not the reference graph can trace all the way back to the main program block.

Enter class constructors. We're talking native Delphi here. Delphi for .NET and Delphi Prism have had class constructors all along since that is a concept that is baked into the .NET Common Language Runtime (CLR). However, there has never been the equivalent concept in Delphi for Win32. We're looking at fixing that. What if the following simple singleton pattern were possible?

unit SingletonUnit;

interface

type
TSingleton = class
private
class var FSingle: TSingleton;
class constructor Create;
public
procedure DoSomething;
class property Instance: TSingleton read FSingle;
end;

implementation

class constructor TSingleton.Create;
begin
FSingle := TSingleton.Create;
end;

procedure TSingleton.DoSomething;
begin
end;

end.

Now you can simply access the singleton by TSingleton.Instance.DoSomething; Because of the class constructor, the compiler will ensure that it is called long before you actually call "DoSomething" on the Instance class property. The astute among you have probably already spotted the hole in the above case. There's a memory leak now. How is the FSingle field destroyed? This is where the non-garbage-collected world of native Delphi has to do a little more work. The class destructor is how this will be handled.


  private
class var FSingle: TSingleton;
class constructor Create;
class destructor Destroy;
public
...
class destructor TSingleton.Destroy;
begin
FSingle.Free;
end;

Now let's look a little at how this all works. Class constructors (or type initializers) differ from instance constructors in that it is execute before any methods can be called or instances of the class constructed. The only rule is that it needs to run before anything else. How long before is largely irrelevant. Unlike class constructors in .NET, you cannot explicitly call them in Delphi Win32.  For Delphi Win32, class constructors are called in a manner similar to unit initialization. The difference is that the compiler treats them as a "weak reference." The class constructor is only explicitly called if other code references the class. Class constructors are called prior to the unit initialization getting called for the unit in which the class with the class constructor resides. If one class constructor references another class with a class constructor in the same unit, the compiler attempts to order the constructor calls such that deepest reference is called first. Beware of cycles! If you have several classes with class constructors within the same unit and they all refer to one-another, the ordering may be indeterminate and you may end up with strange results or even crashes. So be careful before you decide to add them to that huge morass of spaghetti code you inherited from your predecessor. For class destructors, they are called in the exact reverse order of the class constructors and are called after a given unit's finalization section is executed.


Back to the gesture engine. How does this all relate? When you drop a TGestureManager component onto a form, the designer/code manager adds an instance field of type TGesureManager to the designed form class. There is also a reference to the unit in which that component is declared added to the uses clause. The mere addition of the unit to the uses clause isn't what causes the gesture engine to be initialized, it is the component reference on the form itself that does this. If you removed the component from the form and the reference is deleted and left the uses clause reference, all that would be linked in would be a stub initialization/finalization from the given unit.


I'm already seeing several places throughout the Delphi RTL and VCL that would benefit from this. What if you wanted to use function from SysUtils, but did not want to incur the extra weight of full exception support? We may add a class constructor to the base Exception class that hook up the proper functions in System. There are probably many more places in the RTL and VCL that could be refactored in this manner. Of course we need to be cognizant of the fact that going too far may introduce strange ordering differences and could make some things behave badly or radically different. While this isn't some kind of magical "incredible shrinking machine," it is another tool that can be easily leveraged as we are adding and improving the VCL libraries. We will be able to add significant functionality without grossly impacting the minimum core set of code.

Tuesday, May 19, 2009

Yes, Virginia, there is a Delphi MacOSX and Linux project...

I guess the proverbial cat is now out of the bag. As was shown in the Delphi/C++Builder roadmap at Delphi Live!, Project X has been under way for a while now. So now you know some of the reason why things have been rather quiet here since I could not really talk about what I'm working on. The good news is that we now have a returning top-shelf engineer working on the compiler. This person was heavily involved with the original Delphi on Linux project, so there is a lot of institutional knowledge that he's able to bring to the table. Things are going to be done

Another noteworthy item is that the information in the roadmap was more about future technology rather than specific releases. In fact, for the first time in nearly as long as I can remember, we literally have several parallel efforts going on. Unlike the previous Delphi on Linux era where the teams were bounced back and forth between the Windows and Linux projects, we're keeping a smaller, more focused team engaged on "future" work with minimal distractions. Of course the "next" product release will always engage the majority of the team, but having several "background threads" of development adds a truly exciting dynamic to the team.

So if you're at all interested in some tidbits of information about the technology behind Project X and some interesting insight into a lot of the really low-level bit-twiddley aspects of the Delphi compiler and how it integrates with a new platform (and even an "old" platform like Linux) you really must check out Eli Boling's new blog. In fact, he's already starting posting some pretty gnarly stuff about some of the more goofy aspects of the Mac OS. Oh, and if you know the definitive answer to this question on Stack Overflow, please post it there.

So strap in, hang on, it's going to be an interesting ride :-).

Wednesday, May 13, 2009

Delphi Live! Here I Come

As always, I'm just now completing the slides and demos for my Delphi Live! talk. That is about par for the course... So bright and early tomorrow morning, I'll be driving past my normal exit and heading on over the Santa Cruz Mountains to downtown San Jose. Hopefully traffic will allow me to get there in plenty of time to get to the Opening Keynote on time. I've been following some of the Twitter traffic for the pre-conference sessions. So far it looks like the response has been very positive. Tomorrow evening is the "Bea^H^H^HMeet the Team" session and hope to meet many of the attendees. If you're coming to Delphi Live!... see ya there!

Friday, May 1, 2009

Product Leadership Team, Research, Weaver, Delphi Live! - Oh my!

First of all I must apologize profusely for the dearth of posts here over the last few months. OK, "dearth" in this case would unfortunately, be an overstatement since the last thing I posted here was right after the Microsoft Professional Developers Conference. While I do have explanations for this silence, I don't view them as excuses. Excuses are something that one does to deflect responsibility and blame off themselves. So I make no excuses and take full responsibility for the decided lack of posting I've done over the last few months. Certainly, some of the reasons for remaining silent here can be attributed to major distractions and that I could not talk about the stuff I've been working on. Other reasons are far less interesting and boil down to pure laziness and lack of motivation on my part. The good new is I now do have some stuff to talk about and the motivation to do has finally come back :-) Let's get started... again.

 

Product Leadership Team

Last fall, Embarcadero formed a special team that meets periodically to discuss all kinds of things about the products, their direction, markets, technology, etc... Another charter for this team is to identify technologies and market trends and to think of ways we can either leverage, drive and or otherwise participate in any of these emerging trends or markets. Or not. Deciding to not pursue a market or trend is just as valid of an outcome as deciding to do something. I'm able to be involved with this team that includes our CTO, James Pitts and our VP of Products, Michael Swindell, and at times Wayne Williams, the EMBT CEO. There are also a couple of other very senior engineers on this team with whom we can really do deep dives into technology and ideas.

Late last year, the PLT commissioned some research and even some preliminary development on some new product directions. Myself and a couple of other senior engineers have been off feverishly toiling away at this. It is this work I've been doing over the last few months that I've been unable to really talk about. There are two main reasons for remaining silent. First of all, as with any research project, it could be cancelled or shelved at any time. We don't want to talk too much about something that, while exciting, may never come to fruition. Secondly, what I talk about early into the research may have zero or nearly zero bearing on the final outcome. The good news is that it is very likely that some sneak peaks will be coming at the Delphi Live! conference in San Jose, CA. So, if you haven't signed up yet, now is the time.

 

Weaver

Hopefully by now you've heard about the next major RAD Studio release, code-named Weaver. You can even apply to field-test this new version here. If you want to see what coming in the next release and feel you have some valuable feedback, make your case and apply to participate by clicking on the above link (posting a comment here won't work). Again, if you're coming to Delphi Live! there is certain to be some information and demos with Weaver.

 

Delphi Live!

In case you haven't guessed, a common theme throughout this post is to stress the importance of attending the first face-to-face Delphi and C++Builder centric conference and the first major conference with Delphi content in over 4 years since the last Borland Conference. I will be there doing a talk on a lot of the newer designer features that have been introduced over the last 4 or 5 Delphi releases. I'll cover things like guidelines, property filters, and maybe even some new stuff coming in Weaver. I'll also be helping out with the Product Address and any "What's Cooking in the Labs?" discussions. There will also be a meet-the-team session where you can come meet nearly the entire RAD Studio development team and get your chance to corner one of us to discuss your favorite product feature or even the lack thereof :-). I'll see you all there!