Saturday, July 21, 2007

Performance Implications on Collections

When you want additions, removals, and lookups to be very quick, and when you are not concerned about the order of the items in the collections, your first inclination should be to use a System.Collections.Generic.Dictionary.

On the other hand, with a List, inserting and removing items can take a variable amount of time. (List stores items in an underlying array that maintains order. If your usage pattern requires few deletions and mostly additions, and if it is important for you to keep the collection in order, you may still want to choose a List.

Using the new LinkedList collection can potentially help you improve performance in scenarios where you need to maintain order yet still achieve fast inserts. Unlike List, LinkedList is implemented as a chain of dynamically allocated objects. In comparison to List, inserting an object in the middle only requires updating two connections and adding the new item. The downside of a linked list from a performance point of view is increased activity by the garbage collector as it has to traverse the entire list to make sure objects were not disposed of. Additionally, performance problems can arise with large linked lists due to the overhead associated with each node as well as where in memory each node lives.

SortedDictionary, uses a balanced tree implementation as the underlying data store; this provides relatively fast lookups and maintains items in a sorted order, but insertions will most likely be slower.

From CLR Inside Out: Collections Best Practices by Inbar Gazit.

Generic Counterparts to Non-Generic Collections

Sunday, July 08, 2007

Separating Administrative Events and Operational, Analytical, or Trace/Debug Messages

If there's one thing an IT pro really hates, it's an application that makes a lot of noise in the application event log, drowning out the really important messages that well-behaved applications produce from time to time. You shouldn't be writing operational, analytical, or trace/debug messages to the application log! These are more appropriate for a custom application log.

From Security Briefs: Improve Manageability through Event Logging by Keith Brown.

Localization Strategy Used in the Windows Event Log

The Windows® event log was designed with localization and efficiency in mind. For example, a well-designed event found in the Application log should contain just enough prose to explain a problem to the administrator and provide a suggested course of action. The vast majority of this prose should be localized for the reader, who may very well be on a remote machine in a different country. To support reading the log in your own native language, the localizable prose in the message is not actually stored in the log; rather, it is merged with the log locally as you read it. The actual prose is stored in a localized resource DLL on the reader's machine. This also has the effect of keeping the log files smaller and reducing the amount of network traffic required to read them.

Before the .NET Framework came along, this was all very clear to developers because you had to create and register these resource DLLs yourself. A typical message in a resource DLL might look like this: "Failed to connect to database %1 using connection string %2. Check to see that the database is available."

In this example, the only data about the event that would be stored in the event log would be the event ID, source, category, and a few other bits of metadata, along with the arguments supplied when the event was logged: the database name (%1) and the connection string (%2). When you use a tool such as Event Viewer to read an event like this, Windows will load the message resource DLL installed on your machine, look up the localized message based on the event ID, then merge the arguments from the log in order to display the message to you.

The way Windows figures out which resource DLL to use is by looking at the name of the event source in the log and mapping it to a registry key. This registry key contains the path to the resource DLL that should be used to display the message.

In version 1.x of the .NET Framework, the simple call to CreateEventSource wires your event source up with a default message file. This file is called EventLogMessages.dll, and it contains 65,536 event descriptions, each of which consists of the string "%1", a placeholder for whatever string you want to write. While this may have encouraged a few more people to use the event log, it defeated the purpose of having message files in the first place: to allow localized viewing of messages in the reader's language, and to keep the size of the event logs in check.

Fortunately, version 2.0 of the .NET Framework remedies this and allows you to gain the full power of the event log by registering a message file when you create your event source. This lets you support localized categories and messages, and it reduces the size of your messages in the log.

From Security Briefs: Improve Manageability through Event Logging by Keith Brown.

Sunday, July 01, 2007

Write Code Once For Both Mobile And Desktop Apps

Differences in the tools, the languages, the libraries, and the runtime engine affect the goal of writing cross-platform code.

The .NET Compact Framework achieves 80 percent of the relevant functionality found in the .NET Framework with only 20 percent of the footprint. Major areas of the .NET Framework that are absent from the compact version include: ASP.NET, CLR hosting, code access security (CAS), binary serialization, Reflection.Emit, and CodeDOM. Windows Presentation Foundation and Windows Workflow Foundation are not going to be supported any time soon.

System.Data.SqlServerCe, System.Net.IrDA, Microsoft.WindowsMobile.DirectX and Microsoft.WindowsCE.Forms are four device-specific assemblies that are in the .NET Compact Framework and not in the the .NET Framework. So the .NET Compact Framework is not a strict subset of the .NET Framework.

IL opcodes that are not supported by the .NET Compact Framework common are: jmp, calli, refanyval, refanytype, mkrefany, arglist, localloc, unaligned, and tail.

The implementations of the garbage collector and the just-in-time (JIT) compiler are different in the .NET Compact Framework than they are in the .NET Framework.

Note that the public key token for the .NET Compact Framework assemblies starts with 9 whereas the desktop equivalents start with B. You can use that information to quickly determine whether what you are deploying or referencing is a desktop or a device framework assembly.

Implementation approaches: retargeting, conditional branching, or a mix of both.

A runtime check is not enough because of JIT compiling.

Share the Code, Not the Binary.

There are two limitations with the retargetable approach: First, you can’t use any desktop-only types or methods in your code. They simply will not compile. Second, you must be careful not to load any device-specific assemblies on the desktop as they will fail with run-time exceptions.

From Share Code: Write Code Once For Both Mobile And Desktop Apps by Daniel Moth