|
Personal Info:
Joe  leads the architecture of an experimental OS's developer platform, where
he is also chief architect of its programming language. His current mission is to enable
writing large-scale software that is reliable, secure, and scalable by-construction. Before this, Joe
founded the Parallel Extensions to .NET project.
He has been granted 19 patents, with 49 pending. When not working, Joe enjoys travelling with his wife,
writing books, writing music,
studying music theory & mathematics, and doing anything involving food & wine.
My books
My music
Disclaimer:
The content of this site are my own personal opinions and do
not represent my employer's view in anyway.
© 2012, Joe Duffy
|
|
 Saturday, August 14, 2004
340hp. 4.2L V8. German engineered.

I love it. And yes, I enjoy frivolous, wallet draining toys.
Breaking changes are typically thought of as modifications which alter a public API's surface area. For example, changing a method name from Foo() to Bar(), or otherwise changing it's signature, such as adding a required parameter. Anything else is simply implementation fodder, subject to change as more efficient and/or appropriate means to compute the same result become available, yes?
Well, not exactly. There are some subtleties. Depending on your perspective, implicit semantic constraints - such as pre- and post-conditions - would likely break existing code if altered behind a client's back. These are slightly less tangible to understand in this context due to the lack of a standard static representation of such notions in mainstream .NET languages. This subtlety is also prevalent with structured exception handling. Consider the following example.
Say there’s a public API defined as such:
public void DoThrowingOperation()
{
throw new CheckExceptionA("Test");
}
And a client comes along, decides the API’s useful enough to take a dependency on (what, you say, that method's not very useful? bahhh), and adds code which uses it:
public void DoCheck()
{
CheckDepends cd = new CheckDepends();
try
{
cd.DoThrowingOperation();
}
catch (CheckExceptionA e)
{
Console.WriteLine("Caught exception: " + e);
}
}
Well, it's entirely reasonable for them to expect that catching CheckExceptionA is sufficient to recover from specific exceptions occurring from their invocation to DoThrowingOperation(). That is, the only way an exception could leak outside of this method is for a critical system error to occur, or perhaps other exceptions coming from code upon which the public API depends. This is an extremely naive viewpoint, and an obvious reason that clients should properly factor their exception handling code to be resilient against the scenario I describe (e.g. liberal use of finally clauses).
What if the public API changes its implementation vis-à-vis exception throwing patterns? No verification errors here, the API surface area remains the same:
public void DoThrowingOperation()
{
Random r = new Random(0, 1);
if (r.Next() == 0)
throw new CheckExceptionB("Ha ha");
else
throw new CheckExceptionC("You are broken");
}
The implementers of the old DoThrowingOperation() thought it made more sense to refactor their exception hierarchy, specifically to separate the errors thrown into two more descriptive classes. Unless these new exceptions derive from the old one (enabling polymorphic catching), however, any clients could be in for a surprise if the new API version is deployed and bound at runtime. The client’s catch clause will never fire now, and in fact any of the new exceptions thrown from this method will propagate freely up the caller’s stack. Boom:
Unhandled Exception: CheckExceptionB: Ha ha at CheckDepends.DoThrowingOperation() at CheckTest.DoCheck() at CheckTest.Main(String[] args)
One could easily rationalize this problem as a result of C#’s lack of checked exceptions. And, of course, one would be wrong in doing so. Checked exceptions, at least in Java’s implementation, are nothing but a compiler trick. Constraints as rich as those necessary to enforce call graph exception checking are much too expensive to verify at runtime, and as such the situation is the same in Java.
For example, this API:
public void DoThrowingOperation() throws CheckExceptionA
{
throw new CheckExceptionA("Test");
}
And this client code:
public void DoCheck()
{
CheckDepends cd = new CheckDepends();
try
{
cd.DoThrowingOperation();
}
catch (CheckExceptionA e)
{
System.out.println("Caught exception: " + e);
}
}
Wouldn’t play very nicely if the API were altered slightly, even though the API's static throws information has been changed correctly:
public void DoThrowingOperation() throws CheckExceptionB, CheckExceptionC
{
if (Math.random() < 0.5)
throw new CheckExceptionB("Ha ha");
else
throw new CheckExceptionC("You're broken");
}
At least in the case of Java, the compiler would catch this problem the next time the client recompiles. With C#, the problem could be a bit more difficult and labor intensive to track down (since there’s no easy way to detect this statically or even report on what exceptions a given API could possibly throw, a la JavaDocs). Both would likely result in nasty runtime bugs, however. I’d love to see a feature in Reflector (well, a VS MDA would be even better) which computes the possible exceptions a method invocation could leak. This is a bit tricky because a deep call graph traversal needs to occur, but I’d even take a list of exceptions thrown directly by the method in question.
 Friday, August 13, 2004
Those perf architects are seldom wrong. For instance, when they recommend that you provide an explicit override implementation of the Equals(object) method for your value types, it'd be wise to listen. Unless you intend to never compare your instances for memberwise equivallence, that is.
In fact, not heeding this particular advice causes your value types to fall back to the System.ValueType implementation of Equals(). ValueType.Equals() takes an object parameter, causing value types to box as they're handed off to this method, and also uses reflection to determine memberwise equivallence. Needless to say, it's not overly performant for uses within loops, or other code with high performance requirements.
Specifically, the core of this implementation looks something like this (see here for the full Rotor implementation):
public override bool Equals (Object obj) {
// ...
FieldInfo[] thisFields = thisType.InternalGetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, false);
for (int i=0; i<thisFields.Length; i++) {
thisResult = ((RuntimeFieldInfo)thisFields[i]).InternalGetValue(thisObj,false);
thatResult = ((RuntimeFieldInfo)thisFields[i]).InternalGetValue(obj, false);
if (thisResult == null) {
if (thatResult != null)
return false;
}
else
if (!thisResult.Equals(thatResult)) {
return false;
}
}
return true;
}
I wrote a test harness (full code available here) to test out the performance impact that this has. As with most hack perf harnesses, the exact results should be taken with a huge rock of salt. However, the deltas are significant enough that I felt compelled to post this entry.
My value type looks like this:
struct ValueTypeA
{
private string a;
public string A
{
get { return a; }
set { a = value; }
}
private DateTime b;
public DateTime B
{
get { return b; }
set { b = value; }
}
private int c;
public int C
{
get { return c; }
set { c = value; }
}
}
...And my main loop looks like this:
[MethodImpl(MethodImplOptions.NoInlining)]
void DoDefaultEquals(Array a)
{
ValueTypeA[] aa = (ValueTypeA[])a;
for (int i = 1; i < aa.Length; i++)
for (int j = 0; j < i; j++)
aa[i].Equals(aa[j]);
}
Admittedly, this is a very contrived, comparison-intensive example. Nonetheless, let's consider the default implementation as our baseline, that is 1.0 or 100%; the other numbers will be scaled appropriately to make comparing results less arbitrary (e.g. scenario 1 took 37,151 milliseconds to run, etc.).
So, what if we explicitly override Equals(object) in our value type?
public override bool Equals(object o)
{
if (o is ValueTypeA)
{
ValueTypeA v = (ValueTypeA)o;
return A == v.A && B == v.B && C == v.C;
}
else
{
return false;
}
}
This actually comes in way under the default implementation. In fact, on my computer it took on average about 10.5% (0.105) of the time the original scenario took to execute! Pretty darn good!
But we can still improve slightly, as the above implementation requires the value types are boxed before being passed to the implementation.
public override bool Equals(object o)
{
if (o is ValueTypeA)
return Equals((ValueTypeA)o);
else
return false;
}
public bool Equals(ValueTypeA v)
{
return A == v.A && B == v.B && C == v.C;
}
This one comes in at 6.5% (0.065) of the original implementation's execution time.
So just for summary, these are the comparative results I got on my machine:
Default ValueType.Equals(): 100% Equals() Override (w/ boxing): 10.5% Equals() Override (w/out boxing): 6.5%
For yucks, I tried a loop which used Array.IndexOf() to look up value types stored in an array.
[MethodImpl(MethodImplOptions.NoInlining)]
void DoFind(Array a)
{
for (int j = 0; j < 100; j++)
{
ValueTypeA[] aa = (ValueTypeA[])a;
for (int i = 0; i < aa.Length; i++)
Array.IndexOf(aa, aa[i]);
}
}
I received similar results:
Default ValueType.Equals(): 100% Equals() Override (w/ boxing): 28.5% Equals() Override (w/out boxing): 27%
These difference in performance here is fairly substantial. The take away is not specific figures, but rather that overall a custom implementation of Equals makes sense if you expect your value types to be compared for equivallence.
Truthfully, I'm surprised that the C# compiler doesn't optimize for this. One could imagine the compiler detecting the absence of an Equals override, triggering an injection of a simple, brainless memberwise comparison. I'm sure there are plenty of reasons not to do this (premature optimization comes to mind, that is adding stuff that'd bloat the metadata... stuff that might not even be required), but this is painful, boilerplate code that complicates the maintenance of value types. Sufficient justification to me.
 Monday, August 09, 2004
I'm in the process of reading the following books, all of which tickle me in a special way,
 |
Game Physics by David H. Eberly
This book is unfortunately primarily a refresher course in high school physics, perhaps university level, but there are a couple sections which make this one a keeper. I'd recommend it for reference, not something with which you'd want to curl up in front of the fireplace. |
While I didn't read the following book cover to cover, I did read through about 50% of the material over the weekend.
 |
Threat Modeling by Frank Swiderski, Window Snyder
Written by a couple of my fellow Microsofties, this book details the threat modeling process in great detail. It's definitely a process book, and as such makes a few assumptions I would prefer to steer away from (e.g. lack of quantitative data showing why the investment in threat modeling is a Good Thing(tm)). That said, there is a lot of good material here. |
So many books left to read, so little time.
 Saturday, August 07, 2004
I'm not sure why, but that frightening Playskool doll from the 80s and its accompanying theme song (which sends chills down my spine when I reminisce about it, I might add) popped into my head when contemplating this post. I'm sure that little invention is to blame for many a child's nightmares... Anywho, on to the real content. Right-o.
When I saw BradA's post about the ISV Buddy program back in early July, I ran right out and signed up immediately. I decided only to sign up for 1 right now, as I was hesistant to overcommit on bandwidth...
Well, I just received information about my newly assigned buddy today! The whole concept is really cool - that is, hooking up an ISV professional working “down in the trenches” with a Microsoft professional also “down in the trenches.” It's a bit like a penpal thing, but with perhaps more structure and concrete goals. I'm looking forward to it.
(By the way, when I first arrived at MS, I was a little concerned and confused when I saw posters depicting Sanjay Parthasarathy and Eric Rudder (two MS execs) as bobbleheads, accompanied by the phrase “He's not kooky, he's my buddy.“ littering the walls. It all made sense as soon as I read Brad's post... To the poster designers' credit, they did include a URL at which one could read more information on the program. I suppose the ever increasing proliferation of sticky notes with colorful comments by other employees that decorated each poster diverted my attention enough that I never thought to go read more about it. This video shows the animated version of the poster. :) )
If you're unfamiliar with the program, I recommend you check it out. |
 Monday, August 02, 2004
I've received a bit of feedback on my Microsoft Vocab Part I post.
In particular, I have learned
- From Adam, there is a surprisingly complete and up-to-date reference available that dates back to the late 90's. Not much has changed.
- Microsoft employees like to cling to old product names, even when referring to replacement products. In particular, Eric pointed out that S+ stands for the old pre-Outlook Schedule+ application, and that people still use the name Raid when referring to its successor, Product Studio.
- My grasp on real vocabulary is embarrassing. Evidently the term “vet“ is a real word, and I didn't even know - or think to double check. Glad I didn't have to pass a vocab test to get hired... ;)
I'm aware there's a problem adding comments at the moment (i.e. they don't show up at all)... Please continue adding them. I am still receiving the email notifications with the full details.
I'll fix this tonight and will manually add the backlog of comments once it's functional again.
Update: They're baaaack... I guess that's what happens when you upload a couple rounds of digital images (400+MB), forgetting that only a limited quota of space is available for the taking. Duhhh...
 Thursday, July 29, 2004
 Wednesday, July 28, 2004
These people are nuts (I'm including myself in this broad categorization, too, btw). Microsofties definitely utilize a different vocabulary than normal human beings. Sometimes this entails noun-izing verbs, mutating existing words, or even just plain making stuff up. I've noticed that I'm now incorporating nearly all of these into my daily speech, so before I've completely conformed I wanted to document the odd experience of being subjected to it all...
Here's a brief guide to the top ones I've encountered thus far:
ask noun A requirement or request that something happen. Example: The Speedo team has an ask that we add red dancing baboons to our product's splash screen. Example: What are the Speedo team's asks?
bar noun A dichotomy in which a set of criteria defines a categorization status of below/above. Things which fall below the bar are considered to be necessary to address, while things above the bar are not (most likely temporarily). The bar is subject to move up and down at will. Example: We have a defined a bar for the Super Soaker 5000's release criteria.
blocked verb Prevented from making progress due to a dependency on someone or something else. Example: Are you blocked on getting feedback from Henry?
bits noun Software. Example: The Whidbey Beta1 bits are now available on MSDN.
drop noun A release of software intended for a specific purpose. Example: We should expect the next product drop in May.
feature-complete adjective A product state in which all features have been completed, albeit not completely stabilized and tested. Example: As of September 12th, you must be feature-complete.
Franken-build noun A conglomoration of unfinished software components which evidently function together, although the steps are typically Black Magic to reproduce. Example: Hey, could you send me some reproducable steps to get a Franken-build of System.Collections, JIT hotspot inlining, and tuned GC working together?
needs noun The set of asks that a particular entity needs. This implies they are not full of shit. (See also: wants.) Example: We should address team ZoomZoom's needs in our next status meeting.
own verb If you screw it up, your head is on the chopping block. Example: Joe owns this initiative.
triage verb The act of taking a set of things, comparing it to a defined bar, and assigning a status to those things - i.e. above or below. noun An effort to perform triaging against a large set of items. Example: We triaged our feature requests against the minbar, and came up with this set of items which need completion by the end of today.
S+ (or Sched+) noun An Outlook meeting request. Example: S+ me w/ the details.
scrub verb When some set of things are reviewed to ensure that they are up-to-date, and if not updated to reflect the current state of affairs. noun A large-scale effort to perform scrubbing against a large set of items. Example: By scrubbing our database, we were able to close out 90% of the issues.
vett verb Finalizing, discussing, and agreeing on a common outcome. Example: Have you vetted the design yet?
wants noun The set of asks that a particular entity wants. This carries with it a connotation of not believing that the entity actually requires them, but rather that they are nice-to-haves. Example: Do we have a good handle on team ZoomZoom's wants?
 Friday, July 23, 2004
My primary machine at work has two partitions. One hosts WinXP, the other Windows Longhorn.
The cool thing about this randomness is that I haven't even booted into WinXP for about a week, and have been using Longhorn as my primary OS for the past three weeks. This includes development with Whidbey, Office-stuff, blog reading, surfing, etc., etc.
I'd be lying if I said I have had absolutely no problems, but considering the early state of the product and amount of functionality I've received as a result of the switch, I'm extremely happy. And I will come forth and say that I haven't had a single crash. Zero.
I'd cry if I didn't have my little analog clock and gray minibar any longer. Never looking back. ;)
|
|
Recent Entries:
Search:
Browse by Date:
Browse by Category:
Notables:
|