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

@ -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.
*/