Objective c NSMutableDictionary用于大型浮点数数据集

Objective c NSMutableDictionary用于大型浮点数数据集,objective-c,c,performance,hashmap,nsmutabledictionary,Objective C,C,Performance,Hashmap,Nsmutabledictionary,我有一些代码可以将一个大的(很多千兆字节)XML文件转换成另一种格式 除此之外,我需要在哈希表中存储一个或两个千兆字节的浮点值(每个条目两个浮点值),并使用int作为值的键 目前,我正在使用NSMutableDictionary和一个包含两个浮点的自定义类: // create the dictionary NSMutableDictionary *points = [[NSMutableDictionary alloc] init]; // add an entry (the data is

我有一些代码可以将一个大的(很多千兆字节)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 numberwhitint:][/code>一样,我确信我可以通过完全避免对象来降低内存使用率,但我对C编程知之甚少(这个项目肯定在教我!)

如何用高效的C数据结构替换
NSMuableDictionary
NSNumber
MyPoint
?没有任何第三方库依赖关系

我还希望能够将此数据结构写入磁盘上的文件,这样我就可以处理不完全适合内存的数据集,但我可能没有此功能

(对于那些不熟悉Objective-C的人,NSMutableDictionary类只能存储Obj-C对象,它的键也必须是对象。NSNumber和MyPoint是哑容器类,允许NSMutableDictionary使用浮点值和int值。)

编辑:

我已经尝试使用CFMutableDictionary来存储结构,如所示。当字典为空时,它的性能非常好。但随着字典的发展,它变得越来越慢。通过解析一个文件(字典中约有400万个条目),大约25%的文档开始嘎嘎作响,比文件中更早的部分慢两个数量级

NSMutableDictionary没有相同的性能问题。Instruments显示了大量应用哈希和比较字典键的活动(下面的
intEqual()
方法)。比较int很快,所以经常执行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, NULL, NULL, intEqual, intHash};
CFDictionaryValueCallBacks agPrimitveCoordValueCallBacks = {0, NULL /*agPrimitveCoordRetain*/, agPrimitveCoordRelease, NULL, agPrimitveCoordEqual};
temporaryNodeStore = CFDictionaryCreateMutable(NULL, 0, &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);
}
typedef结构{
浮动车床;
浮子离子;
}阿格德;
void agPrimitveCoordRelease(CFAllocatorRef分配器,const void*ptr){
CFAllocatorDeallocate(分配器,(AGPrimitiveCoord*)ptr);
}
布尔值agPrimitveCoordEqual(常量void*ptr1,常量void*ptr2){
AGPrimitiveCoord*p1=(AGPrimitiveCoord*)ptr1;
AGPrimitiveCoord*p2=(AGPrimitiveCoord*)ptr2;
返回值(fabsf(p1->lat-p2->lat)<0.0000001&&fabsf(p1->lon-p2->lon)<0.0000001);
}
布尔整数(常数void*ptr1,常数void*ptr2){
返回(int)ptr1==(int)ptr2;
}
CFHashCode intHash(const void*ptr){
返回(CFHashCode)((int)ptr);
}
//初始化存储字典
CFDictionaryKeyCallBacks intKeyCallBacks={0,NULL,NULL,NULL,intEqual,intHash};
CFDictionaryValueCallBacks agPrimitveCoordValueCallBacks={0,NULL/*agPrimitveCoordRetain*/,agPrimitveCoordRelease,NULL,agPrimitveCoordEqual};
temporaryNodeStore=CFDictionaryCreateMutable(NULL、0、&intKeyCallBacks和&agPrimitveCoordValueCallBacks);
//将一项添加到字典中
-(void)parserRecordNode:(int)nodeId lat:(float)lat lon:(float)lon
{
AGPrimitiveCoord*coordPtr=(AGPrimitiveCoord*)CFAllocatorAllocate(NULL,sizeof(AGPrimitiveCoord),0);
坐标->纬度=纬度;
coordPtr->lon=lon;
CFDictionarySetValue(临时节点存储,(void*)节点ID,coordPtr);
}
编辑2:

性能问题是由于苹果的示例代码中几乎无用的哈希实现造成的。我使用以下方法提高了性能:

// 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);
//来自的哈希算法http://burtleburtle.net/bob/hash/integer.html
uint32_t a=abs((int)ptr);
a=(a+0x7ed55d16)+(a19);

A=(A+0x165667 B1)+(A< P>这类东西,我只使用C++容器<代码> STD::无序的映射图和 STD::配对< /COD>。您可以在ObjtoVC++中使用它们。只需给您的文件一个<代码> mm >代码>扩展而不是通常的代码> M>代码>扩展。 更新

在你的评论中你说你以前从来没有做过C++。在这种情况下,你应该试试Kevin Ballard的回答<代码> CF字典>代码>,或者在标准库中查<代码> > HeCudie< /C>,<代码> H销毁< /COD>,和<代码> HSCACHE> <代码>函数。


如果您想要类似NSMutableDictionary的行为,但使用malloc'd内存,您可以下拉到(或者在您的情况下,)。它实际上是NSMutableDictionary的基础,但它允许一些自定义,即您可以告诉它您没有存储对象。当您调用
CFDictionaryCreateMutable()时
您为它提供了一个结构,该结构描述了您正在处理的值的类型(它包含指示它如何保留、释放、描述、散列和比较值的指针)。因此,如果您想使用包含两个浮点数的结构,并且您很乐意为每个结构使用malloc的内存,您可以malloc您的结构,填充它,并将其交给
CFDictionary
,然后您可以编写回调函数,使其与特定的结构一起工作。对键和对象的唯一限制是将
CFDictionary
与is一起使用,因为它们需要装入
void*

将.m文件重命名为.mm,然后切换到使用C++:

std::map<int, std::pair<float>> points;
std::映射点;

你能给我一个例子,说明如何定义一个无序的地图,添加一个条目,然后删除一个?我从来没有写过一行C++。当从几百兆字节的数据集随机访问值时,我应该期待什么样的性能?谢谢。我调查过,但是我不能把我的头放在人的页面上。y工作得很好。这个文件在部署后会改变吗?我正在考虑预处理。我永远不会在部署中使用这个代码。它是