博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
svg动画导致持续占用CPU
阅读量:5331 次
发布时间:2019-06-14

本文共 6588 字,大约阅读时间需要 21 分钟。

1、在一次性能优化中突然发现一个svg矢量图动画导致CPU持续占用的问题,该svg在web中使用,

  即使webview释放之后,CPU依然占用达到10%,6s+上测试结果

  svg如下所示:

  

  注意该动画的时间是无限长,指定时间结束之后,CPU将不再占用,因此这可能是webkit中的bug。

  svg是HTML5中的标准,每个webview都应该支持。未测试WKWebView兼容情况

2、问题解决  

  可以看到该svg是由web中的css文件引用,真正的请求是:https://egame.gtimg.cn/club/pgg/v2.5/v2/img/global/loading-fecf2b8eea.svg

  为了可以将这个问题解决掉,在前端暂无法修复的情况下,我选择使用NSURLProtocol中的方法,hook该请求,并返回404

  具体操作使用了一个OHHTTPStubs的框架,代码如下:

  

+ (void)addLoadingSVG_Patch{    [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {                NSString *url = [request.URL description];        if([url hasSuffix:@"svg"] && [[url lastPathComponent] hasPrefix:@"loading"])        {            QG_Event(MODULE_LIVE_ASS, @"patch fuck loading animated svg request!!! = %@", request);            return YES;        }        return NO;    } withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) {                return [OHHTTPStubsResponse responseWithFileAtPath:@""                                                statusCode:404 headers:@{@"Content-Type":@"image/jpeg"}];    }];}

  问题解决

3、NSURLProtocol是苹果的一个协议,其中通过 + (BOOL)canInitWithRequest:(NSURLRequest *)request; 这个方法返回是否要手动接管这个请求

  通常web的离线缓存基于此实现,接管请求之后,需要自己实现请求的代码,并将返回结果通过NSURLProtocol的client对象回调给上层,例如:

  在startLoading方法中,实现请求,并返回结果。

- (void)startLoading{    self.clientRunLoop = CFRunLoopGetCurrent();    NSURLRequest* request = self.request;    id
client = self.client; if (!self.stub) { NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys: @"It seems like the stub has been removed BEFORE the response had time to be sent.", NSLocalizedFailureReasonErrorKey, @"For more info, see https://github.com/AliSoftware/OHHTTPStubs/wiki/OHHTTPStubs-and-asynchronous-tests", NSLocalizedRecoverySuggestionErrorKey, request.URL, // Stop right here if request.URL is nil NSURLErrorFailingURLErrorKey, nil]; NSError* error = [NSError errorWithDomain:@"OHHTTPStubs" code:500 userInfo:userInfo]; [client URLProtocol:self didFailWithError:error]; if (OHHTTPStubs.sharedInstance.afterStubFinishBlock) { OHHTTPStubs.sharedInstance.afterStubFinishBlock(request, self.stub, nil, error); } return; } OHHTTPStubsResponse* responseStub = self.stub.responseBlock(request); if (OHHTTPStubs.sharedInstance.onStubActivationBlock) { OHHTTPStubs.sharedInstance.onStubActivationBlock(request, self.stub, responseStub); } if (responseStub.error == nil) { NSHTTPURLResponse* urlResponse = [[NSHTTPURLResponse alloc] initWithURL:request.URL statusCode:responseStub.statusCode HTTPVersion:@"HTTP/1.1" headerFields:responseStub.httpHeaders]; // Cookies handling if (request.HTTPShouldHandleCookies && request.URL) { NSArray* cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:responseStub.httpHeaders forURL:request.URL]; if (cookies) { [NSHTTPCookieStorage.sharedHTTPCookieStorage setCookies:cookies forURL:request.URL mainDocumentURL:request.mainDocumentURL]; } } NSString* redirectLocation = (responseStub.httpHeaders)[@"Location"]; NSURL* redirectLocationURL; if (redirectLocation) { redirectLocationURL = [NSURL URLWithString:redirectLocation]; } else { redirectLocationURL = nil; } [self executeOnClientRunLoopAfterDelay:responseStub.requestTime block:^{ if (!self.stopped) { // Notify if a redirection occurred if (((responseStub.statusCode > 300) && (responseStub.statusCode < 400)) && redirectLocationURL) { NSURLRequest* redirectRequest = [NSURLRequest requestWithURL:redirectLocationURL]; [client URLProtocol:self wasRedirectedToRequest:redirectRequest redirectResponse:urlResponse]; if (OHHTTPStubs.sharedInstance.onStubRedirectBlock) { OHHTTPStubs.sharedInstance.onStubRedirectBlock(request, redirectRequest, self.stub, responseStub); } } // Send the response (even for redirections) [client URLProtocol:self didReceiveResponse:urlResponse cacheStoragePolicy:NSURLCacheStorageNotAllowed]; if(responseStub.inputStream.streamStatus == NSStreamStatusNotOpen) { [responseStub.inputStream open]; } [self streamDataForClient:client withStubResponse:responseStub completion:^(NSError * error) { [responseStub.inputStream close]; NSError *blockError = nil; if (error==nil) { [client URLProtocolDidFinishLoading:self]; } else { [client URLProtocol:self didFailWithError:responseStub.error]; blockError = responseStub.error; } if (OHHTTPStubs.sharedInstance.afterStubFinishBlock) { OHHTTPStubs.sharedInstance.afterStubFinishBlock(request, self.stub, responseStub, blockError); } }]; } }]; } else { // Send the canned error [self executeOnClientRunLoopAfterDelay:responseStub.responseTime block:^{ if (!self.stopped) { [client URLProtocol:self didFailWithError:responseStub.error]; if (OHHTTPStubs.sharedInstance.afterStubFinishBlock) { OHHTTPStubs.sharedInstance.afterStubFinishBlock(request, self.stub, responseStub, responseStub.error); } } }]; }}- (void)stopLoading{ self.stopped = YES;}

  

转载于:https://www.cnblogs.com/doudouyoutang/p/6679953.html

你可能感兴趣的文章
新式类多继承的查找顺序
查看>>
Shell编程
查看>>
gulp入门
查看>>
结构(值类型)的构造器
查看>>
DFMEA
查看>>
mycat详细
查看>>
KEGG数据库的使用方法与介绍
查看>>
django处理静态文件
查看>>
云游戏流媒体整体架构设计(云游戏流媒体技术前瞻,最近云游戏概念很火,加之对流媒体技术略有研究,简单写一些)...
查看>>
JQuery里面的下啦菜单
查看>>
图像处理基础(4):高斯滤波器详解
查看>>
Palindromes&nbsp;_easy&nbsp;version
查看>>
Mac上使用brew安装nvm来支持多版本的Nodejs
查看>>
vuejs数据双向绑定原理(get & set)
查看>>
LAMP、LNMP实战之四搭建mysql(持续更新)
查看>>
iOS 开发者必知的 75 个工具(译文)
查看>>
rabbitmq
查看>>
原型学习
查看>>
编程数学-中括号
查看>>
缓存-System.Web.Caching.Cache
查看>>