1

I'm re-writing alibrary with a mandate to make it totally allocation free. The goal is to have 0 collections after the app's startup phase is done.

Previously, there were a lot of calls like this:

Int32 foo = Int32.Parse(ASCIIEncoding.ASCII.GetString(bytes, start, length));

Which I believe is allocating a string. I couldn't find a C# library function that would do the same thing automatically. I looked at the BitConverter class, but it looks like that is only if your Int32 is encoded with the actual bytes that represent it. Here, I have an array of bytes representing Ascii characters that represent an Int32.

Here's what I did

public static Int32 AsciiBytesToInt32(byte[] bytes, int start, int length)
{
     Int32 Temp = 0;
     Int32 Result = 0;
     Int32 j = 1;

     for (int i = start + length - 1; i >= start; i--)
     {
          Temp = ((Int32)bytes[i]) - 48;

          if (Temp < 0 || Temp > 9)
          {
               throw new Exception("Bytes In AsciiBytesToInt32 Are Not An Int32");
          }

          Result += Temp * j;
          j *= 10;
     }

     return Result;
}

Does anyone know of a C# library function that already does this in a more optimal way? Or an improvement to make the above run faster (its going to be called millions of times during the day probably). Thanks!

Michael Covelli
  • 2,113
  • 4
  • 27
  • 41
  • 3
    If there is one thing that makes managed code superior to traditional code then it is the *very* low cost of allocating memory. Intentionally avoiding it is like blowing your left foot off to compete in the Olympics. – Hans Passant Mar 26 '10 at 12:26
  • Allocating memory is cheap; garbage collection isn't. Creating tons of garbage could end up pushing relatively short-lived object onto the Gen2 heap, which in general is something worth avoiding. – Gabe Mar 26 '10 at 12:54
  • Agreed. We're trying to cut down on collections. We're definitely seeing some Gen2 collections that take up to 100ms. These short-lived strings aren't a huge issue I guess, they should be collected pretty quickly. But they're not that hard to remove. And it makes it easier to track down where the real heavy allocations are coming from if we just say: no allocations during the continuous operating phase of the app. – Michael Covelli Mar 26 '10 at 13:24

1 Answers1

5

Millions of times per day shouldn't be a problem - I'd expect that to be able to run hundreds of thousands of times per second. Personally I'd rewrite the above to only declare "temp" within the loop (and get rid of the Pascal-cases local variable names - urgh) but it should be okay.

The code would be more immediately understandable as:

int digit = bytes[i] - '0';

which does the same as your

Temp = ((Int32)bytes[i]) - 48;

line, but in a simpler way (IMO). They should behave exactly the same way.

On a general note, trying to write C# without any allocations is pretty harsh, and fights against the way the language and framework are designed. Do you believe this is actually a reasonable requirement? Admittedly I've heard about it being the way some games are written in managed code... but it does seem a bit odd.

Of course, you're going to allocate an exception if the bytes are inappropriate...

EDIT: Note that your code doesn't allow for negative numbers. Is that okay?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    He also doesn't handle overflow. – Gabe Mar 26 '10 at 12:58
  • Thanks for your reply. Great points on the negatives and the overflow. These integers should mostly be pretty small, but the negatives may be an issue. – Michael Covelli Mar 26 '10 at 13:20
  • I shouldn't have said no allocations. I really just meant that we're trying to pre-allocate almost everything during the startup phase of our application. This is an app where a 100ms freeze for a Gen2 collection may have an impact so we're trying to follow something like the design practices outlined here: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=4215ab9e-4181-4526-823b-d364448188b2 – Michael Covelli Mar 26 '10 at 13:21