Fwd: non-linearly bad performance when encoding dictionaries?

  • > From: Alberto Ricart <aricart...>
    > Date: July 25, 2005 11:27:27 PM CDT
    > To: Michael B. Johnson <wave...>
    > Subject: Re: non-linearly bad performance when encoding dictionaries?
    >
    >
    > What version of OS X are you running?
    > If I run your code as you posted, I get fairly linear performance.
    >
    > If you substitute all your [NSMutableX x], for [[NSMutableX
    > allocWithZone:nil]init], and then bracketed with a [x release] when
    > done using/or adding I can improve the performance by a tiny bit
    > because you eliminate some messaging, but not enough to make any
    > difference. I AM encoding different (unique objects):
    >
    > 2005-07-25 23:06:18.714 Performance[2207] took  0.10 seconds to
    > encode 1000 objects
    > 2005-07-25 23:06:18.903 Performance[2207] took  0.16 seconds to
    > encode 2000 objects
    > 2005-07-25 23:06:19.175 Performance[2207] took  0.23 seconds to
    > encode 3000 objects
    > 2005-07-25 23:06:19.553 Performance[2207] took  0.33 seconds to
    > encode 4000 objects
    > 2005-07-25 23:06:20.026 Performance[2207] took  0.41 seconds to
    > encode 5000 objects
    > 2005-07-25 23:06:20.654 Performance[2207] took  0.55 seconds to
    > encode 6000 objects
    > 2005-07-25 23:06:21.317 Performance[2207] took  0.58 seconds to
    > encode 7000 objects
    > 2005-07-25 23:06:22.062 Performance[2207] took  0.65 seconds to
    > encode 8000 objects
    > 2005-07-25 23:06:22.954 Performance[2207] took  0.77 seconds to
    > encode 9000 objects
    >
    > for the same object, I get:
    >
    > 2005-07-25 23:13:30.145 Performance[2239] took  0.08 seconds to
    > encode 1000 objects
    > 2005-07-25 23:13:30.296 Performance[2239] took  0.13 seconds to
    > encode 2000 objects
    > 2005-07-25 23:13:30.520 Performance[2239] took  0.20 seconds to
    > encode 3000 objects
    > 2005-07-25 23:13:30.813 Performance[2239] took  0.27 seconds to
    > encode 4000 objects
    > 2005-07-25 23:13:31.186 Performance[2239] took  0.34 seconds to
    > encode 5000 objects
    > 2005-07-25 23:13:31.631 Performance[2239] took  0.41 seconds to
    > encode 6000 objects
    > 2005-07-25 23:13:32.155 Performance[2239] took  0.49 seconds to
    > encode 7000 objects
    > 2005-07-25 23:13:32.760 Performance[2239] took  0.56 seconds to
    > encode 8000 objects
    > 2005-07-25 23:13:33.449 Performance[2239] took  0.64 seconds to
    > encode 9000 objects
    >
    >
    > I am wondering if you are running into a memory issue where your
    > machine is starting to page, and that is really the issue you are
    > observing. Tweaking the initial size of the arrayk or dictionary
    > doesn't really improve performance much. If you run shark on it,
    > you find that 40% of the time is spent in the allocator, and
    > growing the dictionary (when values are getting removed).
    >
    > I think you are running into OS X's slow memory allocation. BTW, I
    > am running on a 1.67GHz G4, with 1.5GB of RAM.
    >
    >
    > /a
    >
    > On Jul 25, 2005, at 2:58 PM, Michael B. Johnson wrote:
    >
    >
    >> I'm assuming I'm doing something really stupid, and usually the
    >> best way to find it is to write a little program to show someone.
    >> Unfortunately, I've written the program, and I still don't see
    >> what I'm doing wrong.
    >>
    >> I've got a class that has a mutable dictionary in it.
    >> I have an array of N of these objects;
    >>
    >> The dictionary in each object has (say) a single entry with a
    >> key.  Note that it doesn't seem to matter much if that object is
    >> the same or unique among the array of these objects.
    >>
    >> I have an array of these simple objects,
    >> I  put that array in a dictionary.
    >> I then do an encodeWithCoder: on that dictionary using keyed
    >> coding.  The performance is pretty bad after about 1000 of them:
    >>
    >> 2005-07-25 12:30:12.211 EncodeBugCL[7252] took  0.48 seconds to
    >> encode 1000 objects
    >> 2005-07-25 12:30:14.562 EncodeBugCL[7252] took  2.34 seconds to
    >> encode 2000 objects
    >> 2005-07-25 12:30:18.632 EncodeBugCL[7252] took  4.05 seconds to
    >> encode 3000 objects
    >> 2005-07-25 12:30:27.431 EncodeBugCL[7252] took  8.76 seconds to
    >> encode 4000 objects
    >> 2005-07-25 12:30:47.366 EncodeBugCL[7252] took 19.89 seconds to
    >> encode 5000 objects
    >> 2005-07-25 12:31:10.564 EncodeBugCL[7252] took 23.14 seconds to
    >> encode 6000 objects
    >> 2005-07-25 12:31:38.528 EncodeBugCL[7252] took 27.90 seconds to
    >> encode 7000 objects
    >> 2005-07-25 12:32:35.041 EncodeBugCL[7252] took 56.43 seconds to
    >> encode 8000 objects
    >> 2005-07-25 12:33:42.335 EncodeBugCL[7252] took 67.20 seconds to
    >> encode 9000 objects
    >>
    >> If the object is the same it looks better, but still bad:
    >> 2005-07-25 12:39:28.485 EncodeBugCL[7287] took  0.49 seconds to
    >> encode 1000 objects
    >> 2005-07-25 12:39:30.246 EncodeBugCL[7287] took  1.75 seconds to
    >> encode 2000 objects
    >> 2005-07-25 12:39:34.952 EncodeBugCL[7287] took  4.68 seconds to
    >> encode 3000 objects
    >> 2005-07-25 12:39:46.002 EncodeBugCL[7287] took 11.01 seconds to
    >> encode 4000 objects
    >> 2005-07-25 12:39:59.725 EncodeBugCL[7287] took 13.69 seconds to
    >> encode 5000 objects
    >> 2005-07-25 12:40:18.462 EncodeBugCL[7287] took 18.66 seconds to
    >> encode 6000 objects
    >> 2005-07-25 12:40:52.035 EncodeBugCL[7287] took 33.51 seconds to
    >> encode 7000 objects
    >> 2005-07-25 12:41:30.208 EncodeBugCL[7287] took 38.10 seconds to
    >> encode 8000 objects
    >> 2005-07-25 12:42:14.975 EncodeBugCL[7287] took 44.69 seconds to
    >> encode 9000 objects
    >>
    >> Just to be clear, if I don't add anything to the properties
    >> dictionary, here's what it looks like:
    >>
    >> 2005-07-25 12:43:25.350 EncodeBugCL[7309] took  0.08 seconds to
    >> encode 1000 objects
    >> 2005-07-25 12:43:25.514 EncodeBugCL[7309] took  0.14 seconds to
    >> encode 2000 objects
    >> 2005-07-25 12:43:25.697 EncodeBugCL[7309] took  0.15 seconds to
    >> encode 3000 objects
    >> 2005-07-25 12:43:25.942 EncodeBugCL[7309] took  0.20 seconds to
    >> encode 4000 objects
    >> 2005-07-25 12:43:26.226 EncodeBugCL[7309] took  0.25 seconds to
    >> encode 5000 objects
    >> 2005-07-25 12:43:26.562 EncodeBugCL[7309] took  0.29 seconds to
    >> encode 6000 objects
    >> 2005-07-25 12:43:27.007 EncodeBugCL[7309] took  0.39 seconds to
    >> encode 7000 objects
    >> 2005-07-25 12:43:27.481 EncodeBugCL[7309] took  0.42 seconds to
    >> encode 8000 objects
    >> 2005-07-25 12:43:28.034 EncodeBugCL[7309] took  0.49 seconds to
    >> encode 9000 objects
    >>
    >>
    >>
    >> Here's the code for a main.m to show it:
    >>
    >> #import <Foundation/Foundation.h>
    >> #include <sys/time.h>
    >> #include <sys/types.h>
    >> #include <unistd.h>
    >>
    >> static double _getCurrentTime_(void){
    >> struct timeval v;
    >> double seconds;
    >> double useconds;
    >>
    >> gettimeofday(&v, NULL);
    >> seconds = v.tv_sec;
    >> useconds = (1.0e-6) * v.tv_usec;
    >> seconds += useconds;
    >> return seconds;
    >> }
    >>
    >> @interface MyElement : NSObject {
    >> NSMutableDictionary* _properties;
    >> }
    >> @end
    >>
    >>
    >> @implementation MyElement
    >> - init {
    >> [super init];
    >> _properties = [[NSMutableDictionary dictionary] retain];
    >> // make them the same:
    >> NSString* str = [NSString stringWithFormat:@"why is this slow?"];
    >> // make them all different:
    >> //NSString* str = [NSString stringWithFormat:@"%p", self];
    >> [_properties setObject:str forKey:@"anyOldKey"];
    >> return self;
    >> }
    >>
    >> - (NSDictionary*)properties {
    >> return _properties;
    >> }
    >>
    >> - (void)encodeWithCoder:(NSCoder *)encoder {
    >> if ([encoder allowsKeyedCoding]) {
    >> NSKeyedArchiver* coder = (NSKeyedArchiver*)encoder;
    >> [coder encodeObject:[self properties]
    >> forKey:@"MyElement__properties"];
    >> } else {
    >> NSLog(@"MyElement only supports keyed coding");
    >> }
    >> }
    >> @end
    >>
    >>
    >> encode(unsigned int count) {
    >> NSMutableDictionary* stuff = [NSMutableDictionary dictionary];
    >> NSMutableArray* elements = [NSMutableArray array];
    >> unsigned int i;
    >>
    >> for (i = 0; i < count; i++) {
    >> MyElement* e = [[[MyElement alloc] init] autorelease];
    >> [elements addObject:e];
    >> }
    >> [stuff setObject:elements forKey:@"elements"];
    >>
    >> double startTime = _getCurrentTime_();
    >> NSData* data = [NSKeyedArchiver
    >> archivedDataWithRootObject:stuff];
    >> double duration = _getCurrentTime_() - startTime;
    >> NSLog(@"took %5.2f seconds to encode %d objects", duration,
    >> count);
    >> }
    >>
    >>
    >>
    >> int main (int argc, const char * argv[]) {
    >> NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    >> unsigned int i, howMany = 10;
    >>
    >> for (i = 1; i < howMany; i++) {
    >> NSAutoreleasePool* pool2 = [[NSAutoreleasePool alloc] init];
    >> unsigned int count = i * 1000;
    >> encode(count);
    >> [pool2 release];
    >> }
    >>
    >> [pool release];
    >> return 0;
    >> }
    >>
    >>
    >>
    >>
    >> --> Michael B. Johnson, PhD
    >> --> http://homepage.mac.com/drwave (personal)
    >> --> http://xenia.media.mit.edu/~wave (alum)
    >> --> MPG Lead
    >> --> Pixar Animation Studios
    >>
    >> _______________________________________________
    >> MacOSX-dev mailing list
    >> <MacOSX-dev...>
    >> http://www.omnigroup.com/mailman/listinfo/macosx-dev
    >>
    >>
    >>
    >>
    >
    >