Ok, I've been experimenting off and on. My loop is this (some #if's and stuff removed); proxy is just a normal remoteObjectProxy on the XPC connection, with an error handler just for logging:
int counter = 0;
while (self.stopRun == NO) {
NSNumber *objNum;
size_t dataLength = arc4random() % 16384;
void *dataBuffer = malloc(dataLength);
NSData *data = nil;
@synchronized (self) {
objNum = [NSNumber numberWithUnsignedLongLong:self.count++];
}
NSString *objName = [NSString stringWithFormat:@"Object %@", objNum];
if (dataBuffer != NULL) {
arc4random_buf(dataBuffer, dataLength);
data = [NSData dataWithBytesNoCopy:dataBuffer length:dataLength freeWhenDone:YES];
}
TestObject *to = [TestObject name:objName data:data];
[proxy logDataWithEntry:to];
if ((counter++ & 0x7ff) == 0) {
dispatch_semaphore_t sempaphore = dispatch_semaphore_create(0);
[self.connection scheduleSendBarrierBlock:^{
printf("In schedule block\n");
dispatch_semaphore_signal(sempaphore);
[self updateBandwidth];
return;
}];
dispatch_semaphore_wait(sempaphore, DISPATCH_TIME_FOREVER);
printf("Done with lock");
}
}
});
Some screenshots from Instruments -- the allocation graph during the runtime, and then the source code with its annotation for allocation size
In the allocation graph, once it exits out of the loop, the memory use goes back to (delightfully!) 0. Until then, however, it doesn't seem to be dong any releasing of memory. The output of both top and Activity Monitor match the allocation size and behavior.
Until! If I put an autorelease pool inside the entire contents of the loop, then... it grows, albeit much more slowly. It also runs much faster, which indicates (to me) that Instruments is interfering with it enough to change its behavior.
So, in summary: I am still deeply confused about how ARC is reaping when I use it with XPC. 😄
(Our actual application gets into hundreds of mbytes fairly quickly; I've already tried adding in a barrier call.)