Saturday 15 September 2012

c# - Get 'optimistic' size of managed object in memory -



c# - Get 'optimistic' size of managed object in memory -

first, aware of many posted questions covering topic: 1 2 3 4 5. proposed approaches & why not:

marshal.sizeof() 1 - not work menaged types. gc.gettotalmemory 1 2 - race status prone. serialization 1 2 3 4 - it's quite close, automatic-fields can problematic, properties without public setter. also, it's not optimal performance-wise. code profiling using sos 1 2 and other tools - great, not runtime.

due padding , issues posted 1 2 3, appears, there no optimal solution, rather trade-off between precision, performance , code-bloat.

however, needed simple method count optimistic (minimum) memory usage, i.e. want know object occupies @ to the lowest degree that much. rationale have environment of types owning many collections, nested, , want approximate quickly, object coming close i.e. .5 gb in memory etc..

there came & questions:

i looking forwards thoughts , suggestions on can done better. especially, i'm looking memory not accounted in code, , (without writing 200+ lines of code this).

i can't auto generated fields (property __backingfield) inherited type, whilst works fine not inherited backing fields. searched proper bindingflag, not find one.

/// <summary> /// minimal memory amount occupied instance. /// counted instance fields, including auto-generated, private , protected. /// not counted: static fields, properties, functions, actions, fellow member methods etc. /// </summary> public static long sizeinbytes<t>(this t obj) { if (obj == null) homecoming sizeof(int); var type = obj.gettype(); if (type.isprimitive) { switch (type.gettypecode(type)) { case typecode.boolean: case typecode.byte: case typecode.sbyte: homecoming sizeof(byte); case typecode.char: homecoming sizeof(char); case typecode.single: homecoming sizeof(float); case typecode.double: homecoming sizeof(double); case typecode.int16: case typecode.uint16: homecoming sizeof(int16); case typecode.int32: case typecode.uint32: homecoming sizeof(int32); case typecode.int64: case typecode.uint64: default: homecoming sizeof(int64); } } else if (obj decimal) { homecoming sizeof(decimal); } else if (obj string) { homecoming sizeof(char) * obj.tostring().length; } else if (type.isenum) { homecoming sizeof(int); } else if (type.isarray) { long size = sizeof(int); var casted = (ienumerable)obj; foreach (var item in casted) { size += item.sizeinbytes(); } homecoming size; } else { long size = 0; var t = type; while (t != null) { foreach (var field in t.getfields(bindingflags.instance | bindingflags.public | bindingflags.nonpublic | bindingflags.declaredonly)) { var tempval = field.getvalue(obj); if (!object.referenceequals(obj,tempval)) { size += tempval.sizeinbytes(); } } t = t.basetype; } homecoming size; } }

to reply 3rd question getting fields, can reliably fields in type this:

public static ienumerable<fieldinfo> getallfields(type t) { while (t != null) { foreach (fieldinfo field in t.getfields(bindingflags.instance | bindingflags.nonpublic | bindingflags.public | bindingflags.declaredonly)) { yield homecoming field; } t = t.basetype; } }

this works because getfields can homecoming private fields of current type, not inherited private fields; need walk inheritance chain calling getfields on each type.

c# .net memory memory-management

No comments:

Post a Comment