导致内存增长的持久分配
Persistent allocations causing memory growth
我一直在使用 Instruments 来尝试减少我的应用程序的内存占用。 运行 在 "Profile" 模式下选择 Leaks 选项同时标记世代,我注意到我的 SQLite 数据库 class 正在保留导致内存增长的变量。由于我的应用程序将在其更新过程中调用这些函数数千次,因此它开始变成一个更大的问题。
第一个函数只是准备 SQL 语句并绑定可能存在的任何变量:
- (BOOL)prepare:(NSString *)sql withBindings:(NSArray *)bindings {
if (! sqlite3_prepare_v2(_db, [sql UTF8String], -1, &_statement, NULL) == SQLITE_OK) {
return NO;
}
for (int i = 0; i < [bindings count]; i++) {
sqlite3_bind_text(_statement,
i + 1,
[bindings[i] isKindOfClass:[NSNull class]]
? [@"" UTF8String]
: [bindings[i] UTF8String],
-1,
SQLITE_TRANSIENT);
}
return YES;
}
其中提供了以下信息:
- 0 libsystem_malloc.dylib malloc_zone_malloc
- 1 libsqlite3.dylib 0x1958cf588
- 2 libsqlite3.dylib 0x1958d7f68
- 3 libsqlite3.dylib 0x19591cc58
- 4 libsqlite3.dylib 0x195905728
- 5 libsqlite3.dylib 0x1958d0614
- 6 libsqlite3.dylib 0x19592a934
- 7 app -[Db prepare:withBindings:] app/Db.m:68
- 8个应用-[更新update] app/Update.m:208
- 9 应用程序 __57-[AppDelegate application:didFinishLaunchingWithOptions:]_block_invoke_2 app/AppDelegate.m:70
- 10 libdispatch.dylib _dispatch_call_block_and_release
- 11 libdispatch.dylib _dispatch_client_callout
- 12 libdispatch.dylib _dispatch_queue_drain
- 13 libdispatch.dylib _dispatch_queue_invoke
- 14 libdispatch.dylib _dispatch_root_queue_drain
- 15 libdispatch.dylib _dispatch_worker_thread3
- 16 libsystem_pthread.dylib _pthread_wqthread
- 17 libsystem_pthread.dylib start_wqthread
第二个函数简单地遍历行:
- (BOOL)stepThrough {
return sqlite3_step(_statement) == SQLITE_ROW;
}
其中提供了以下信息:
- 0 libsystem_malloc.dylib malloc_zone_malloc
- 1 libsqlite3.dylib 0x1958cf588
- 2 libsqlite3.dylib 0x1958d7f68
- 3 libsqlite3.dylib 0x19591cc58
- 4 libsqlite3.dylib 0x195905728
- 5 libsqlite3.dylib 0x195914a0c
- 6 libsqlite3.dylib 0x195906dc8
- 7 libsqlite3.dylib sqlite3_step
- 8 poc -[Db stepThrough] app/Db.m:79
- 9 poc -[update更新] app/Update.m:208
- 10 poc __57-[AppDelegate application:didFinishLaunchingWithOptions:]_block_invoke_2 app/AppDelegate.m:70
- 11 libdispatch.dylib _dispatch_call_block_and_release
- 12 libdispatch.dylib _dispatch_client_callout
- 13 libdispatch.dylib _dispatch_main_queue_callback_4CF
- 14 个核心基础 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE_
- 15 个核心基础 __CFRunLoopRun
- 16 CoreFoundation CFRunLoopRunSpecific
- 17 个图形服务 GSEventRunModal
- 18 UIKit UIApplicationMain
- 19 poc 主app/main.m:16
- 20 libdyld.dylib 开始
希望这些信息足以让某人说 "Oh, you've an extra retain count there",但如果您需要更多信息,请告诉我。
我发现了我的问题 - 我没有在保留内存的准备好的语句上调用 sqlite3_finalize
。在我调用这个之后,我的内存使用率急剧下降。
编辑 更详细一点,一旦我完成查询,然后我 运行 我创建了一个新函数来清理所有内存:
- (void)finalise {
sqlite3_finalize(_statement);
}
我的应用程序看起来像这样:
Db * db = [[Db alloc] init];
[db prepare:@"SELECT * FROM `table`" withBindings:@[]];
while ([db stepThrough]) {
// Do something with data here
}
[db finalise];
我一直在使用 Instruments 来尝试减少我的应用程序的内存占用。 运行 在 "Profile" 模式下选择 Leaks 选项同时标记世代,我注意到我的 SQLite 数据库 class 正在保留导致内存增长的变量。由于我的应用程序将在其更新过程中调用这些函数数千次,因此它开始变成一个更大的问题。
第一个函数只是准备 SQL 语句并绑定可能存在的任何变量:
- (BOOL)prepare:(NSString *)sql withBindings:(NSArray *)bindings {
if (! sqlite3_prepare_v2(_db, [sql UTF8String], -1, &_statement, NULL) == SQLITE_OK) {
return NO;
}
for (int i = 0; i < [bindings count]; i++) {
sqlite3_bind_text(_statement,
i + 1,
[bindings[i] isKindOfClass:[NSNull class]]
? [@"" UTF8String]
: [bindings[i] UTF8String],
-1,
SQLITE_TRANSIENT);
}
return YES;
}
其中提供了以下信息:
- 0 libsystem_malloc.dylib malloc_zone_malloc
- 1 libsqlite3.dylib 0x1958cf588
- 2 libsqlite3.dylib 0x1958d7f68
- 3 libsqlite3.dylib 0x19591cc58
- 4 libsqlite3.dylib 0x195905728
- 5 libsqlite3.dylib 0x1958d0614
- 6 libsqlite3.dylib 0x19592a934
- 7 app -[Db prepare:withBindings:] app/Db.m:68
- 8个应用-[更新update] app/Update.m:208
- 9 应用程序 __57-[AppDelegate application:didFinishLaunchingWithOptions:]_block_invoke_2 app/AppDelegate.m:70
- 10 libdispatch.dylib _dispatch_call_block_and_release
- 11 libdispatch.dylib _dispatch_client_callout
- 12 libdispatch.dylib _dispatch_queue_drain
- 13 libdispatch.dylib _dispatch_queue_invoke
- 14 libdispatch.dylib _dispatch_root_queue_drain
- 15 libdispatch.dylib _dispatch_worker_thread3
- 16 libsystem_pthread.dylib _pthread_wqthread
- 17 libsystem_pthread.dylib start_wqthread
第二个函数简单地遍历行:
- (BOOL)stepThrough {
return sqlite3_step(_statement) == SQLITE_ROW;
}
其中提供了以下信息:
- 0 libsystem_malloc.dylib malloc_zone_malloc
- 1 libsqlite3.dylib 0x1958cf588
- 2 libsqlite3.dylib 0x1958d7f68
- 3 libsqlite3.dylib 0x19591cc58
- 4 libsqlite3.dylib 0x195905728
- 5 libsqlite3.dylib 0x195914a0c
- 6 libsqlite3.dylib 0x195906dc8
- 7 libsqlite3.dylib sqlite3_step
- 8 poc -[Db stepThrough] app/Db.m:79
- 9 poc -[update更新] app/Update.m:208
- 10 poc __57-[AppDelegate application:didFinishLaunchingWithOptions:]_block_invoke_2 app/AppDelegate.m:70
- 11 libdispatch.dylib _dispatch_call_block_and_release
- 12 libdispatch.dylib _dispatch_client_callout
- 13 libdispatch.dylib _dispatch_main_queue_callback_4CF
- 14 个核心基础 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE_
- 15 个核心基础 __CFRunLoopRun
- 16 CoreFoundation CFRunLoopRunSpecific
- 17 个图形服务 GSEventRunModal
- 18 UIKit UIApplicationMain
- 19 poc 主app/main.m:16
- 20 libdyld.dylib 开始
希望这些信息足以让某人说 "Oh, you've an extra retain count there",但如果您需要更多信息,请告诉我。
我发现了我的问题 - 我没有在保留内存的准备好的语句上调用 sqlite3_finalize
。在我调用这个之后,我的内存使用率急剧下降。
编辑 更详细一点,一旦我完成查询,然后我 运行 我创建了一个新函数来清理所有内存:
- (void)finalise {
sqlite3_finalize(_statement);
}
我的应用程序看起来像这样:
Db * db = [[Db alloc] init];
[db prepare:@"SELECT * FROM `table`" withBindings:@[]];
while ([db stepThrough]) {
// Do something with data here
}
[db finalise];