Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does "readonly" (C#) reduce memory usage?

In C#, does setting a field as readonly reduce memory usage?

i.e.

DBRepository _db = new DBRepository();

vs

readonly DBRepository _db = new DBRepository();

Just curious. Thanks.

like image 571
Chaddeus Avatar asked Jul 20 '09 09:07

Chaddeus


4 Answers

No.

It means you can't assign to it except at the declaration point or in a constructor. You also can't pass it as a ref or out parameter to a method.

Edit: based on the comment below. The following field is readonly because you want callers to have direct read access to string.Empty, but you don't want them to set it to something else.

public sealed class String
{
    public static readonly string Empty = "";
}

Also, sometimes when I have a List<> or Dictionary<> as a field in a class, I'll declare it readonly to indicate that I want to work with its members (even Add and Remove items, etc.) but I never want to actually assign a different List or Dictionary object to it.

One more edit: Make sure you read about the deprecated Path.InvalidPathChars field (in the remarks section) to show a serious problem that can happen when you don't understand what readonly is and is not.

like image 85
Sam Harwell Avatar answered Nov 06 '22 16:11

Sam Harwell


No. readonly and const basically serve the same purpose: to prevent assignments to the values at runtime. However, they have semantically different uses.

readonly versus const

A const field is evaluated at compile time and can only be initialized at declaration, while a readonly field is evaluated at run time and can be initialized both in constructors and at declaration site.

Also, a const field value is stored as part of the metadata and so is initialized in the relevant constructor of the class that declared it while readonly fields will have to be computed at runtime.

like image 27
Mike J Avatar answered Nov 06 '22 15:11

Mike J


YES!

Yes? Yes! How? Simple. A read-only field cannot get a new value so you can't create a second DBRepository and assign it to this field. If it's not read-only then you could write code which will re-assign a new value to this field. And during the time between the reassignment and the time for the garbage collector to clear your old value, you will have a bit more memory in use. Furthermore, if cleanup of the DBRepository has a memory leak, then reassigning new values to this field will cause multiple memory leaks.

A situation where such a memory leak could occur is this: 1) You assign a value to _db. 2) You assign the value of _db to another field. 3) You reassign a new value to _db. At this moment you will have two DBRepository objects in memory because the old object is still referenced to from another object. Thus the old object won't be freed until the second field releases it.

But this is very nitpicky and quite rare. The answer "No" is more appropriate. Don't use "ReadOnly" to save memory because you'd be using it for the wrong reason. Use "ReadOnly" to make sure others won't reassign a value to this field. (Basically, I'm saying that it can reduce memory usage...)

like image 7
Wim ten Brink Avatar answered Nov 06 '22 15:11

Wim ten Brink


The answer No is written from the perspective of a good performance focused coder who already knows all the tricks and traps eg.:

  1. No LINQ in tight loops. Really. None. Ever.
  2. Cast your enums to ints before comparison
  3. Beware of value type structs
  4. 'new' is the new Grue
  5. CLRProfiler is your friend
  6. Other profilers will put variable construction time into weird places

The answer Yes is very relevant to a coder not aware of the pitfalls of the design of C#, or one who has swallowed the "Profiling is evil" coolade.

I initialize a lot (maybe even a LOT) of matrices and arrays in our code. I have noticed that lazy initialization with: if (variable == null) // variable = new Variable()

seems less performant than constructing up front. Since readonly forces you to construct in the constructor you get the benefits of data localization in memory and prevents you from doing other disasterous 'build and replace at runtime' things. C# can choke horribly on the garbage collector.

C# allows us to very easily write terribly memory innefficient code. malloc was a way to force us to think about (de)allocation. In the same way, readonly forces us to think about it.

Run CLRProfiler, see for yourself how much memory spam you make. If you've been writing HPC without almost superhuman discipline, the chances are you're spamming the heap and readonly can help prevent you from doing that.

That said, if you're not writing HPC code then premature optimization is the root of all learning about machine architecture. Oh, no, wait... I meant evil, per the standard doctrine. All hail the standard doctrine.

like image 1
Doug Avatar answered Nov 06 '22 16:11

Doug