objective-c – NSMutableDictionary用于大型浮点数据集
我有一些代码将大型(许多千兆字节)
XML文件转换为另一种格式.
除此之外,我需要在哈希表中存储一个或两个千兆字节的浮点数(每个条目有两个浮点数),并使用int作为值的键. 目前,我正在使用NSMutableDictionary和一个包含两个浮点数的自定义类: // create the dictionary NSMutableDictionary *points = [[NSMutableDictionary alloc] init]; // add an entry (the data is read from an XML file using libxml) int pointId = 213453; float x = 42.313554; float y = -21.135213; MyPoint *point = [[MyPoint alloc] initWithX:x Y:y]; [points setObject:point forKey:[NSNumber numberWithInt:pointId]]; [point release]; // retrieve an entry (this happens later on while parsing the same XML file) int pointId = 213453; float x; float y; MyPoint *point = [points objectForKey:[NSNumber numberWithInt:pointId]]; x = point.x; y = point.y; 这个数据集使用我正在使用的XML文件消耗大约800MB的RAM,并且执行需要相当长的时间.我希望有更好的性能,但更重要的是我需要降低内存消耗,以便我可以处理更大的XML文件. objc_msg_send就在代码的配置文件中,就像 – [NSNumber numberWithInt:],我确信我可以通过完全避免对象来减少内存使用量,但我对C编程知之甚少(这个项目肯定教我!). 如何用高效的C数据结构替换NSMuableDictionary,NSNumber MyPoint?没有任何第三方库依赖? 我也希望能够将这个数据结构写入磁盘上的文件,因此我可以使用不完全适合内存的数据集,但我可能没有这种功能. (对于不熟悉Objective-C的人,NSMutableDictionary类只能存储Obj-C对象,键也必须是对象.NSNumber和MyPoint是哑容器类,允许NSMutableDictionary使用float和int值.) 编辑: 我已经尝试使用CFMutableDictionary来存储结构,按照apple’s sample code.当字典为空时,它表现很好.但随着字典的增长,它变得越来越慢.大约25%通过解析文件(字典中约400万个项目),它开始突然变慢,比文件中的早先慢两个数量级. NSMutableDictionary没有相同的性能问题. Instruments演示了许多应用哈希值和比较字典键的活动(下面的intEqual()方法).比较一个int很快,所以经常执行它是非常错误的. 这是我创建字典的代码: typedef struct { float lat; float lon; } AGPrimitiveCoord; void agPrimitveCoordRelease(CFAllocatorRef allocator,const void *ptr) { CFAllocatorDeallocate(allocator,(AGPrimitiveCoord *)ptr); } Boolean agPrimitveCoordEqual(const void *ptr1,const void *ptr2) { AGPrimitiveCoord *p1 = (AGPrimitiveCoord *)ptr1; AGPrimitiveCoord *p2 = (AGPrimitiveCoord *)ptr2; return (fabsf(p1->lat - p2->lat) < 0.0000001 && fabsf(p1->lon - p2->lon) < 0.0000001); } Boolean intEqual(const void *ptr1,const void *ptr2) { return (int)ptr1 == (int)ptr2; } CFHashCode intHash(const void *ptr) { return (CFHashCode)((int)ptr); } // init storage dictionary CFDictionaryKeyCallBacks intKeyCallBacks = {0,NULL,intEqual,intHash}; CFDictionaryValueCallBacks agPrimitveCoordValueCallBacks = {0,NULL /*agPrimitveCoordRetain*/,agPrimitveCoordRelease,agPrimitveCoordEqual}; temporaryNodeStore = CFDictionaryCreateMutable(NULL,&intKeyCallBacks,&agPrimitveCoordValueCallBacks); // add an item to the dictionary - (void)parserRecordNode:(int)nodeId lat:(float)lat lon:(float)lon { AGPrimitiveCoord *coordPtr = (AGPrimitiveCoord *)CFAllocatorAllocate(NULL,sizeof(AGPrimitiveCoord),0); coordPtr->lat = lat; coordPtr->lon = lon; CFDictionarySetValue(temporaryNodeStore,(void *)nodeId,coordPtr); } 编辑2: 性能问题是由于Apple的示例代码中几乎无用的哈希实现.我通过使用以下方式获得了性能提升: // hash algorithm from http://burtleburtle.net/bob/hash/integer.html uint32_t a = abs((int)ptr); a = (a+0x7ed55d16) + (a<<12); a = (a^0xc761c23c) ^ (a>>19); a = (a+0x165667b1) + (a<<5); a = (a+0xd3a2646c) ^ (a<<9); a = (a+0xfd7046c5) + (a<<3); a = (a^0xb55a4f09) ^ (a>>16); 解决方法
如果你想要类似NSMutableDictionary的行为,但有malloc’d内存,你可以下拉到
CFDictionary(或者你的情况下,CFMutableDictionary).它实际上是NSMutableDictionary的基础,但它允许一些自定义,即你可以告诉它你没有存储对象.当你调用CFDictionaryCreateMutable()时,你给它一个结构来描述你正在处理它的值(它包含指示它如何保留,释放,描述,散列和比较你的值的指针).因此,如果你想使用包含两个浮点数的结构,并且你很高兴为每个结构使用malloc内存,你可以对你的结构进行malloc,填充它,然后将它交给CFDictionary,然后你可以编写回调函数这样他们就可以使用你的特定结构.对CFDictionary使用的键和对象的唯一限制是它们需要适合void *.
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |