Several users noticed that GMinder did not correctly display dates and times on their computers. This is because GMinder did not take into account various international time formats. New version 1.2.10 now has better support for such formats, including 24 hour formats. Note that GMinder will now use your regional settings in Windows to format the time.

Additionally, there is a new "About GMinder" window that displays the version of GMinder that you are using, accessible from the system tray.

As always, thank you for your suggestions and feedback!
GMinder trys to ping www.google.com prior to downloading events. If ECHO is disabled on your network (possibly blocked by your admin), then events will not be downloaded even if your calendars can be downloaded. With GMinder v1.2.8, an option has been added to enable/disable the connectivity test. To skip the ping, go into Options and uncheck "Test connectivity before downloading events".

EDIT: Version 1.2.8 used some faulty logic when deciding if it should ping. It has been quickly replaced by 1.2.9. I apologize for the mistake, please download the new version.

I released a new version (1.2.7) of GMinder today, with the following improvements:

  • Ability to add events to your calendars (Thanks to Dan at rowdypixel.com for getting this started!)
  • Improved Google authentication
  • Automatic proxy configuration
  • "Always on Top" option for the reminder window

The new Quick Add feature
GMinder Add.png


I recommend installing this new version, especially if a previous version had given you trouble.

Thank you for all your suggestions and feedback!

GMinder is a reminder program that waits in your system tray and alerts you when you have an upcoming Google Calendar event. GMinder supports multiple calendars and allows you to configure how you want to be alerted. Since it downloads your events, it works offline and enables you to preview your agenda of events.

GMinder's main reminder window
GMinder Reminder.png

Preview your agenda
GMinder Preview.png

Check it out on the project page!

We know that .NET performs optimizations when accessing rectangular arrays, but for sequential access should the inner loop be on the first or second index? Is there even a difference?

The Code

using System;
 
class Program
{
    static void Main(string[] args)
    {
        int size = 512;
        int count = 1000;
        int[,] array = new int[size, size];
        int total = 0;
 
        var watch = System.Diagnostics.Stopwatch.StartNew();
        for (int i = 0; i < count; i++)
            for (int x = 0; x < size; x++)
                for (int y = 0; y < size; y++)
                    total += array[x, y];
        watch.Stop();
        Console.WriteLine(String.Format("Sequential access by [x,y]: {0}ms", watch.ElapsedMilliseconds));
 
        watch = System.Diagnostics.Stopwatch.StartNew();
        for (int i = 0; i < count; i++)
            for (int x = 0; x < size; x++)
                for (int y = 0; y < size; y++)
                    total += array[y, x];
        watch.Stop();
        Console.WriteLine(String.Format("Sequential access by [y,x]: {0}ms", watch.ElapsedMilliseconds));
 
        Console.WriteLine(total);
        Console.Read();
    }
}


The Output

Sequential access by [x,y]: 825ms
Sequential access by [y,x]: 2414ms
0

 

What a difference! Incrementing the first index in the inner loop takes almost 3 times longer, probably because there are so many more cache misses.


The Verdict

For best performance, process your rectangular arrays by incrementing the first index in an outer loop, and the second index in an inner loop.

Concurrency Encapsulation

| | Comments (0)

One of my projects is a perfect candidate for concurrency. There is a collection of entities that each need to be processed, and each can be processed independently. For the sake of Separation of Concerns, I developed a WorkManager class dedicated to performing an action on the elements of an enumeration. Before I spill the code, here is how it is used:

Entity[] myCollection = LoadEntities();
WorkManager manager = new WorkManager();
manager.ForEach(myCollection, e => e.Process());

Note the lambda expression above. It means that for each Entity in myCollection, the code will execute its Process method. The program will create a separate thread for each processor, and evenly distribute the workload across the threads.

And without further delay, the WorkManager class:

One thing I love about WSUS is the ability to monitor the presence of clients. It gives me a good approximation of the last time a computer was on the network. I often use this information to help me clean missing computers out of Active Directory.

But what about when a computer is removed from the domain before it is removed from WSUS? Rather than manually checking, I wrote an IronPython script that compares the list of computers in Active Directory with the computers on WSUS. When I run this script, it lists computers that should be removed from WSUS, and deletes them for me (after prompting).

Embedding IronPython

| | Comments (0)

In my current programming project, I've embedded IronPython in a C# program. I thought I would share the basics of embedding a scripting engine. I imagine the process would be the same for any language that uses the DLR (Dynamic Language Runtime), like IronRuby. Here is a sample using IronPython 2.0 Beta 5.

using System;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
 
public class Program
{
    // Delegate matching the signature of the factorial function
    delegate int FactorialDelegate(int n);
 
    static void Main(string[] args)
    {
        // Our factorial function
        string[] lines = {"def factorial(n):",
                          "  for i in range(1, n):",
                          "    n = n * i",
                          "  return n"};
 
        string code = String.Join("\r", lines);
 
        // Instantiate the IronPython environment
        ScriptEngine engine = Python.CreateEngine();
 
        // Create a scope/module to work in
        ScriptScope scope = engine.CreateScope();
 
        // A little preparation
        ScriptSource source = engine.CreateScriptSourceFromString(code, SourceCodeKind.Statements);
 
        // Compile the code
        CompiledCode compiled = source.Compile();
 
        // Execute the code in the scope
        compiled.Execute(scope);
 
        //Now the factorial function exists in the IronPython environment. Let's use it.
 
        // Set x = 5
        scope.SetVariable("x", 5);
 
        // print factorial(x)
        ScriptSource print = engine.CreateScriptSourceFromString("print factorial(x)", SourceCodeKind.SingleStatement);
        print.Execute(scope);       //outputs 120
 
        // Get the result from IronPython
        int result1 = scope.Execute<int>("factorial(6)");
        Console.WriteLine(result1); //outputs 720
 
        // We can also call the function directly from C#
        FactorialDelegate factorial = scope.GetVariable<FactorialDelegate>("factorial");
        int result2 = factorial(7);
        Console.WriteLine(result2); //outputs 5040
 
        Console.Read();
    }
}

Math.BigMul Exposed

| | Comments (0)

Today a friend and I were reflecting through System.Math (courtesy of IronPython) and we noticed the BigMul method:

Math.BigMul(Int32, Int32) : Int64

Why have a method just for multiplication? It seems to be a trivial reason to add a method to the .NET framework. After all, multiplication with casting does the same thing:

(long)a * (long)b

Being optimistic, I suggested that perhaps Microsoft's BigMul is implementing a faster and more efficient multiplication algorithm. Maybe there is a clever way to multiply two 32 bit numbers without explicit casting to 64 bit. Naturally, I wrote a simple speed test.

static void Main(string[] args)
{
    int a = 40993;
    int b = 69872;
    long c = 0;
 
    DateTime start;
    TimeSpan length;
 
    Console.WriteLine("Inline multiplication");
    start = DateTime.Now;
    for (int i = 0; i < 1000000000; i++)
        c = (long)a * (long)b;
    length = DateTime.Now - start;
    Console.WriteLine(c);
    Console.WriteLine(length.ToString());
    Console.WriteLine();
 
    Console.WriteLine("Math.BigMul");
    start = DateTime.Now;
    for (int i = 0; i < 1000000000; i++)
        c = Math.BigMul(a, b);
    length = DateTime.Now - start;
    Console.WriteLine(c);
    Console.WriteLine(length.ToString());
    Console.WriteLine();
 
    Console.Read();
}

The results were not encouraging.

I prefer Firefox as my default web browser. For website development, Firefox with Firebug is a killer combination. But when I test a page in Internet Explorer, I sometimes get cryptic Javascript errors that are impossible to track down. It turns out that Internet Explorer needs some coaxing to play nice with Visual Studio.

Enable Javascript Debugging
Open Internet Options and head over to the Advanced tab. Uncheck Disable script debugging (Internet Explorer).

debugging-ie-1.jpg

That's all it takes; the next time you encounter a Javascript error, you will be prompted to debug. Select an instance of Visual Studio and you'll have interactive debugging.

Launch with Internet Explorer
When you run or debug a website, Visual Studio uses you default system browser. But maybe you prefer to debug in a different browser. To change this setting, right-click on an aspx file in Solution Explorer and select Browse With. Select the desired browser and set it as default.

Select a default browser

That's it! Do you have any tips or tools for website debugging?