From 00bfb0443d6b96d738428ba92f8b602fa89834dc Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Mon, 7 Aug 2006 15:55:49 +0000 Subject: Add 'size' sample svn path=/trunk/mono/; revision=63435 --- samples/size/Makefile | 12 +++++ samples/size/README | 28 +++++++++++ samples/size/objectinspector.cs | 37 +++++++++++++++ samples/size/sample.cs | 23 +++++++++ samples/size/size.c | 101 ++++++++++++++++++++++++++++++++++++++++ samples/size/size.cs | 38 +++++++++++++++ 6 files changed, 239 insertions(+) create mode 100644 samples/size/Makefile create mode 100644 samples/size/README create mode 100644 samples/size/objectinspector.cs create mode 100644 samples/size/sample.cs create mode 100644 samples/size/size.c create mode 100644 samples/size/size.cs (limited to 'samples') diff --git a/samples/size/Makefile b/samples/size/Makefile new file mode 100644 index 00000000000..e5dabdf1935 --- /dev/null +++ b/samples/size/Makefile @@ -0,0 +1,12 @@ + +all: objectinspector.dll libmono-profiler-size.so sample.exe + LD_LIBRARY_PATH=. mono --profile=size sample.exe + +sample.exe: objectinspector.dll sample.cs + mcs -r:objectinspector.dll sample.cs + +objectinspector.dll: objectinspector.cs + mcs -target:library objectinspector.cs + +libmono-profiler-size.so: size.c + gcc -Wall -shared -o libmono-profiler-size.so size.c `pkg-config --cflags --libs mono` diff --git a/samples/size/README b/samples/size/README new file mode 100644 index 00000000000..706da70ae59 --- /dev/null +++ b/samples/size/README @@ -0,0 +1,28 @@ + +* Size sample + + This sample provides a new internal call that can be used to + obtain the size of an object and all of the referenced objects + that this object holds. + + This is exposed in the method: + + int Mono.ObjectServices.ObjectInspector.GetMemoryUsage (object x) + + Available in the objectinspector.dll file; To use this, you + must run Mono with the --profile=size argument (and have the + libmono-profile-size.so module in your path). + +* Inner Details. + + This implementation used a profiler hook at jit-end to install + a new internal call, and exposes a small DLL + (objectinspector.dll). + + There is no need to use the profiler, the method body that + does the object size computation can be copy/pasted elsewhere, + particularly on embedded uses of Mono. + + + + diff --git a/samples/size/objectinspector.cs b/samples/size/objectinspector.cs new file mode 100644 index 00000000000..1da7b7f15a7 --- /dev/null +++ b/samples/size/objectinspector.cs @@ -0,0 +1,37 @@ + +// +// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System.Runtime.CompilerServices; +using System; +using System.Security; +using System.Reflection; +using System.Threading; + +namespace Mono.ObjectServices { + + public class ObjectInspector { + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static int GetMemoryUsage (object x); + } +} diff --git a/samples/size/sample.cs b/samples/size/sample.cs new file mode 100644 index 00000000000..5a874dec852 --- /dev/null +++ b/samples/size/sample.cs @@ -0,0 +1,23 @@ +using System; +using Mono.ObjectServices; + +class Demo { + int a; + static void Main () + { + Demo d = new Demo (); + + prints ("d", d); + prints ("dd", new DD ()); + } + + static void prints (string s, object x) + { + Console.WriteLine ("size of " + s + ":" + ObjectInspector.GetMemoryUsage (x)); + } +} + +class DD { + Demo d = new Demo (); + object [] o = new object [10]; +} diff --git a/samples/size/size.c b/samples/size/size.c new file mode 100644 index 00000000000..a3d2253add1 --- /dev/null +++ b/samples/size/size.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define FIELD_ATTRIBUTE_STATIC 0x10 + +int +memory_usage (MonoObject *this, GHashTable *visited) +{ + int total = 0; + MonoClass *class; + gpointer iter = (gpointer) 0; + MonoClassField *field; + + if (g_hash_table_lookup (visited, this)) + return total; + + class = mono_object_get_class (this); + + g_hash_table_insert (visited, this, this); + + while ((field = mono_class_get_fields (class, &iter)) != NULL){ + MonoType *ftype = mono_field_get_type (field); + void *value; + + if ((ftype->attrs & FIELD_ATTRIBUTE_STATIC) != 0) + continue; + + switch (ftype->type){ + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + mono_field_get_value (this, field, &value); + + if (value != NULL) + total += memory_usage ((MonoObject *) value, visited); + break; + + case MONO_TYPE_SZARRAY: + printf ("implement me\n"); + break; + + case MONO_TYPE_I4: + case MONO_TYPE_I1: + case MONO_TYPE_I2: + case MONO_TYPE_U4: + case MONO_TYPE_U2: + case MONO_TYPE_U1: + case MONO_TYPE_VOID: + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_CHAR: + /* ignore */ + break; + default: + printf ("unhandled type: 0x%x\n", ftype->type); + } + } + + total += mono_class_instance_size (class); + + return total; +} + +/* + * Only returns data for instances, not for static fields, those might + * be larger, or hold larger structures + */ +static int +GetMemoryUsage (MonoObject *this) +{ + GHashTable *visited = g_hash_table_new (NULL, NULL); + int n; + + n = memory_usage (this, visited); + + g_hash_table_destroy (visited); + + return n; +} + +static int installed = 0; + +void install_icall (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) +{ + if (installed) + return; + + mono_add_internal_call ("Mono.ObjectServices.ObjectInspector::GetMemoryUsage", GetMemoryUsage); + installed = 1; +} + +void +mono_profiler_startup (const char *desc) +{ + mono_profiler_install_jit_end (install_icall); + mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION); +} diff --git a/samples/size/size.cs b/samples/size/size.cs new file mode 100644 index 00000000000..dd8f5d3a730 --- /dev/null +++ b/samples/size/size.cs @@ -0,0 +1,38 @@ + +// +// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using Mono.Interop; +using System.Runtime.CompilerServices; +using System; +using System.Security; +using System.Reflection; +using System.Threading; + +namespace Mono.ObjectServices { + + public class ObjectInspector { + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern static int GetMemoryUsage (object x); + } +} -- cgit v1.2.3