After only a short time here on Blogger, I have found a new home on the interwebs!
What better domain name to promote self-branding than my name!
http://www.patrickdelancy.com/
I will be migrating and redirecting my existing posts, so don't worry about looking for the content in two places (I know you were worried about it :-)
Facepalm Coding
"The only true wisdom consists in knowing that you know nothing." - Socrates / Bill S. Preston, Esq.
Tuesday, June 12, 2012
Thursday, June 7, 2012
St. Louis Day of .NET 2012
The blog is moving to a new domain. This post has found a new home: http://www.patrickdelancy.com/2012/06/st-louis-days-of-net-2012/
My topic is going to be centered around code anti-patterns. Why they are bad, how to identify them, and how to fix them.
Here is a deep link to my session page on the conference website: http://www.stlouisdayofdotnet.com/2012/sniffing-out-sucess-identifying-smells-and-anti-patterns-in-your-code
If you have a "favorite" anti-pattern, let me know! I might try and fit it into the presentation!
Hope to see you there!
Thursday, May 31, 2012
Critical Blocks and Improper Lock Objects
The blog is moving to a new domain. This post has found a new home: http://www.patrickdelancy.com/2012/05/critical-blocks-and-improper-lock-objects/
Quick catch-up... critical application blocks are blocks of code that can only be executed by one thread at a time. Stock example for illustration:
public static class SmackTracker { private static int smackCount = 0; private static object locker = new object(); public static void HitItAgain() { lock (locker) { smackCount++; } } }No matter how many threads call this method, the smackCount will only be incremented by one thread at a time, but this is not a post on the value and usage of thread locking...
What I want to cover is some common pitfalls people get into, sometimes without even realizing it. The resulting issues can sometimes manifest as phantom performance issues, inconsistent data corruption, intermittent memory exceptions and any number of other vague or elusive symptoms, like clammy hands.
Don't become a victim! When using sync objects, follow these simple rules...
- Don't use publicly accessible sync objects.
- Avoid using strings as lock objects.
Don't use publicly accessible sync objects.
The short explanation here is this... if the sync object is publicly accessible, it can be used (incorrectly or accidentally) for locking an external code block, resulting in potential deadlocks or other issues.
Historically it was common, even recommended, to use "this" or "typeof(MyType)" as your lock object. This is no longer recommended. Consider this example:
//Don't use public sync objects, and "this" is public! using System; using System.Threading; namespace FacepalmCoding { public class Program { public static void Main(string[] args) { DateTime start = DateTime.Now; Console.WriteLine("Starting worker threads..."); Person theMan = new Person("The Man"); Thread p2thread = new Thread(new ThreadStart(theMan.Operate)); p2thread.Start(); Thread.Sleep(10); lock (theMan) { theMan.OperateNoLock(); } p2thread.Join(); Console.WriteLine("This should have taken about 3 seconds in parallel, instead it took {0} seconds.", (DateTime.Now - start).TotalSeconds); Console.WriteLine("Done."); } } public class Person { private readonly string personId; public Person(string id) { personId = id; } public void Operate() { DateTime start = DateTime.Now; //use private instance string as sync object for this resource lock (this) { // ... do stuff that takes 3 seconds ... Thread.Sleep(3000); } Console.WriteLine("Person '{0}' operation took {1} seconds to complete.", personId, (DateTime.Now - start).TotalSeconds); } public void OperateNoLock() { DateTime start = DateTime.Now; // ... do stuff that takes 3 seconds ... Thread.Sleep(3000); Console.WriteLine("Person '{0}' operation took {1} seconds to complete (No Lock).", personId, (DateTime.Now - start).TotalSeconds); } } }
Starting worker thread... Person 'The Man' operation took 3.0108053 seconds to complete. Person 'The Man' operation took 3.0108053 seconds to complete (No Lock). This should have taken about 3 seconds in parallel, instead it took 6.0216106 seconds. Done.Click here to see it in action.
Note in this example, "theMan" is the same object reference as "this" internally. The result... an internal critical code block is locked in an external scope. This is bad!
Avoid using strings as lock objects.
In .NET and Java (and probably others), strings are public sync objects. The lock is identified by the string value, instead of the string object reference. This means that any string value (doesn't have to be string literal) can be used to as a sync key globally throughout the entire process, as if you were referencing a global object, no matter the scope of the string variable you are using. That may be hard to follow... here is an example...
//Do not use strings as thread lock/sync objects! using System; using System.Threading; namespace FacepalmCoding { public class Program { public static void Main(string[] args) { Console.WriteLine("Starting worker threads..."); Person firstPerson = new Person("first"); Person secondPerson = new Person("second"); Role firstRole = new Role("first"); Thread p1thread = new Thread(new ThreadStart(firstPerson.Operate)); Thread p2thread = new Thread(new ThreadStart(secondPerson.Operate)); Thread r1thread = new Thread(new ThreadStart(firstRole.Operate)); p1thread.Start(); p2thread.Start(); r1thread.Start(); p1thread.Join(); p2thread.Join(); r1thread.Join(); Console.WriteLine("Done."); } } public class Person { private readonly string personLocker = "lock object"; private readonly string personId; public Person(string id) { personId = id; //personLocker = id; } public void Operate() { DateTime start = DateTime.Now; //use private instance string as sync object for this resource lock (personLocker) { // ... do stuff that takes 3 seconds ... Thread.Sleep(3000); } Console.WriteLine("Person '{0}' operation took {1} seconds to complete.", personId, (DateTime.Now - start).TotalSeconds); } } public class Role { private readonly string roleLocker = "lock object"; private readonly string roleId; public Role(string id) { roleId = id; //roleLocker = id; } public void Operate() { DateTime start = DateTime.Now; //use different private string as sync object here //but since the string value is the same, will wait //for "personLocker" to be released! lock (roleLocker) { // ... do stuff that takes 3 seconds ... Thread.Sleep(3000); } Console.WriteLine("Role '{0}' operation took {1} seconds to complete.", roleId, (DateTime.Now - start).TotalSeconds); } } }
Starting worker threads... Person 'first' operation took 3.0108053 seconds to complete. Person 'second' operation took 6.0216106 seconds to complete. Role 'first' operation took 9.0324159 seconds to complete. Done.
Un-comment lines 40 and 62 and watch how the behavior changes.
Closing Thoughts
In case you forgot why any of this matters, I'll summarize it in a bullet list:
- Deadlocks and race conditions can be extremely difficult to diagnose and troubleshoot.
- Improper use of critical application blocks can cause deadlocks and race conditions.
- Widely-scoped sync objects can be accidentally abused.
- 'this', 'typeof' and any string value are all public sync objects.
Wednesday, May 23, 2012
Order of Operations in nested try..catch..finally
The blog is moving to a new domain. This post has found a new home: http://www.patrickdelancy.com/2012/05/order-of-operations-in-nested-try-catch-finally/
Everyone should be familiar with the standard try..catch..finally construct:
try { //this code will run only until an exception is thrown } catch { //this code will run only IF and exception is thrown } finally { //this code will run always AFTER the try and/or catch blocks have been executed }Here is a less common arrangement. When might this be appropriate to use?
try { try { } catch { } } finally { }Now let's look at some concrete examples. Consider this code snippet:
string output = ""; try { output += "A"; try { throw new InvalidOperationException("1"); output += "B"; } finally { output += "C"; } output += "D"; } catch (Exception e) { output += e.Message; } finally { output += "E"; } Console.WriteLine("Output: " + output);
Output: AC1EThere are two interesting points to note here: 1) the exception is raised to the outer try..catch. It is not suppressed by the nested try..finally, and 2) the nested finally block executes before the outer catch!
Now consider this code snippet:
string output = ""; try { output += "A"; try { throw new InvalidOperationException("1"); output += "B"; } finally { throw new InvalidOperationException("2"); output += "C"; } output += "D"; } catch (Exception e) { output += e.Message; } finally { output += "E"; } Console.WriteLine("Output: " + output);
Output: A2ELike the first example, the exception is raised to the outer try..catch, but the difference here is that the first exception is suppressed! Only exception "2" is captured! The short answer is do not throw exceptions from a catch or finally.
Wednesday, May 16, 2012
Exceptional Introduction
The blog is moving to a new domain. This post has found a new home: http://www.patrickdelancy.com/2012/05/exceptional-introduction/
Exceptions are Expensive, like Store Brand is Cheap
Maybe the best way to breach the topic of exception performance is to simply give you a short list of axioms that I believe to be true.
1. Exceptions are expensive
It has been proven many times that there is additional cost associated with constructing and throwing an exception. This seems to be exaggerated in managed applications (.NET, Java, etc.). That being said, this extra "cost" of constructing and throwing an exception would only be noticeable in time-critical real-time systems, or if they are used excessively. That brings me to my next axiom...
2. Exceptions should be just that... exceptions to normal operation
I firmly believe that when an application is running properly, there should ideally be no exceptions thrown... ever.
Don't start writing your flame comments yet! Notice the emphasized words in that statement. I completely understand that this situation is difficult if not impossible. We live in a corrupted world, and there is no such thing as a perfect developer, let alone a perfect application or system.
Building on this perception of errors, if you are returning success messages in an error or exception context, stop it! I recently worked on a system where an API call returned this message: <error code="$0000">Error: Completed successfully</error>
There are absolutely great reasons to write exceptions into your application... that brings us to my third axiom...
3. Exceptions can be used effectively to increase system stability and code maintainability
No, this is not a contradiction of my previous statements. Maybe the best way for me to tackle this section is to just give you a bullet list.
Good times to raise exceptions:
- Invalid parameters
- When validating input parameters to a function, constructing an exception can provide a lot of valuable information to help troubleshoot the problem. Possibly even informing the user so that they can correct the inputs and re-submit.
- Enforce code assumptions
- If you are building a library (for internal or external use), you should first of all document any assumptions you make about the objects coming from your factories or the objects you are acting upon. When it is feasible, test these assumptions and throw an exception so you can trace the source of the problem.
- External resources are unreachable or behave in an unexpected way
- This could be a database, 3rd party library, web service, etc.
- etc.
Bad times to raise exceptions:
- To return valid values to a calling function
- Use return values instead!
- On a timer, as a status update
- Code smells (indicator you are using this anti-pattern): You have a custom exception type called "StatusReport"
- Raise an event instead!
- etc.
Exceptions have been designed to capture details about errant behavior in an application. They contain a lot of valuable information that can help to troubleshoot everything from programming errors to network instability. That was a lot of background and build-up to get to the main point of this article...
Exceptions contain valuable information. Don't ignore them!
Following from my three axioms above, if an exception is raised, don't ignore it! An empty catch block is a common code smell. This particular code smell usually enters the code when you are working on something else, and an exception is preventing you from reaching the code you care about at that moment. So you slap in an empty catch to suppress the exception and get to your other code. This is like sticking a piece of gum on a leaky pipe and walking away."But what about expected errors in a 3rd party library?" Okay... so you are using a library that was written more poorly than your own code, and it raises an exception that can be safely ignored. What happens when that library gets updated, and that "safe to ignore" exception doesn't fire anymore, but a similar exception could be thrown which CANNOT be safely ignored? Now you are suppressing a valid exception that could result in bad behavior within your own application! In the very least, you should have some tracing or logging message that is generated when the exception occurs. I plan to address this more in an upcoming article about application logging and tracing. For now, we will leave it at that.
Friday, April 27, 2012
Troubleshooting Software In Production
The blog is moving to a new domain. This post has found a new home: http://www.patrickdelancy.com/2012/04/troubleshooting-software-in-production/
This is my first serious presentation for public consumption. Being such, I will continue to improve it as I get good feedback and as I think of ways to make it more accurate and informative. With that intent, I openly welcome your constructive feedback! Hit me up on G+, LinkedIn, or comment here!
Troubleshooting Software in Production
This topic is amazingly large. In my presentation, I try to give a good foundation that can be used as a starting point for building up your own skills in this area. If you missed my presentation, or if you want to watch it again, here are the links. The presentation is pretty minimal, so you will not get very much information just watching the slideshow. All of the "good stuff" is in the speaker notes.
- Presentation (Prezi / Flash-based)
- Speaker Notes (Google Docs)
Watch the presentation, read the speaker notes, give me feedback. What did you like? What did you learn? What did I miss? What do you disagree with? Hit me up on G+, Twitter or comment below!
Tuesday, April 10, 2012
KC Developer Conference 2012
The blog is moving to a new domain. This post has found a new home: http://www.patrickdelancy.com/2012/04/kc-developer-conference-2012/
Needless to say, this is a HUGE topic! There really is too much information to fit into a single hour. Since there is so much good stuff to talk about, and so many things that people misunderstand or routinely do wrong, I will be publishing a series of articles that delve deeper into this topic.
Don't think that is an excuse not to attend!
My presentation at the conference will try to give a solid overview of troubleshooting your software in a production environment and propose some practices and tricks to make it easier. As time allows, we will then talk about some specific tools and types of tools to get the job done. I am structuring my presentation deliberately to incite conversation with those in attendance. If you aren't there, you will certainly miss out on a lot of valuable discussion that will not make it into the slides.
I hope to see you there!
Labels:
Conferences,
KCDC,
KCDC12,
Schedule
Subscribe to:
Posts (Atom)