|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.0 (the 'License'). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License." ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: /* ! 25: * objc-utils.m ! 26: * Copyright 1988, NeXT, Inc. ! 27: * Author: s. naroff ! 28: */ ! 29: #ifdef SHLIB ! 30: #import "shlib.h" ! 31: #endif ! 32: ! 33: #import "objc-private.h" ! 34: ! 35: #include <sys/time.h> ! 36: #include <sys/resource.h> ! 37: #include <stdio.h> ! 38: #include <time.h> ! 39: #include "objc-dispatch.h" ! 40: ! 41: #import "HashTable.h" ! 42: ! 43: ! 44: /* Return time used so far, in microseconds. */ ! 45: ! 46: int gettime (void) ! 47: { ! 48: struct rusage rusage; ! 49: ! 50: getrusage (0, &rusage); ! 51: return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec ! 52: + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec); ! 53: } ! 54: ! 55: void print_time (const char *str, int total, struct timeval *tv) ! 56: { ! 57: extern char **NXArgv; ! 58: ! 59: fprintf (stderr, ! 60: "time to `%s' for `%s':\n\t%7d.%06d (sys+usr)" ! 61: "\t%7ld.%01ld (real).\n", str, NXArgv[0], ! 62: total / 1000000, total % 1000000, ! 63: tv->tv_sec, tv->tv_usec/100000); ! 64: } ! 65: ! 66: static int cacheHits = 0; ! 67: static int cacheMisses = 0; ! 68: static int supercacheHits = 0; ! 69: static int supercacheMisses = 0; ! 70: ! 71: void _objc_msgCollectStats(MSG stackframe, int fromsuper, int cacheHit) ! 72: { ! 73: if (fromsuper) ! 74: cacheHit ? supercacheHits++ : supercacheMisses++; ! 75: else ! 76: cacheHit ? cacheHits++ : cacheMisses++; ! 77: } ! 78: ! 79: void _objc_msgPrintStats(void) ! 80: { ! 81: time_t tm = time(0); ! 82: ! 83: fprintf (stderr, "%s", ctime(&tm)); ! 84: fprintf (stderr, "maxSelector: %d\n", (int) _sel_getMaxUid()); ! 85: fprintf (stderr, " _msg: sent = %6d, %6d hits %6d misses", ! 86: cacheHits+cacheMisses, cacheHits,cacheMisses); ! 87: fprintf (stderr, " (%3.2f%%)\n", ! 88: ! 89: (float)cacheHits/(cacheHits+cacheMisses) * 100); ! 90: fprintf (stderr, " _msgSuper: sent = %6d, %6d hits %6d misses", ! 91: supercacheHits+supercacheMisses, supercacheHits,supercacheMisses); ! 92: fprintf (stderr, " (%3.2f%%)\n", ! 93: (float)supercacheHits/(supercacheHits+supercacheMisses) * 100); ! 94: ! 95: // reset ! 96: cacheHits = cacheMisses = supercacheHits = supercacheMisses = 0; ! 97: } ! 98: ! 99: int _objc_class_respondsTo(Class class) ! 100: { ! 101: Class super; ! 102: int nMethods = 0; ! 103: ! 104: if (class->methods) { ! 105: struct objc_method_list *catmethods = class->methods->method_next; ! 106: if (catmethods) { ! 107: do { ! 108: nMethods += catmethods->method_count; ! 109: catmethods = catmethods->method_next; ! 110: } while (catmethods); ! 111: } else { ! 112: nMethods += class->methods->method_count; ! 113: } ! 114: } ! 115: ! 116: for (super = class->super_class; super; super = super->super_class) ! 117: if (super->methods) { ! 118: struct objc_method_list *catmethods = super->methods->method_next; ! 119: if (catmethods) { ! 120: do { ! 121: nMethods += catmethods->method_count; ! 122: catmethods = catmethods->method_next; ! 123: } while (catmethods); ! 124: } else { ! 125: nMethods += super->methods->method_count; ! 126: } ! 127: } ! 128: return nMethods; ! 129: } ! 130: ! 131: /* ! 132: * Purpose: debug/analysis. ! 133: */ ! 134: void _objc_classPrintStats(int detail) ! 135: { ! 136: int n_meta = 0, b_meta = 0, n_class = 0, b_class = 0; ! 137: int n_classes = 0, n_classes_used = 0; ! 138: int n_class_responds = 0, n_meta_responds = 0; ! 139: int class_responds = 0, meta_responds = 0; ! 140: int n_class_implements = 0, n_meta_implements = 0; ! 141: int class_implements = 0, meta_implements = 0; ! 142: int n_categories = 0; ! 143: Class cls, oldvalue; ! 144: NXHashTable *class_hash; ! 145: NXHashState state; ! 146: void *page; ! 147: HashTable *pagehash = [HashTable newKeyDesc:"i"]; ! 148: ! 149: class_hash = objc_getClasses(); ! 150: state = NXInitHashState(class_hash); ! 151: ! 152: while (NXNextHashState(class_hash, &state, (void **)&cls)) { ! 153: ! 154: Class meta = cls->isa; ! 155: ! 156: n_classes++; ! 157: ! 158: // if (CLS_GETINFO(meta, CLS_INITIALIZED)) ! 159: { ! 160: if (CLS_GETINFO(meta, CLS_INITIALIZED)) ! 161: n_classes_used++; ! 162: ! 163: page = (void *)((unsigned int)cls - ((unsigned int)cls % 0x2000)); ! 164: oldvalue = [pagehash insertKey:page value:cls]; ! 165: ! 166: if (detail) ! 167: printf("`%s' (%p,page #%p):\n", cls->name, ! 168: cls, page); ! 169: ! 170: if (cls->methods) { ! 171: struct objc_method_list *catmethods; ! 172: ! 173: class_implements = cls->methods->method_count; ! 174: catmethods = cls->methods->method_next; ! 175: if (catmethods) { ! 176: n_categories = 0; ! 177: do { ! 178: class_implements += catmethods->method_count; ! 179: catmethods = catmethods->method_next; ! 180: if (catmethods) ! 181: n_categories++; ! 182: } while (catmethods); ! 183: } ! 184: } else { ! 185: class_implements = 0; ! 186: } ! 187: ! 188: //printf("n_categories = %d\n",n_categories); ! 189: ! 190: if (meta->methods) { ! 191: struct objc_method_list *catmethods; ! 192: ! 193: meta_implements = meta->methods->method_count; ! 194: catmethods = meta->methods->method_next; ! 195: if (catmethods) { ! 196: do { ! 197: meta_implements += catmethods->method_count; ! 198: catmethods = catmethods->method_next; ! 199: } while (catmethods); ! 200: } ! 201: } else { ! 202: meta_implements = 0; ! 203: } ! 204: ! 205: if (detail) ! 206: printf(" implements %d instance methods, %d class methods\n", ! 207: class_implements, meta_implements); ! 208: ! 209: n_class_implements += class_implements; ! 210: n_meta_implements += meta_implements; ! 211: ! 212: class_responds = _objc_class_respondsTo(cls); ! 213: meta_responds = _objc_class_respondsTo(meta); ! 214: ! 215: if (detail) ! 216: printf(" responds to %d instance methods, %d class methods\n", ! 217: class_responds, meta_responds); ! 218: ! 219: n_class_responds += class_responds; ! 220: n_meta_responds += meta_responds; ! 221: ! 222: if (cls->cache) ! 223: { ! 224: if (detail) { ! 225: printf(" using %u instance methods\n", cls->cache->occupied); ! 226: printf(" instance cache has %u slots, it is %3.2f%% full.\n", ! 227: cls->cache->mask+1, ! 228: (float)cls->cache->occupied/(cls->cache->mask+1) * 100); ! 229: } ! 230: b_class += sizeof(struct objc_cache) + ! 231: ((cls->cache->mask+1) * sizeof(Method)); ! 232: n_class++; ! 233: } ! 234: if (meta->cache) ! 235: { ! 236: if (detail) { ! 237: printf(" using %u class methods\n", meta->cache->occupied); ! 238: printf(" class cache has %u slots, it is %3.2f%% full.\n", ! 239: meta->cache->mask+1, ! 240: (float)meta->cache->occupied/(meta->cache->mask+1) * 100); ! 241: } ! 242: b_meta += sizeof(struct objc_cache) + ! 243: ((meta->cache->mask+1) * sizeof(Method)); ! 244: n_meta++; ! 245: } ! 246: } ! 247: } ! 248: { ! 249: Module *mods = objc_getModules(); ! 250: int catcnt = 0; ! 251: ! 252: while (*mods) { ! 253: int i, total = (*mods)->symtab->cls_def_cnt + ! 254: (*mods)->symtab->cat_def_cnt; ! 255: ! 256: catcnt += (*mods)->symtab->cat_def_cnt; ! 257: ! 258: /* add categories */ ! 259: for (i = (*mods)->symtab->cls_def_cnt; i < total; i++) { ! 260: //Category cat = (*mods)->symtab->defs[i]; ! 261: //printf("Category `%s' for Class `%s'.\n", cat->category_name, cat->class_name); ! 262: } ! 263: mods++; ! 264: } ! 265: printf("\nClass Info:\n\n"); ! 266: printf("%d classes (%d categories) - class descriptors spread across %u pages.\n", ! 267: n_classes, catcnt, [pagehash count]); ! 268: } ! 269: printf("%d classes currently in use\n", n_classes_used); ! 270: printf("%d instance methods, ",n_class_implements); ! 271: printf("%d instance responders\n",n_class_responds); ! 272: printf("%d class methods, ",n_meta_implements); ! 273: printf("%d class responders\n",n_meta_responds); ! 274: ! 275: if (n_class) { ! 276: printf("%d bytes allocated to cache instance methods ",b_class); ! 277: printf("(%d bytes per class)\n", ! 278: b_class/n_class); ! 279: } ! 280: if (n_meta) { ! 281: printf("%d bytes allocated to cache class methods ",b_meta); ! 282: printf("(%d bytes per meta class)\n", ! 283: b_meta/n_meta); ! 284: } ! 285: ! 286: { ! 287: Module *mods = objc_getModules(); ! 288: int selrefs = 0; ! 289: ! 290: while (*mods) { ! 291: int nsels = (*mods)->symtab->sel_ref_cnt; ! 292: #if 0 ! 293: int i; ! 294: for (i = 0; i < nsels; i++) ! 295: printf("refs[%d] = %s\n",i, ! 296: sel_getName((*mods)->symtab->refs[i])); ! 297: #endif ! 298: selrefs += nsels; ! 299: mods++; ! 300: } ! 301: ! 302: printf("\nSelector Info:\n\n"); ! 303: printf("%d selector references\n", selrefs); ! 304: printf("%d unique selectors\n", (int) _sel_getMaxUid()); ! 305: } ! 306: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.