- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一些代码可以将一个大的(许多 GB 的)XML 文件转换成另一种格式。
除其他事项外,我需要在哈希表中存储一或两千兆字节的 float (每个条目两个 float ),并使用一个 int 作为值的键。
目前,我正在使用 NSMutableDictionary 和一个包含两个 float 的自定义类:
// 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, 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);
}
编辑 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 内存,你可以下拉到 CFDictionary (或者在您的情况下, CFMutableDictionary )。它实际上是 NSMutableDictionary 的基础,但它允许一些自定义,即您可以告诉它您没有存储对象。当你调用 CFDictionaryCreateMutable()
时,你给它一个结构来描述你传递给它的值类型(它包含告诉它如何保留、释放、描述、散列和比较你的值的指针).所以如果你想使用一个包含两个 float 的结构,并且你很高兴为每个结构使用 malloc 内存,你可以 malloc 你的结构,填充它,然后把它交给 CFDictionary
,然后然后你可以编写回调函数,使它们与你的特定结构一起工作。您可以使用 CFDictionary
的键和对象的唯一限制是它们需要放在 void *
中。
关于objective-c - NSMutableDictionary 用于巨大的 float 数据集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8936428/
我遵循了一本名为“Sitepoint Full Stack Javascript with MEAN”的书中的教程,我刚刚完成了第 6 章,应该已经创建了一个带有“数据库”的“服务器”。数据库只不过是
在 Jquery 中,我创建两个数组,一个嵌入另一个数组,就像这样...... arrayOne = [{name:'a',value:1}, {name:'b',value:2}] var arra
这个问题在这里已经有了答案: What is the explanation for these bizarre JavaScript behaviours mentioned in the 'Wa
我被放在别人的代码上,有一个类用作其他组件的基础。当我尝试 ng serve --aot(或 build --prod)时,我得到以下信息。 @Component({ ...,
我正在测试一些代码,并使用数据创建了一个 json 文件。 问题是我在警报中收到“[object Object],[object Object]”。没有数据。 我做错了什么? 这是代码:
我想打印 [object Object],[object Object] 以明智地 "[[{ 'x': '1', 'y': '0' }, { 'x': '2', 'y': '1' }]]"; 在 ja
我有一个功能 View ,我正在尝试以特殊格式的方式输出。但我无法让列表功能正常工作。 我得到的唯一返回是[object Object][object Object] [object Object]
在使用优秀的 Sim.js 和 Three.js 库处理 WebGL 项目时,我偶然发现了下一个问题: 一路走来,它使用了 THREE.Ray 的下一个构造函数: var ray = new THRE
我正在使用 Material UI 进行多重选择。这是我的代码。 {listStates.map(col => (
我的代码使用ajax: $("#keyword").keyup(function() { var keyword = $("#keyword").val(); if (keyword.
我遇到了下一个错误,无法理解如何解决它。 Can't resolve all parameters for AuthenticationService: ([object Object], ?, [o
我正在尝试创建一个显示动态复选框的表单,至少应选中其中一个才能继续。我还需要获取一组选中的复选框。 这是组件的代码: import { Component, OnInit } from '@angul
我正在开发 NodeJs 应用程序,它是博客应用程序。我使用了快速验证器,我尝试在 UI 端使用快速闪存消息将帖子保存在数据库中之前使用闪存消息验证数据,我成功地将数据保存在数据库中,但在提交表单后消
我知道有些人问了同样的问题并得到了解答。我已经查看了所有这些,但仍然无法解决我的问题。我有一个 jquery snipet,它将值发送到处理程序,处理程序处理来自 JS 的值并将数据作为 JSON 数
我继承了一个非常草率的项目,我的任务是解释为什么它不好。我注意到他们在整个代码中都进行了这样的比较 (IQueryable).FirstOrDefault(x => x.Facility == fac
我只是在删除数组中的对象时偶然发现了这一点。 代码如下: friends = []; friends.push( { a: 'Nexus', b: 'Muffi
这两个代码片段有什么区别: object = nil; [object release] 对比 [object release]; object = nil; 哪个是最佳实践? 最佳答案 object
我应该为其他人将从中继承的第一个父对象传递哪个参数,哪个参数更有效 Object.create(Object.prototype) Object.create(Object) Object.creat
我在不同的对象上安排不同的选择器 [self performSelector:@selector(doSmth) withObject:objectA afterDelay:1]; [self per
NSLog(@"%p", &object); 和 NSLog(@"%p", object); 有什么区别? 两者似乎都打印出一个内存地址,但我不确定哪个是对象的实际内存地址。 最佳答案 这就是我喜欢的
我是一名优秀的程序员,十分优秀!