Performance
Hi all, A performance related question: I've written a Cocoa app that continuously reads data from a USB device and plots it on a graph. It consists of three of my own classes. The first class is the model that submits asynchronous bulk reads to the USB device. The callback for these reads copies the received data from the buffer asynchronous filled by the request and into an NSData object that is allocated and added to an NSArray. The buffer that the asynchronous request was using is recycled into a new asynchronous request. So the pool of buffers is allocated once and reused while the NSData objects are continuously allocated and deallocated (when released by the controller). The second class is the view that uses an NSTimer to call [self setNeedsDisplay:YES] 24 times per second. The drawRect: method requests data from the data source (the third, controller class) and draws it with OpenGL. The third class is the controller class that serves as a data source for the view. When the view calls the giveMeData: method, the controller class calls the buffer: method in the model class, which removes and returns the oldest NSData object in its NSArray. The controller then does some computations on it and passes it off to the view in a new NSData object. The application runs pretty well, and running it through the Leaks instrument there are no leaks except for 16-bytes when the application is first starting caused by IOUSBLib. However, looking at it in the Activity Monitor, the real memory used starts off at 25 MB and steadily grows to 250+ MB while the virtual memory starts off at about the same and steadily grows to about the same or sometimes close to 500MB, over the course of several minutes. This especially happens if I don't move the mouse for a while, or don't have the application in focus. As soon as a move the mouse or bring the application into focus, it's as if an autorelease pool is drained and the memory drops back down to 30-40MB real and 30-40MB virtual. This is annoying since the application hangs for 5 seconds or so when this memory draining is occurring. Has anyone dealt with this before? Any ideas on what could be causing this and how to work around it? Another related question: The number of asynchronous requests that the driver submits at once and the maximum number of objects in the NSArray are set to some constant. Now in theory, the requests should be added and drained simultaneously (i.e. by separate threads), but if I make this constant larger, I notice a greater delay between when data entering the USB device and being plotted. It's as if the asynchronous requests are being filled and added to the NSArray all in a group, and then drained by the view all in a group... maybe? Is this something subtle from the way run loops work? Is the USB asynchronous bulk read run loop source on the same thread as the view class's drawRect method? My apologies for the length of this post and if the USB stuff isn't strictly Cocoa related, but since it's so intertwined with Cocoa classes, I figured this was the best place to ask. Advice is much appreciated. Please CC me on replies. Chris ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
usb notification
Hi all, Can't get a simple example working. AppearedNotificationHandler() should be called in the code below when a USB device (any device for now) is plugged in. I see the NSLog(@registerDeviceCallbackHandler) message appear in the console when I start the application, but never see the NSLog(@AppearedNotificationHandler) message when I plug in a device. What am I missing? Note: The project's MainMenu.nib Interface Builder file has an NSObject whose class is USBDriver. static void AppearedNotificationHandler (void * refCon, io_iterator_t iterator); @interface USBDriver(Private) - (void) registerDeviceCallbackHandler; @end @implementation USBDriver(Private) - (void) registerDeviceCallbackHandler { IOReturnkernErr; CFRunLoopSourceRef runLoopSource; CFMutableDictionaryRef matchingDict = IOServiceMatching (kIOUSBDeviceClassName); CFRunLoopRefrunLoop; // Create the port on which we will receive notifications. We'll wrap it in a runLoopSource // which we then feed into the runLoop for async event notifications. deviceNotifyPort = IONotificationPortCreate (kIOMasterPortDefault); if (deviceNotifyPort == NULL) { return; } // Get a runLoopSource for our mach port. runLoopSource = IONotificationPortGetRunLoopSource (deviceNotifyPort); matchingDict = (CFMutableDictionaryRef) CFRetain (matchingDict); kernErr = IOServiceAddMatchingNotification (deviceNotifyPort, kIOFirstMatchNotification, matchingDict, AppearedNotificationHandler, (void *) self, deviceAppearedIterator); kernErr = IOServiceAddMatchingNotification (deviceNotifyPort, kIOTerminatedNotification, matchingDict, DisappearedNotificationHandler, (void *) self, deviceDisappearedIterator ); // Get our runLoop runLoop = [[NSRunLoop currentRunLoop] getCFRunLoop]; // Add our runLoopSource to our runLoop CFRunLoopAddSource (runLoop, runLoopSource, kCFRunLoopDefaultMode); NSLog(@registerDeviceCallbackHandler); } @end @implementation USBDriver - (id) init { [super init]; if (self) { deviceNotifyPort= IO_OBJECT_NULL; deviceAppearedIterator = 0; [self registerDeviceCallbackHandler]; } return self; } @end static void AppearedNotificationHandler (void * refCon, io_iterator_t iterator) { NSLog(@AppearedNotificationHandler); } Any help is much appreciated. Thanks, Chris ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: usb notification
IOReturnkernErr; You never seem to check for errors. Please ensure your calls are succeeding by checking the value of this variable. If they're failing, use macerror(1) to look up the error number. IOServiceAddMatchingNotification() returns no errors (0). - (id) init { [super init]; if (self) { This is not the correct initializer pattern. You need to assign to self here. --Kyle Sluder Changed this to self = [super init]; However, the issue still persists. Chris ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
NSTableView bug?
Hello, I've created a simple application with an NSTableView. I have written a delegate for this table, numberOfRowsInTableView:objectValueForTableColumn:row:, that returns the number of rows in the table when requested. My application uses the table view to display hexadecimal data on a flash memory chip, with 16 bytes displayed per row. As a test, I tried returning a large number for the number of rows, 0x100. When I scroll through the table, everything looks okay for the first 14 million rows or so, after which the gray horizonal cell separator disappears and the row data begins to shift by a pixel per row, until it eventually is superimposed on the row above it. This seems like a bug with the NSTableView class, but perhaps I'm doing something wrong. Has anyone else run into this problem? Chris ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
instance management in IB
Hello, I've been scratching my head trying to get a basic delegate/data source Cocoa/AppKit program working and feel that I'm misunderstanding something basic (I've included the code is at the end). I set a breakpoint within the if statement in the init method of MyModel and see it called more than once. The second time the debugger throws a EXC_BAD_ACCESS. This message goes away if I comment out the two lines in stepAnimation that call the getBuffer and getLength methods and then modify the buffer. All this makes me think that somehow the instance of MyModel is being deallocated as soon as the data source message returns, but before the data is copied into the pointBuffer. I created an NSView and NSObject in Interface Builder, assigning the MyView subclass to the NSView object and MyModel to the NSObject object. Then I connected the dataSource outlet on MyView to th MyModel object. What am I missing? How can I get the data from MyModel to be viewable my MyView? Sidenote: Ultimately I'm trying to plot a real-time frequency spectrum. My plan is to pull in data over a CFMessagePort in the model and have the view access it view the data source. Help is much appreciated! Chris main.m -- int main(int argc, char *argv[]) { // Launch Cocoa application return NSApplicationMain(argc, (const char **) argv); } MyView.m: -- @implementation MyView - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { pointPath = [NSBezierPathbezierPath]; pointBuffer = malloc (sizeof(NSPoint) * 100); [NSTimerscheduledTimerWithTimeInterval:0.1 target:self selector:@selector(stepAnimation:) userInfo:nil repeats:YES]; } return self; } - (void)drawRect:(NSRect)rect { [pointPath removeAllPoints]; [pointPathappendBezierPathWithPoints:(NSPointArray)pointBuffercount:100]; [pointPathstroke]; } - (void)setDataSource:(id)inDataSource { dataSource = inDataSource; } - (id)dataSource { returndataSource; } - (void)stepAnimation:(NSTimer *)timer { float*inBuffer; int i, length; // Fetch buffer pointer inBuffer = [[self dataSource] getBuffer:self]; length = [[self dataSource] getLength:self]; // Copy to point buffer for (i = 0; i length; i++) { pointBuffer[i].y = inBuffer[i]; pointBuffer[i].x = i; } // Mark display for painting [selfsetNeedsDisplay:YES]; } - (void)dealloc { free(pointBuffer); [super dealloc]; } @end MyView.h -- @interface MyView : NSView { IBOutletid dataSource; NSBezierPath *pointPath; NSPoint *pointBuffer; } - (void)setDataSource:(id)inDataSource; - (id)dataSource; - (void)stepAnimation:(NSTimer *)timer; @end @interface NSObject(MyViewDataSource) - (float *)getBuffer:(MyView *)view; - (int)getLength:(MyView *)view; @end MyModel.m -- @implementationMyModel - (id)init { self= [superinit]; if (self) { buffer = malloc (sizeof(float) * 100); length = 100; } return self; } - (float *)getBuffer:(GraphView *)view { returnbuffer; } - (int)getLength:(GraphView *)view { returnlength; } - (void)dealloc { free (buffer); [super dealloc]; } @end MyModel.h -- @interface MyModel : NSObject { float *buffer; int length; } - (float *)getBuffer:(GraphView *)view; - (int)getLength:(GraphView *)view; @end ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: instance management in IB
Hi Jon, Thanks! That did the trick -- I was way off. Chris - Original Message From: Jonathan Hess jh...@apple.com To: Chris Carson cucar...@yahoo.com Cc: cocoa-dev@lists.apple.com Sent: Tuesday, May 12, 2009 1:19:11 AM Subject: Re: instance management in IB Hey Chris - This line pointPath = [NSBezierPath bezierPath]; in the init method creates an NSBezierPath instance that may (will!) be destroyed with the next autorelease pool flush. You should be creating your bezier path with pointPath = [[NSBezierPath alloc] init]; and then add a [pointPath release] to your dealloc method. http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html Good Luck - Jon Hess On May 11, 2009, at 6:29 PM, Chris Carson wrote: Hello, I've been scratching my head trying to get a basic delegate/data source Cocoa/AppKit program working and feel that I'm misunderstanding something basic (I've included the code is at the end). I set a breakpoint within the if statement in the init method of MyModel and see it called more than once. The second time the debugger throws a EXC_BAD_ACCESS. This message goes away if I comment out the two lines in stepAnimation that call the getBuffer and getLength methods and then modify the buffer. All this makes me think that somehow the instance of MyModel is being deallocated as soon as the data source message returns, but before the data is copied into the pointBuffer. I created an NSView and NSObject in Interface Builder, assigning the MyView subclass to the NSView object and MyModel to the NSObject object. Then I connected the dataSource outlet on MyView to th MyModel object. What am I missing? How can I get the data from MyModel to be viewable my MyView? Sidenote: Ultimately I'm trying to plot a real-time frequency spectrum. My plan is to pull in data over a CFMessagePort in the model and have the view access it view the data source. Help is much appreciated! Chris main.m -- int main(int argc, char *argv[]) { // Launch Cocoa application return NSApplicationMain(argc, (const char **) argv); } MyView.m: -- @implementation MyView - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { pointPath = [NSBezierPathbezierPath]; pointBuffer = malloc (sizeof(NSPoint) * 100); [NSTimerscheduledTimerWithTimeInterval:0.1 target:self selector:@selector(stepAnimation:) userInfo:nil repeats:YES]; } return self; } - (void)drawRect:(NSRect)rect { [pointPath removeAllPoints]; [pointPathappendBezierPathWithPoints:(NSPointArray)pointBuffercount:100]; [pointPathstroke]; } - (void)setDataSource:(id)inDataSource { dataSource = inDataSource; } - (id)dataSource { returndataSource; } - (void)stepAnimation:(NSTimer *)timer { float*inBuffer; int i, length; // Fetch buffer pointer inBuffer = [[self dataSource] getBuffer:self]; length = [[self dataSource] getLength:self]; // Copy to point buffer for (i = 0; i length; i++) { pointBuffer[i].y = inBuffer[i]; pointBuffer[i].x = i; } // Mark display for painting [selfsetNeedsDisplay:YES]; } - (void)dealloc { free(pointBuffer); [super dealloc]; } @end MyView.h -- @interface MyView : NSView { IBOutletid dataSource; NSBezierPath *pointPath; NSPoint *pointBuffer; } - (void)setDataSource:(id)inDataSource; - (id)dataSource; - (void)stepAnimation:(NSTimer *)timer; @end @interface NSObject(MyViewDataSource) - (float *)getBuffer:(MyView *)view; - (int)getLength:(MyView *)view; @end MyModel.m -- @implementationMyModel - (id)init { self= [superinit]; if (self) { buffer = malloc (sizeof(float) * 100); length = 100; } return self; } - (float *)getBuffer:(GraphView *)view { returnbuffer; } - (int)getLength:(GraphView *)view { returnlength; } - (void)dealloc { free (buffer); [super dealloc]; } @end MyModel.h -- @interface MyModel : NSObject { float *buffer; int length; } - (float *)getBuffer:(GraphView *)view; - (int)getLength:(GraphView *)view; @end ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/jhess%40apple.com This email sent to jh...@apple.com