// // JXPerformanceTests.m // AICityTests // // Feature: 003-ios-api-https // 剧星平台性能测试 // #import #import "JXPlaybackProgressStorage.h" #import "JXCountFormatter.h" @interface JXPerformanceTests : XCTestCase @property (nonatomic, strong) JXPlaybackProgressStorage *storage; @end @implementation JXPerformanceTests - (void)setUp { [super setUp]; self.storage = [JXPlaybackProgressStorage sharedStorage]; [self.storage clearAll]; } - (void)tearDown { [self.storage clearAll]; [super tearDown]; } #pragma mark - 存储性能测试 - (void)testPerformanceSingleProgressSave { [self measureBlock:^{ NSString *episodeId = [NSString stringWithFormat:@"perf_ep_%d", arc4random()]; [self.storage saveProgressWithEpisodeId:episodeId dramaId:@"perf_drama" position:arc4random() % 120000 duration:120000 isCompleted:NO synced:NO completion:nil]; }]; } - (void)testPerformanceBatchProgressSave { [self measureBlock:^{ for (int i = 0; i < 100; i++) { NSString *episodeId = [NSString stringWithFormat:@"batch_ep_%d", i]; [self.storage saveProgressWithEpisodeId:episodeId dramaId:@"batch_drama" position:arc4random() % 120000 duration:120000 isCompleted:NO synced:NO completion:nil]; } }]; } - (void)testPerformanceProgressQuery { // 准备测试数据 for (int i = 0; i < 1000; i++) { NSString *episodeId = [NSString stringWithFormat:@"query_ep_%d", i]; [self.storage saveProgressWithEpisodeId:episodeId dramaId:@"query_drama" position:arc4random() % 120000 duration:120000 isCompleted:NO synced:arc4random() % 2 == 0 completion:nil]; } [self measureBlock:^{ NSString *randomEpisodeId = [NSString stringWithFormat:@"query_ep_%d", arc4random() % 1000]; [self.storage getProgressWithEpisodeId:randomEpisodeId]; }]; } - (void)testPerformanceDramaProgressQuery { // 准备测试数据 for (int i = 0; i < 500; i++) { NSString *episodeId = [NSString stringWithFormat:@"drama_query_ep_%d", i]; [self.storage saveProgressWithEpisodeId:episodeId dramaId:@"drama_query_test" position:arc4random() % 120000 duration:120000 isCompleted:NO synced:arc4random() % 2 == 0 completion:nil]; } [self measureBlock:^{ [self.storage getProgressByDramaId:@"drama_query_test"]; }]; } - (void)testPerformanceUnsyncedProgressQuery { // 准备测试数据(50%未同步) for (int i = 0; i < 1000; i++) { NSString *episodeId = [NSString stringWithFormat:@"unsynced_ep_%d", i]; [self.storage saveProgressWithEpisodeId:episodeId dramaId:@"unsynced_drama" position:arc4random() % 120000 duration:120000 isCompleted:NO synced:i % 2 == 0 // 50%已同步,50%未同步 completion:nil]; } [self measureBlock:^{ [self.storage getUnsyncedProgresses]; }]; } #pragma mark - 格式化工具性能测试 - (void)testPerformanceCountFormatter { NSArray *testNumbers = @[ @0, @999, @1000, @9999, @10000, @99999, @100000, @999999, @1000000, @9999999, @10000000, @99999999, @100000000, @999999999 ]; [self measureBlock:^{ for (NSNumber *number in testNumbers) { [JXCountFormatter formatCount:[number longLongValue]]; } }]; } - (void)testPerformanceCountFormatterSpecificMethods { NSMutableArray *testCounts = [NSMutableArray array]; for (int i = 0; i < 1000; i++) { [testCounts addObject:@(arc4random() % 1000000000)]; } [self measureBlock:^{ for (NSNumber *count in testCounts) { long long countValue = [count longLongValue]; [JXCountFormatter formatLikeCount:countValue]; [JXCountFormatter formatCommentCount:countValue]; [JXCountFormatter formatShareCount:countValue]; [JXCountFormatter formatFavoriteCount:countValue]; [JXCountFormatter formatPlayCount:countValue]; } }]; } #pragma mark - 批量操作性能测试 - (void)testBulkOperationPerformance { NSArray *bulkSizes = @[@10, @50, @100, @500, @1000]; for (NSNumber *sizeNumber in bulkSizes) { NSInteger size = [sizeNumber integerValue]; // 清空数据 [self.storage clearAll]; // 测试批量插入性能 NSDate *insertStart = [NSDate date]; for (NSInteger i = 0; i < size; i++) { NSString *episodeId = [NSString stringWithFormat:@"bulk_ep_%ld", (long)i]; [self.storage saveProgressWithEpisodeId:episodeId dramaId:@"bulk_drama" position:arc4random() % 120000 duration:120000 isCompleted:NO synced:NO completion:nil]; } NSTimeInterval insertTime = [[NSDate date] timeIntervalSinceDate:insertStart]; // 测试批量查询性能 NSDate *queryStart = [NSDate date]; [self.storage getProgressByDramaId:@"bulk_drama"]; NSTimeInterval queryTime = [[NSDate date] timeIntervalSinceDate:queryStart]; // 测试批量删除性能 NSDate *deleteStart = [NSDate date]; [self.storage deleteProgressByDramaId:@"bulk_drama"]; NSTimeInterval deleteTime = [[NSDate date] timeIntervalSinceDate:deleteStart]; NSLog(@"Bulk size: %ld", (long)size); NSLog(@"Insert time: %.3fms", insertTime * 1000); NSLog(@"Query time: %.3fms", queryTime * 1000); NSLog(@"Delete time: %.3fms", deleteTime * 1000); NSLog(@"---"); } } - (void)testConcurrentOperationPerformance { NSInteger concurrentOperations = 50; NSDate *startTime = [NSDate date]; // 模拟并发操作 for (NSInteger i = 0; i < concurrentOperations; i++) { NSString *episodeId = [NSString stringWithFormat:@"concurrent_ep_%ld", (long)i]; NSString *dramaId = [NSString stringWithFormat:@"concurrent_drama_%ld", (long)(i % 10)]; // 10个不同的剧 [self.storage saveProgressWithEpisodeId:episodeId dramaId:dramaId position:arc4random() % 120000 duration:120000 isCompleted:NO synced:NO completion:nil]; // 每隔几次操作就查询一次 if (i % 5 == 0 && i > 0) { NSString *queryEpisodeId = [NSString stringWithFormat:@"concurrent_ep_%ld", (long)(i - 1)]; [self.storage getProgressWithEpisodeId:queryEpisodeId]; } } NSTimeInterval totalTime = [[NSDate date] timeIntervalSinceDate:startTime]; NSLog(@"Concurrent operations (%ld): %.3fms", (long)concurrentOperations, totalTime * 1000); NSLog(@"Average per operation: %.3fms", (totalTime * 1000) / concurrentOperations); } #pragma mark - 内存使用测试 - (void)testMemoryUsagePattern { // 获取初始内存使用情况 struct mach_task_basic_info info; mach_msg_type_number_t size = MACH_TASK_BASIC_INFO_COUNT; kern_return_t kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size); vm_size_t initialMemory = 0; if (kerr == KERN_SUCCESS) { initialMemory = info.resident_size; } NSLog(@"Initial memory usage: %.2fMB", initialMemory / 1024.0 / 1024.0); // 执行大量操作 for (int i = 0; i < 1000; i++) { NSString *episodeId = [NSString stringWithFormat:@"memory_ep_%d", i]; NSString *dramaId = [NSString stringWithFormat:@"memory_drama_%d", i % 20]; [self.storage saveProgressWithEpisodeId:episodeId dramaId:dramaId position:arc4random() % 120000 duration:120000 isCompleted:NO synced:NO completion:nil]; // 每100次操作检查一次内存 if (i % 100 == 0) { kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size); if (kerr == KERN_SUCCESS) { NSLog(@"Memory after %d operations: %.2fMB", i, info.resident_size / 1024.0 / 1024.0); } } } // 执行查询操作 for (int i = 0; i < 100; i++) { NSString *dramaId = [NSString stringWithFormat:@"memory_drama_%d", i % 20]; [self.storage getProgressByDramaId:dramaId]; } // 记录最终内存 kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size); if (kerr == KERN_SUCCESS) { vm_size_t finalMemory = info.resident_size; NSLog(@"Final memory usage: %.2fMB", finalMemory / 1024.0 / 1024.0); NSLog(@"Memory increase: %.2fMB", (finalMemory - initialMemory) / 1024.0 / 1024.0); } } #pragma mark - 数据库增长性能测试 - (void)testDatabaseGrowthPerformance { NSArray *growthSteps = @[@100, @500, @1000, @2000, @5000]; for (NSNumber *totalRecordsNumber in growthSteps) { NSInteger totalRecords = [totalRecordsNumber integerValue]; // 清空并重新填充到指定数量 [self.storage clearAll]; NSDate *populateStart = [NSDate date]; for (NSInteger i = 0; i < totalRecords; i++) { NSString *episodeId = [NSString stringWithFormat:@"growth_ep_%ld", (long)i]; NSString *dramaId = [NSString stringWithFormat:@"growth_drama_%ld", (long)(i % 100)]; [self.storage saveProgressWithEpisodeId:episodeId dramaId:dramaId position:arc4random() % 120000 duration:120000 isCompleted:NO synced:NO completion:nil]; } NSTimeInterval populateTime = [[NSDate date] timeIntervalSinceDate:populateStart]; // 测试在不同数据量下的查询性能 NSDate *queryStart = [NSDate date]; for (int i = 0; i < 50; i++) { NSString *randomEpisodeId = [NSString stringWithFormat:@"growth_ep_%d", arc4random() % (int)totalRecords]; [self.storage getProgressWithEpisodeId:randomEpisodeId]; } NSTimeInterval queryTime = [[NSDate date] timeIntervalSinceDate:queryStart]; NSDate *unsyncedQueryStart = [NSDate date]; [self.storage getUnsyncedProgresses]; NSTimeInterval unsyncedQueryTime = [[NSDate date] timeIntervalSinceDate:unsyncedQueryStart]; NSLog(@"Records: %ld", (long)totalRecords); NSLog(@"Populate time: %.3fms", populateTime * 1000); NSLog(@"Query time (50 queries): %.3fms", queryTime * 1000); NSLog(@"Unsynced query time: %.3fms", unsyncedQueryTime * 1000); NSLog(@"---"); } } #pragma mark - 格式化工具大数据集性能测试 - (void)testFormatterPerformanceWithLargeDataset { NSMutableArray *largeDataset = [NSMutableArray array]; for (int i = 0; i < 10000; i++) { [largeDataset addObject:@(arc4random() % 10000000000LL)]; // 0到100亿 } NSDate *formatStart = [NSDate date]; for (NSNumber *number in largeDataset) { [JXCountFormatter formatCount:[number longLongValue]]; } NSTimeInterval formatTime = [[NSDate date] timeIntervalSinceDate:formatStart]; NSDate *specificFormatStart = [NSDate date]; for (NSNumber *number in largeDataset) { long long numberValue = [number longLongValue]; [JXCountFormatter formatLikeCount:numberValue]; [JXCountFormatter formatPlayCount:numberValue]; } NSTimeInterval specificFormatTime = [[NSDate date] timeIntervalSinceDate:specificFormatStart]; NSLog(@"Format 10k numbers: %.3fms", formatTime * 1000); NSLog(@"Specific format 20k calls: %.3fms", specificFormatTime * 1000); NSLog(@"Average format time: %.6fms per number", (formatTime * 1000) / largeDataset.count); } #pragma mark - 压力测试 - (void)testStressTestContinuousOperations { NSInteger operationCount = 1000; NSDate *startTime = [NSDate date]; for (NSInteger i = 0; i < operationCount; i++) { // 随机操作类型 NSInteger operationType = arc4random() % 4; NSString *episodeId = [NSString stringWithFormat:@"stress_ep_%ld", (long)(arc4random() % 100)]; NSString *dramaId = [NSString stringWithFormat:@"stress_drama_%ld", (long)(arc4random() % 10)]; switch (operationType) { case 0: // 保存进度 [self.storage saveProgressWithEpisodeId:episodeId dramaId:dramaId position:arc4random() % 120000 duration:120000 isCompleted:NO synced:NO completion:nil]; break; case 1: // 查询单个进度 [self.storage getProgressWithEpisodeId:episodeId]; break; case 2: // 查询剧进度 [self.storage getProgressByDramaId:dramaId]; break; case 3: // 查询未同步进度 [self.storage getUnsyncedProgresses]; break; } } NSTimeInterval totalTime = [[NSDate date] timeIntervalSinceDate:startTime]; NSLog(@"Stress test (%ld operations): %.3fms", (long)operationCount, totalTime * 1000); NSLog(@"Average per operation: %.6fms", (totalTime * 1000) / operationCount); } @end