improve reportingn of memory usage

This commit is contained in:
Richard Frith-Macdonald 2019-06-11 14:07:10 +01:00
parent 42b404c586
commit 3f7d54a33f
18 changed files with 395 additions and 267 deletions

View file

@ -1,3 +1,27 @@
2019-06-11 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/GNUstepBase/GSIArray.h:
* Headers/GNUstepBase/NSObject+GNUstepBase.h:
* Source/Additions/NSObject+GNUstepBase.m:
* Source/GSArray.m:
* Source/GSCountedSet.m:
* Source/GSDictionary.m:
* Source/GSSet.m:
* Source/NSArray.m:
* Source/NSConcreteHashTable.m:
* Source/NSConcreteMapTable.m:
* Source/NSData.m:
* Source/NSDictionary.m:
* Source/NSDistantObject.m:
* Source/NSObject.m:
* Source/NSProxy.m:
* Source/NSSet.m:
* Source/NSString.m:
Revise mechanism for extention to report memory usage of individual
objects. This makes the inclusion of size of objects in ivars a
default, while allowing easy extension to include other heap memory.
API change not final.
2019-05-23 Frederik Seiffert <frederik@algoriddim.com>
* configure:

View file

@ -188,6 +188,15 @@ GSIArrayCount(GSIArray array)
return array->count;
}
GS_STATIC_INLINE NSUInteger
GSIArraySize(GSIArray array)
{
NSUInteger size = sizeof(GSIArray);
size += array->cap * sizeof(GSIArrayItem);
return size;
}
GS_STATIC_INLINE void
GSIArrayGrow(GSIArray array)
{

View file

@ -111,27 +111,80 @@ extern "C" {
@end
/** This is an informal protocol ... classes may implement the method to
* report how much memory is used by the instance and any objects it acts
* as a container for.
/** This is an informal protocol; classes may implement the
* +contentSizeOf:declaredIn:excluding: method to report how much memory
* is used by any objects/pointers it acts as a container for.<br />
* Code may call the -sizeInBytesExcluding: or -sizeinBytes method to
* determine how much heap memory an object (and its content) occupies.
*/
@interface NSObject(MemoryFootprint)
/* This method returns the memory usage of the receiver, excluding any
/** This method returns the size of the memory used by the instance variables
* of obj which were declared in the supplied class (excluding those declared
* by its superclasses or subclasses).<br />
* This is not the memory occupied by obj itself. Rather, it should be the
* memory referenced by any pointers (including objects) in obj.<br />
* Subclasses which do not implement this method will have the memory of their
* object ivars included in the total but not memory pointed to by non-object
* pointers (generic code cannot readily determine the size of blocks of
* memory pointed to by a pointer).<br />
* When an implementation (other than the NSObject implementation) of this
* method is called, cls should be the class in which the implementation
* was defined. However, as a convenience, the implementation may call the
* base implementation to get the size of object ivars, and then add in the
* size of other memory referenced by pointers the instance is using:
* <example>
* @interface foo : bar
* {
* id a; // Some object
* id b; // More storage
* unsigned capacity; // Buffer size
* char *p; // The buffer
* }
* @end
* @implementation foo
* + (NSUInteger) contentSizeOf: (NSObject*)obj
* declaredIn: (Class)cls
* excluding: (NSHashTable*)exclude
*{
* NSUInteger size;
*
* // get the size of the objects (a and b)
* size = [NSObject contentSizeOf: obj
* declaredIn: self
* excluding: exclude];
* // add the memory pointed to by p
* size += obj->capacity * sizeof(char);
* return size;
*}
*@end
* </example>
*/
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude;
/** This method returns the memory usage of the receiver, excluding any
* objects already present in the exclude table.<br />
* The argument is a hash table configured to hold non-retained pointer
* objects and is used to inform the receiver that its size should not
* be counted again if it's already in the table.<br />
* The NSObject implementation returns zero if the receiver is in the
* table, but otherwise adds itself to the table and returns its memory
* footprint (the sum of all of its instance variables, but not any
* memory pointed to by those variables).<br />
* Subclasses should override this method by calling the superclass
* implementation, and either return the result (if it was zero) or
* return that value plus the sizes of any memory owned by the receiver
* (eg found by calling the same method on objects pointed to by the
* receiver's instance variables).
* footprint (the sum of all of its instance variables, plus the result
* of calling +contentSizeOf:declaredIn:excluding: for the class of the
* instance and all its superclasses).<br />
* Classes should not override this method, instead they should implement
* +contentSizeOf:declaredIn:excluding: to return the extra memory usage
* of the pointer/object instance variables (heap memory) they add to
* their superclass.
*/
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude;
/** Convenience method calling -sizeInBytesExcluding: with a newly created
* exclusion hash table, and destroying the table once the size is calculated.
*/
- (NSUInteger) sizeInBytes;
@end
/** This is an informal protocol ... classes may implement the method and

View file

@ -323,28 +323,73 @@ handleExit()
#else
NSUInteger
GSPrivateMemorySize(NSObject *self, NSHashTable *exclude)
@implementation NSObject (MemoryFootprint)
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
if (0 == NSHashGet(exclude, self))
unsigned count;
Ivar *vars;
NSUInteger size = 0;
if (0 != (vars = class_copyIvarList(cls, &count)))
{
NSHashInsert(exclude, self);
return class_getInstanceSize(object_getClass(self));
while (count-- > 0)
{
const char *type = ivar_getTypeEncoding(vars[count]);
type = GSSkipTypeQualifierAndLayoutInfo(type);
if ('@' == *type)
{
NSObject *content = object_getIvar(obj, vars[count]);
if (content != nil)
{
size += [content sizeInBytesExcluding: exclude];
}
}
}
free(vars);
}
return size;
}
+ (NSUInteger) sizeInBytes
{
return 0;
}
@implementation NSObject (MemoryFootprint)
+ (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
return 0;
}
- (NSUInteger) sizeInBytes
{
NSUInteger bytes;
NSHashTable *exclude;
exclude = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 0);
bytes = [self sizeInBytesExcluding: exclude];
NSFreeHashTable(exclude);
return bytes;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
if (0 == NSHashGet(exclude, self))
{
Class c = object_getClass(self);
NSUInteger size = class_getInstanceSize(c);
NSHashInsert(exclude, self);
return class_getInstanceSize(object_getClass(self));
if (size > 0)
{
while (c != Nil)
{
size += [c contentSizeOf: self
declaredIn: c
excluding: exclude];
c = class_getSuperclass(c);
}
}
return size;
}
return 0;
}

View file

@ -73,6 +73,21 @@ static Class GSInlineArrayClass;
@implementation GSArray
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
GSArray *a = (GSArray*)obj;
NSUInteger size = a->_count * sizeof(id);
NSUInteger index = a->_count;
while (index-- > 0)
{
size += [a->_contents_array[index] sizeInBytesExcluding: exclude];
}
return size;
}
- (void) _raiseRangeExceptionWithIndex: (NSUInteger)index from: (SEL)sel
{
NSDictionary *info;
@ -421,6 +436,21 @@ static Class GSInlineArrayClass;
@implementation GSMutableArray
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
GSMutableArray *a = (GSMutableArray*)obj;
NSUInteger size = a->_capacity * sizeof(id);
NSUInteger index = a->_count;
while (index-- > 0)
{
size += [a->_contents_array[index] sizeInBytesExcluding: exclude];
}
return size;
}
+ (void) initialize
{
if (self == [GSMutableArray class])
@ -938,22 +968,6 @@ static Class GSInlineArrayClass;
return count;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = GSPrivateMemorySize(self, exclude);
if (size > 0)
{
NSUInteger count = _count;
size += _capacity*sizeof(void*);
while (count-- > 0)
{
size += [_contents_array[count] sizeInBytesExcluding: exclude];
}
}
return size;
}
@end

View file

@ -90,6 +90,24 @@
@implementation GSCountedSet
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
GSIMapTable map = &((GSCountedSet*)obj)->map;
NSUInteger size = GSIMapSize(map) - sizeof(GSIMapTable);
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
while (node != 0)
{
size += [node->key.obj sizeInBytesExcluding: exclude];
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
return size;
}
+ (void) initialize
{
if (self == [GSCountedSet class])
@ -378,24 +396,4 @@
(&map, state, stackbuf, len);
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = GSPrivateMemorySize(self, exclude);
if (size > 0)
{
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(&map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
size += GSIMapSize(&map) - sizeof(map);
while (node != 0)
{
size += [node->key.obj sizeInBytesExcluding: exclude];
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
}
return size;
}
@end

View file

@ -80,6 +80,25 @@
static SEL nxtSel;
static SEL objSel;
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
GSIMapTable map = &((GSDictionary*)obj)->map;
NSUInteger size = GSIMapSize(map) - sizeof(GSIMapTable);
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
while (node != 0)
{
size += [node->key.obj sizeInBytesExcluding: exclude];
size += [node->value.obj sizeInBytesExcluding: exclude];
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
return size;
}
+ (void) initialize
{
if (self == [GSDictionary class])
@ -356,31 +375,29 @@ static SEL objSel;
(&map, state, stackbuf, len);
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = GSPrivateMemorySize(self, exclude);
if (size > 0)
{
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(&map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
size += GSIMapSize(&map) - sizeof(map);
while (node != 0)
{
size += [node->key.obj sizeInBytesExcluding: exclude];
size += [node->value.obj sizeInBytesExcluding: exclude];
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
}
return size;
}
@end
@implementation GSMutableDictionary
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
GSIMapTable map = &((GSDictionary*)obj)->map;
NSUInteger size = GSIMapSize(map) - sizeof(GSIMapTable);
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
while (node != 0)
{
size += [node->key.obj sizeInBytesExcluding: exclude];
size += [node->value.obj sizeInBytesExcluding: exclude];
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
return size;
}
+ (void) initialize
{
if (self == [GSMutableDictionary class])

View file

@ -106,6 +106,24 @@ static Class arrayClass;
static Class setClass;
static Class mutableSetClass;
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
GSIMapTable map = &((GSSet*)obj)->map;
NSUInteger size = GSIMapSize(map) - sizeof(GSIMapTable);
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
while (node != 0)
{
size += [node->key.obj sizeInBytesExcluding: exclude];
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
return size;
}
+ (void) initialize
{
if (self == [GSSet class])
@ -529,26 +547,6 @@ static Class mutableSetClass;
(&map, state, stackbuf, len);
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = GSPrivateMemorySize(self, exclude);
if (size > 0)
{
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(&map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
size += GSIMapSize(&map) - sizeof(map);
while (node != 0)
{
size += [node->key.obj sizeInBytesExcluding: exclude];
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
}
return size;
}
@end
@implementation GSMutableSet

View file

@ -1964,25 +1964,6 @@ compare(id elem1, id elem2, void* context)
passingTest: predicate];
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = [super sizeInBytesExcluding: exclude];
if (size > 0)
{
NSUInteger count = [self count];
GS_BEGINIDBUF(objects, count);
size += count*sizeof(void*);
[self getObjects: objects];
while (count-- > 0)
{
size += [objects[count] sizeInBytesExcluding: exclude];
}
GS_ENDIDBUF();
}
return size;
}
@end

View file

@ -814,6 +814,28 @@ const NSHashTableCallBacks NSPointerToStructHashCallBacks =
@implementation NSConcreteHashTable
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
GSIMapTable map = (GSIMapTable)obj;
NSUInteger size = GSIMapSize(map) - sizeof(GSIMapTable);
/* If we knew that this table held objects, we could return their size...
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
while (node != 0)
{
size += [node->key.obj sizeInBytesExcluding: exclude];
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
*/
return size;
}
+ (void) initialize
{
if (concreteClass == Nil)
@ -1042,28 +1064,6 @@ const NSHashTableCallBacks NSPointerToStructHashCallBacks =
}
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = [super sizeInBytesExcluding: exclude];
if (size > 0)
{
/* If we knew that this table held objects, we could return their size...
*
* GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(self);
* GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
*
* while (node != 0)
* {
* node = GSIMapEnumeratorNextNode(&enumerator);
* size += [node->key.obj sizeInBytesExcluding: exclude];
* }
* GSIMapEndEnumerator(&enumerator);
*/
size += GSIMapSize(self) - instanceSize;
}
return size;
}
@end
@implementation NSConcreteHashTableEnumerator

View file

@ -1170,6 +1170,28 @@ const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks =
@implementation NSConcreteMapTable
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
GSIMapTable map = (GSIMapTable)obj;
NSUInteger size = GSIMapSize(map) - sizeof(GSIMapTable);
/* If we knew that this table held objects, we could return their size...
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
while (node != 0)
{
size += [node->key.obj sizeInBytesExcluding: exclude];
size += [node->value.obj sizeInBytesExcluding: exclude];
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
*/
return size;
}
+ (void) initialize
{
if (concreteClass == Nil)
@ -1400,29 +1422,6 @@ const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks =
return [p autorelease];
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = [super sizeInBytesExcluding: exclude];
if (size > 0)
{
/* If we knew that this table held objects, we could return their size...
*
* GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(self);
* GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
*
* while (node != 0)
* {
* node = GSIMapEnumeratorNextNode(&enumerator);
* size += [node->key.obj sizeInBytesExcluding: exclude];
* size += [node->value.obj sizeInBytesExcluding: exclude];
* }
* GSIMapEndEnumerator(&enumerator);
*/
size += GSIMapSize(self) - instanceSize;
}
return size;
}
@end
@implementation NSConcreteMapTableKeyEnumerator

View file

@ -509,6 +509,13 @@ failure:
*/
@implementation NSData
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
return [(NSData*)obj length];
}
+ (void) initialize
{
if (self == [NSData class])
@ -2012,17 +2019,6 @@ failure:
return NO;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = [super sizeInBytesExcluding: exclude];
if (size > 0)
{
size += [self length];
}
return size;
}
@end
/**
@ -2146,6 +2142,13 @@ failure:
}
}
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
return [(NSMutableData*)obj capacity];
}
+ (id) data
{
NSMutableData *d;
@ -3325,13 +3328,6 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
}
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = GSPrivateMemorySize(self, exclude);
return size;
}
@end
@ -3408,17 +3404,6 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
return self;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = GSPrivateMemorySize(self, exclude);
if (size > 0)
{
size += length;
}
return size;
}
@end
@implementation NSDataWithDeallocatorBlock
@ -4268,17 +4253,6 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
length = size;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = GSPrivateMemorySize(self, exclude);
if (size > 0)
{
size += capacity;
}
return size;
}
@end
@implementation NSMutableDataWithDeallocatorBlock

View file

@ -1229,31 +1229,6 @@ compareIt(id o1, id o2, void* context)
return 0;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = [super sizeInBytesExcluding: exclude];
if (size > 0)
{
NSUInteger count = [self count];
size += 3 * sizeof(void*) * count;
if (count > 0)
{
NSEnumerator *enumerator = [self keyEnumerator];
NSObject<NSCopying> *k = nil;
while ((k = [enumerator nextObject]) != nil)
{
NSObject *o = [self objectForKey: k];
size += [k sizeInBytesExcluding: exclude];
size += [o sizeInBytesExcluding: exclude];
}
}
}
return size;
}
@end

View file

@ -35,6 +35,7 @@
#import "Foundation/NSPort.h"
#import "Foundation/NSMethodSignature.h"
#import "Foundation/NSException.h"
#import "Foundation/NSHashTable.h"
#import "Foundation/NSInvocation.h"
#include <objc/Protocol.h>
#import "GSInvocation.h"
@ -829,6 +830,13 @@ GS_ROOT_CLASS @interface GSDistantObjectPlaceHolder
*/
@implementation NSDistantObject(GNUstepExtensions)
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
return 0;
}
/**
* Used by the garbage collection system to tidy up when a proxy is destroyed.
*/
@ -912,6 +920,19 @@ GS_ROOT_CLASS @interface GSDistantObjectPlaceHolder
{
return self;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
if (0 == NSHashGet(exclude, self))
{
Class c = object_getClass(self);
NSUInteger size = class_getInstanceSize(c);
return size;
}
return 0;
}
@end

View file

@ -2580,14 +2580,16 @@ GSPrivateMemorySize(NSObject *self, NSHashTable *exclude)
}
@implementation NSObject (MemoryFootprint)
+ (NSUInteger) contentSizeInBytesOf: (NSObject*)instance
excluding: (NSHashTable*)exclude
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
unsigned count;
Ivar *vars;
NSUInteger size = 0;
if (0 != (vars = class_copyIvarList(self, &count)))
if (0 != (vars = class_copyIvarList(cls, &count)))
{
while (count-- > 0)
{
@ -2596,11 +2598,11 @@ GSPrivateMemorySize(NSObject *self, NSHashTable *exclude)
type = GSSkipTypeQualifierAndLayoutInfo(type);
if ('@' == *type)
{
NSObject *obj = object_getIvar(instance, vars[count]);
NSObject *content = object_getIvar(obj, vars[count]);
if (obj != nil)
if (content != nil)
{
size += [obj sizeInBytesExcluding: exclude];
size += [content sizeInBytesExcluding: exclude];
}
}
}
@ -2608,10 +2610,24 @@ GSPrivateMemorySize(NSObject *self, NSHashTable *exclude)
}
return size;
}
+ (NSUInteger) sizeInBytes
{
return 0;
}
+ (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
return 0;
}
- (NSUInteger) sizeInBytes
{
NSUInteger bytes;
NSHashTable *exclude;
exclude = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 0);
bytes = [self sizeInBytesExcluding: exclude];
NSFreeHashTable(exclude);
return bytes;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
if (0 == NSHashGet(exclude, self))
@ -2624,9 +2640,11 @@ GSPrivateMemorySize(NSObject *self, NSHashTable *exclude)
{
while (c != Nil)
{
size += [c contentSizeInBytesOf: self excluding: exclude];
size += [c contentSizeOf: self
declaredIn: c
excluding: exclude];
c = class_getSuperclass(c);
}
c = class_getSuperclass(c);
}
return size;
}

View file

@ -31,6 +31,7 @@
#import "Foundation/NSMethodSignature.h"
#import "Foundation/NSAutoreleasePool.h"
#import "Foundation/NSException.h"
#import "Foundation/NSHashTable.h"
#import "Foundation/NSDistantObject.h"
#import "Foundation/NSPortCoder.h"
@ -84,6 +85,13 @@
return self;
}
+ (NSUInteger) contentSizeOf: (NSObject*)obj
declaredIn: (Class)cls
excluding: (NSHashTable*)exclude
{
return 0;
}
/**
* Returns the receiver.
*/
@ -549,6 +557,34 @@
return class_getSuperclass(object_getClass(self));
}
+ (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
return 0;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
if (0 == NSHashGet(exclude, self))
{
Class c = object_getClass(self);
NSUInteger size = class_getInstanceSize(c);
NSHashInsert(exclude, self);
if (size > 0)
{
while (c != Nil)
{
size += [c contentSizeOf: (NSObject*)self
declaredIn: c
excluding: exclude];
c = class_getSuperclass(c);
}
}
return size;
}
return 0;
}
/**
* Returns the zone in which the receiver was allocated.
*/

View file

@ -999,29 +999,6 @@ static Class NSMutableSet_concrete_class;
return 0;
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = [super sizeInBytesExcluding: exclude];
if (size > 0)
{
NSUInteger count = [self count];
size += 3 * sizeof(void*) * count;
if (count > 0)
{
NSEnumerator *enumerator = [self objectEnumerator];
NSObject *o;
while ((o = [enumerator nextObject]) != nil)
{
size += [o sizeInBytesExcluding: exclude];
}
}
}
return size;
}
@end

View file

@ -6239,17 +6239,6 @@ static NSFileManager *fm = nil;
return GSPropertyListFromStringsFormat(self);
}
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
{
NSUInteger size = [super sizeInBytesExcluding: exclude];
if (size > 0)
{
size += sizeof(unichar) * [self length];
}
return size;
}
/**
* Returns YES if the receiver contains string, otherwise, NO.
*/