Sample Interviews

by Miguel de Icaza

Some folks have been asking what kind of interviews we conduct over email for hiring in the Mono team. We allow people to work remotely. To find out how well they can work independently away from our office we came up with some tasks that we give out on job interviews.

In my experience with hiring people at Ximian, the face-to-face interviews did not yield as good results as reviewing someone's existing track record and contributions or these programming exercises.

A resume, plus an interview when you ask the candidate to "implement XX on the whiteboard" and some trick questions have too many problems which are probably worth discussing some other day. In my experience these kinds of interviews that have been popularized in the industry are bad. They evaluate developers on all the wrong dimensions that you need to produce software.

Am posting here two of the interviews that we used in the past to hire for positions into the Windows.Forms group and the Mono VM engine. These interviews are typically conducted over two to three weeks.

A story that I find funny was when we did the Windows.Forms interview. Once I emailed back the applicants with the 2 week deadline, Andreia Gaita replied to me within 2 or 3 days. She was the first to reply, but thought that she was the last, and her code was great, did everything I requested (and if she gives me permission I can post her submission).

Andreia turned out of course to be a superb hacker, see her recent work on Mono/Mozilla integration.

The interviews follow.

These are not the interviews that we will use for Moonlight, but it will give you an idea of what kind of thing we do ;-)

Windows.Forms Interview

Remember: these interviews are designed to be answered at home during your afternoons when you get back from school/work and would usually take a few days.

* The Widget

    You must implement a small rendering engine for a small
    XML-inspired markup language, the language accepts:

    <p>...</p>    To start paragraphs.

    Paragraphs in turn can contain the following:

    <b>...</b>    Where the text ... is bolded.

    <i>...</i>    Where the text ... is italicized

    <link>...</link> Where the ... is rendered as a link

    <blink>...</blink> The text should blink.

        The control must expose one property:

        string Markup { get; set; }

    Which allows the developer to programatically set the markup
    language, for example:

          m = new MarkupControl ();
          m.Markup = "<p>Hello <b>World</b>!</p>";

    The control must also expose an event, so I can hook up
    whenever someone clicks on a link:

    delegate void LinkClicked (object sender, string link_text);

    So I can use it like this:

          m.LinkClicked += my_clicked;
      ...
        
      void my_clicked (object sender, string link_text)
      {
        Console.WriteLine ("The link {0} was clicked", link_text);
      }
                
    You must also provide a complete program that will run when I
    run it in Linux, and you must also exercise the property and
    the event, this would be nice to have:

      void my_clicked (object sender, string link_text)
      {
        Console.WriteLine ("The link {0} was clicked", link_text);
        ((MarkupControl) sender).Markup = "<p>This is the new text after clicking</p>";
      }

    Extra points: when I use blink, you will have to refresh,
    bonus points if you avoid flicker by using double buffering, or
    by only repaining the area that has changed. 

    I want a small and succinct implementation, but this is your
    opportunity to show that you can write *robust* code, so impress
    me.

* Trick Question

    In our corlib implementation, in System/DateTime.cs we have a
    suboptimal implementation of the method "TryParse", we basically
    call Parse inside try/catch.

    Explain:

        * Why do I say that our solution is "suboptimal"?

        * What would it take it to make more efficient?

        * Why did the maintainer that wrote that code not do
          the more efficient thing?

    The trick question is: Why was the faster process not done in
    the first place.

    Explain.
    

JIT Interview

This interview was constructed by Paolo Molaro when we were hiring folks for the JIT. The developers that joined us have been fantastic, Mark and Rodrigo. They are working in adding the CoreCLR security (I blogged about Mark's work before) and the verifier to Mono (which we will need for Moonlight) and have also been doing many other needed tasks on the VM.

    This interview should take a week to complete in your
    afternoons.  Between 8 to 16 hours for someone not familiar
    with Mono.

    We figured that not everyone has time to allocate to this
    immediately, so we will wait until March 30th to review the
    applications.

    All of this can be answered by using the officially released
    Mono packages from:

            http://www.mono-project.com/Downloads

    Get the mono-1.2.3.tar.gz source code download.

    Feel free to ask any questions privately or in any Mono public
    forums.

First Task: Extending the Mono VM

    Given the following program, change the mono JIT to intercept
    the Datum.Add () function and implement it internally with a
    SSE instruction so that the additions happen in
    parallel. Datum.Add () is to be treated like an intrinsic:
    this means that the JIT knows exactly what it's supposed to do
    and doesn't need to actually compile the IL code in it.

    Ie, you catch early on the call to Datum.Add (), there is no
    need to do any advanced compiler optimizations.  The current
    implementation here will be ignored once you have this
    implemented.

using System;

struct Datum {
    float f1; float f2; float f3; float f4;

    Datum (float val) {
        f1 = f2 = f3 = f4 = val;
    }

    void Add (ref Datum b) {
        f1 += b.f1;
        f2 += b.f2;
        f3 += b.f3;
        f4 += b.f4;
    }

    void Print () {
        Console.WriteLine ("{0}:{1}:{2}:{3}", f1, f2, f3, f4);
    }

    const int count = 100;

    static void Main ()
    {
        Datum[] array = new Datum [count];
        float f = 0.1f;
        for (int i = 0; i < count; ++i) {
                array [i] = new Datum (f);
        }
        for (int i = 1; i < count; ++i) {
                array [i].Add (ref array [i - 1]);
        }
        array [10].Print ();
        array [count - 1].Print ();
    }
}

Second Task: 

     Pick one of two:

        * GC Analysis

        * JIT and Generic Analysis

* GC Analysis.

    Given the description in:

        http://www.mono-project.com/Compacting_GC 

    and the implementation in 

                mono/metadata/sgen-gc.c

    describe briefly 3 changes to the GC code and/or JIT-GC
    interface that would provide a significant performance
    speedup. 

    Explain the changes, the reasons it will improve performance
    and provide rough speedup numbers with a benchmark of your
    choice.

* JIT and Generic Analysis

   Mono supports generics in its compiler and VM, this means that
   code like this is supported:

       class MyStack<T> {
               T [] storage;
               int top;

               MyStack ()
               {
                       storage = new T [10];
               }

               public void Push (T datum)
               {
                       storage [top++] = datum;
               }

               public bool Empty {
                       get {
                               return top == 0;
                       }
               }
       }

   If the above code is used like this:

       MyStack<object> object_stack = new MyStack<object> ()
       MyStack<string> string_stack = new MyStack<string> ()
       MyStack<int> string_stack = new MyStack<int> ()

   Explain:

       * When a generic class is instantiated, what pieces of
         code are shared?

       * Why they should be shared?

       * Are they shared in Mono?   

       * If yes, why?   If not, why not?

       * How could this be improved?

    

Posted on 05 Sep 2007