Direct manipulation of CLI arrays using native pointers

Here’s some code that shows how you can directly manipulate the contents of an array using native pointers. The first sample is for a single dimensional array and the second is for a jagged array.

Natively accessing a single-dimensional array

void Test1()
{
    array<int>^ arr = gcnew array<int>(3);
    arr[0] = 100;
    arr[1] = 200;
    arr[2] = 300;

    Console::WriteLine(arr[0]);
    Console::WriteLine(arr[1]);
    Console::WriteLine(arr[2]);

    /*
    Output :-
      100
      200
      300
    */

    // Modifying the array using a native int*
    // that points to a pinned pointer in GC'd heap
    pin_ptr<int> p1 = &arr[0];
    int* p2 = p1;
    while(*p2)
    {
        (*p2)++;
        p2++;
    }

    Console::WriteLine(arr[0]);
    Console::WriteLine(arr[1]);
    Console::WriteLine(arr[2]);

    /*
    Output :-
      101
      201
      301
    */
} 

Natively accessing a jagged array

void Test2()
{
    array<array<int>^>^ arr = gcnew array<array<int>^>(2);
    arr[0] = gcnew array<int>(2);
    arr[1] = gcnew array<int>(2);
    arr[0][0] = 10;
    arr[0][1] = 100;
    arr[1][0] = 20;
    arr[1][1] = 200;

    Console::WriteLine(arr[0][0]);
    Console::WriteLine(arr[0][1]);
    Console::WriteLine(arr[1][0]);
    Console::WriteLine(arr[1][1]);

    /*
    Output:
      10
      100
      20
      200
    */


    // Copying the managed jagged array to
    // a native array of pointers and accessing
    // the members using the native array
    pin_ptr<int> p1 = &arr[0][0];
    pin_ptr<int> p2 = &arr[1][0];
    int* p3[2];
    p3[0] = p1;
    p3[1] = p2;

    Console::WriteLine(p3[0][0]);
    Console::WriteLine(p3[0][1]);
    Console::WriteLine(p3[1][0]);
    Console::WriteLine(p3[1][1]);

    /*
    Output:
      10
      100
      20
      200
    */

    // Assigning the native array of pointers
    // to a native int** and modifying the array
    int** p4 = p3;
    for(int i=0; i<2; i++)
        for(int j=0; j<2; j++)
            p4[i][j] += 3;

    Console::WriteLine(arr[0][0]);
    Console::WriteLine(arr[0][1]);
    Console::WriteLine(arr[1][0]);
    Console::WriteLine(arr[1][1]);

    /*
    Output:
      13
      103
      23
      203
    */
}

Essentially we use a pinning pointer to the GC’d heap and then treat the casted native pointer as if it were pointing to a native array. Gives us a really fast method to manipulate array content!

7 thoughts on “Direct manipulation of CLI arrays using native pointers

  1. Gives us a really fast method to manipulate array content!
    In my tests using a pin_ptr in such trivial cases decreases performance instead of increasing it.

  2. Hello Ben

    The code snippets were for demo purposes. But I am fairly sure that for a real-life scenario where you need to perform intensive array-manipulations, pointer arithmetic would be considerably faster than using the array in a managed manner.

  3. Hello Nish.

    You’re right, there will be some scenarios where this is faster but you should really measure before doing stuf like that. For example I would have thought using memset instead of looping through the array to init it to a certain value would be much faster. Turns out it’s quite irrelevant. Seems like managed arrays are pretty well optimized as they are already.
    Anyways, performance wasn’t really the point of you’re blog post, I just mentioned it because I was a bit surprised when I did the measuring. A main reason for using pin_ptr is to pass managed objects to unmanaged code. When pinning large amounts of data, you should release the pin_ptr by setting it to nullptr asap to let the GC do it’s business.

  4. Thanks for the tips, Ben. Maybe the CLR and the GC have become good enough so that trying to optimize speed by using pointers/unmanaged code etc might not have as wonderful effects as we expect.

    I think the Whidbey compiler is still too much alpha-ish/beta-ish to be doing benchmarks, but I think I’ll do a few tests to compare array manipulation speeds of managed and pinning pointer access.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s