1

我正在解析 XML 文件中的数据,并相信我找到了一个保留周期。我没有最好的理解如何解决它。简而言之,我正在解析一个块中的一堆浮点数,这导致我的内存使用量超过了 250 MB。不好。这是代码:

[TBXML iterateElementsForQuery:@"library_animations" fromElement:rootElement withBlock:^(TBXMLElement *anElement) {
        [self parseLibraryAnimationsElement:anElement];
}];

上面的方法调用了下面的方法:

- (void)parseLibraryAnimationsElement:(TBXMLElement *)element
{
    [TBXML iterateElementsForQuery:@"animation" fromElement:element withBlock:^(TBXMLElement *anElement) {
        TBXMLElement *extraElement = [TBXML childElementNamed:@"extra" parentElement:anElement];
        TBXMLElement *techniqueElement = [TBXML childElementNamed:@"technique" parentElement:extraElement];

        // grab float data
        **NSData *floatData = [self extractFloatArrayFromElement:techniqueElement];**

        // append data per animation ID
        NSString *key = [NSString stringWithFormat:@"#%@", [TBXML valueOfAttributeNamed:@"id" forElement:anElement]];
        [self.root.sortedAnimationKeys addObject:key];

        // use float data to store color information for this frame
        for (COLLADAMeshGeometry *geometry in self.root.geometries.allValues) {
            AGLKMesh *mesh = geometry.mesh;

            NSMutableData *dynamicColorData = [NSMutableData data];
            GLKVector3 *newColorInfo = (GLKVector3 *)[floatData bytes];

            // cycle through vertices for this mesh and use color float array information
            for (int i = 0; i < mesh.numberOfVertices; i++) {
                AGLKMeshVertex *staticVertex = [mesh vertexAtIndex:i];
                GLKVector3 newColor = newColorInfo[staticVertex->colorIndex];
                GLKVector4 color = GLKVector4Make(newColor.x, newColor.y, newColor.z, 1.0);

                [dynamicColorData appendBytes:&color length:sizeof(color)];
            }

            // get key and store in animation dictionary on the mesh
            [mesh.animationBufferDictionary setObject:dynamicColorData forKey:key];
        }
    }];

    // sort animation keys
    if (self.root.sortedAnimationKeys.count > 0) {
        [self.root.sortedAnimationKeys sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
    }
}

** ... ** 之间的方法也在下面。这就是我认为问题所在。字符串未正确释放。

- (NSData *)extractFloatArrayFromElement:(TBXMLElement *)element
{
    // element is <source>
    NSMutableData *floatData = [NSMutableData data];
    TBXMLElement *floatElement = [TBXML childElementNamed:@"float_array" parentElement:element];
    NSString *stringValues = [TBXML textForElement:floatElement];

    NSArray *values = [stringValues componentsSeparatedByString:@" "];
    for (NSString *value in values) {
        float floatValue = [value floatValue];
        [floatData appendBytes:&floatValue length:sizeof(floatValue)];
    }

    return floatData;
}

我说它在这里的某个地方,因为当我使用分配工具时,我会得到大量的 CFStrings,如下面的屏幕截图所示。我不确定这是否有足够的信息,但如果有人能看到任何问题,请告诉我。否则,也许我可以朝着正确的方向迈出一步。 在此处输入图像描述

当我深入到 CFString(不可变)行时,它有许多行是在[NSString componentsSeparatedByString:].

4

2 回答 2

0

改变这个:

- (NSData *)extractFloatArrayFromElement:(TBXMLElement *)element
{
    // element is <source>
    NSMutableData *floatData = [NSMutableData data];
    TBXMLElement *floatElement = [TBXML childElementNamed:@"float_array" parentElement:element];
    NSString *stringValues = [TBXML textForElement:floatElement];

    NSArray *values = [stringValues componentsSeparatedByString:@" "];
    for (NSString *value in values) {
        float floatValue = [value floatValue];
        [floatData appendBytes:&floatValue length:sizeof(floatValue)];
    }

    return floatData;
}

对此:

- (NSData *)extractFloatArrayFromElement:(TBXMLElement *)element
{
@autoreleasepool {
    // element is <source>
    NSMutableData *floatData = [NSMutableData data];
    TBXMLElement *floatElement = [TBXML childElementNamed:@"float_array" parentElement:element];
    NSString *stringValues = [TBXML textForElement:floatElement];

    NSArray *values = [stringValues componentsSeparatedByString:@" "];
    for (NSString *value in values) {
        float floatValue = [value floatValue];
        [floatData appendBytes:&floatValue length:sizeof(floatValue)];
    }

    return floatData;
}
}

这假设这componentsSeparatedByString:是大量自动释放对象的来源。如果这没有帮助,那么:

  • 按字节数对分配工具中的报告进行排序
  • 打开“仅跟踪活动对象”(或任何名称)
  • 打开“跟踪引用计数事件”
  • 单击对象,然后单击创建单个对象

这应该告诉您代码中的什么触发了分配。从那里开始,就是提高内存使用效率的问题。

于 2013-10-09T18:51:56.197 回答
0

这可能是一些自动释放池中的自动释放对象。

为了释放它们,将自动释放池放置在循环中,或者可能在您的extractFloatArrayFromElement方法中。

避免自动释放对象创建的另一个措施是避免类工厂方法,例如:

NSMutableData* autoreleasedObject = [NSMutableData data];

而是使用:

NSMutableData* data = [[NSMutableData alloc] init];
于 2013-10-09T18:10:37.730 回答