mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
improve reportingn of memory usage
This commit is contained in:
parent
42b404c586
commit
3f7d54a33f
18 changed files with 395 additions and 267 deletions
24
ChangeLog
24
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue