svg动画导致持续占用CPU
1、在一次性能优化中突然发现一个svg矢量图动画导致CPU持续占用的问题,该svg在web中使用,
即使webview释放之后,CPU依然占用达到10%,6s+上测试结果
svg如下所示:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="none" x="0px" y="0px" width="25px" height="25px" viewBox="0 0 25 25"> <path stroke="#777777" stroke-width="1" stroke-linejoin="round" stroke-linecap="round" fill="none" stroke-dasharray="64,6" stroke-dashoffset="0" d="
M 3.4 5.65
Q 9.5 2.2 11.2 1.15 12.6 0.4 14 1.3
L 21.65 5.75
Q 22.9 6.65 22.85 8.2
L 22.85 17.4
Q 22.8 18.6 21.5 19.25 14.85 23.25 13.6 23.9 12.3 24.55 10.8 23.7 4.3 19.9 3.1 19.1 2.35 18.6 2.15 17.75
L 2.1 7.95
Q 2.1 7.25 2.75 6.35
L 3.4 5.65 Z">
<animate attributeName="stroke-dashoffset" begin="0s" dur="1.5s" from="0" to="70" repeatCount="indefinite"/>
</path> <path stroke="#777777" stroke-width="1" stroke-linejoin="round" stroke-linecap="round" fill="none" stroke-dasharray="37,4" stroke-dashoffset="41" d="
M 7.15 8.35
L 11.7 5.7
Q 12.55 5.25 13.35 5.8
L 17.85 8.4
Q 18.6 8.95 18.55 9.85
L 18.55 15.25
Q 18.5 15.95 17.75 16.35 13.85 18.7 13.1 19.05 12.35 19.45 11.45 18.95
L 6.95 16.25
Q 6.55 16 6.4 15.45
L 6.35 9.7
Q 6.35 9.25 6.75 8.75
L 7.15 8.35 Z">
<animate attributeName="stroke-dashoffset" begin="0s" dur="1.5s" from="41" to="0" repeatCount="indefinite"/>
</path> </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<NSURLProtocolClient> 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;
}
svg动画导致持续占用CPU的更多相关文章
- shopex-百度爬虫抓取过于频繁导致php-cgi占用CPU过高的解决办法
步骤 1.开启slowlog:php-fpm里修改配置 观察slowlog里的超时文件,然后修改相应超时文件 2.1修改完后,仍然无效,查看access.log,发现大量如下的请求 220.181.1 ...
- JAVA进程占用CPU分析
在一次生产环境中,服务器负载报警,SSH登录上看到CPU占用很高. 1.执行top命令,看到进程号为9737的进程持续占用CPU 2.怀疑是否是进程配置的内存不够了,引发了fullGC导致CPU占用高 ...
- tomcat+java的web程序持续占cpu问题调试
原文出处:http://www.blogjava.net/hankchen 现象: 在tomcat中部署java的web应用程序,过一段时间后出现tomcat的java进程持续占用cpu高达100%, ...
- tomcat+java的web程序持续占cpu高问题调试【转】
转自 tomcat+java的web程序持续占cpu问题调试 - 像风一样的自由 - CSDN博客http://blog.csdn.net/five3/article/details/28416771 ...
- PHP CGI 进程占用CPU过高导致CPU使用达到100%的另类原因
由于使用的华为云的CDN加速,结果发现我的阿里云服务器突然卡顿,网页打开极慢.登陆华为云CDN管理后台发现最高带宽占用30M,流量短时间内达到10GB以上,这么大的流量我的服务器肯定扛不住啊.于是还跟 ...
- 记一次JAVA进程导致Kubernetes节点CPU飙高的排查与解决
一.发现问题 在一次系统上线后,我们发现某几个节点在长时间运行后会出现CPU持续飙升的问题,导致的结果就是Kubernetes集群的这个节点会把所在的Pod进行驱逐(调度):如果调度到同样问题的节点上 ...
- 服务器CPU又爆了?Linux快速排查Java程序占用CPU很高的方法
这个问题可以说是 Java 面试的高频面试题了,有很多面试官都喜欢问这个问题,问题可能是下面这样的. 线上一台服务器 CPU 使用率100% 了,如果你碰到这样的情况,如何排查并找到问题原因? 1.场 ...
- memcache占用CPU过高的解决办法
Simon最近为公司服务器操碎了心 , 先是mysqld进程占用CPU过高 , 导致服务器性能变低 ,网站打开太慢.通过增加max_connections及table_cache解决了问题 ,随后发现 ...
- 关于linux系统CPU篇--->不容易发现的占用CPU较高进程
1.系统的CPU使用率,不仅包括进程用户态和内核态的运行,还包括中断处理,等待IO以及内核线程等等.所以,当你发现系统的CPU使用率很高的时候,不一定能找到相对应的高CPU使用率的进程 2.案例分析, ...
- 转 JVM找出占用CPU最高的线程
这两天客户这边有一台服务器一到下午3点左右就开始卡住,页面无法访问,服务器CPU占用达到300%多开始以为只是可能只是意外事件,重启一下就好,但是发现重启之后没几分钟服务器马上又反应无法访问,我就开始 ...
随机推荐
- mysql 必知必会整理—子查询与连接表[八]
前言 简单介绍一下子查询与连接表. 正文 什么是子查询呢? 列出订购物品TNT2的所有客户. select cust_id from orders where order_num IN (SELECT ...
- mysql 必知必会整理—数据汇总与分组[七]
前言 简单整理一下数据汇总与分组 正文 我们经常需要汇总数据而不用把它们实际检索出来,为此MySQL提供了专门的函数.使用这些函数,MySQL查询可用于检索数据,以便分析和报表生成. 这种类型的检索例 ...
- docker 应用篇————nginx 例子[六]
前言 简单整理一下nginx 例子. 正文 拉取nginx 镜像. docker pull nginx 那么会拉取nginx:latest 这个. 如果需要其他的,可以去官网查询一下. 2.docke ...
- leetcode每日一题:409. 最长回文串
409. 最长回文串 给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串. 在构造过程中,请注意区分大小写.比如 "Aa" 不能当做一个回文字符串. 注意 ...
- Filebeat 日志采集工具安装
Filebeat 是比较轻量的日志采集工具,对于一些简单的采集任务可以直接使用 Filebeat 采集,同时也支持很多的方式输出,可以输出至 Kafka.Elasticsearch.Redis 等,下 ...
- 浏览器端实现类似input限制输入两位小数,输入时光标从输入位置移动到最后
1.问题描述展示 示例代码所做限制为不允许输入字母d,其他限制规则可以根据需求自己调整,使用React编写,其他框架或原生均可根据该代码理解原理进行转变,特意使用了中文键盘可以看到输入框下面白色框闪出 ...
- 力扣202(java&python)-快乐数(简单)
题目: 编写一个算法来判断一个数 n 是不是快乐数. 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和.然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终 ...
- 力扣686(java)-重复叠加字符串匹配(中等)
题目: 给定两个字符串 a 和 b,寻找重复叠加字符串 a 的最小次数,使得字符串 b 成为叠加后的字符串 a 的子串,如果不存在则返回 -1. 注意:字符串 "abc" 重复叠加 ...
- HarmonyOS NEXT应用开发案例——阻塞事件冒泡
介绍 本示例主要介绍在点击事件中,子组件enabled属性设置为false的时候,如何解决点击子组件模块区域会触发父组件的点击事件问题:以及触摸事件中当子组件触发触摸事件的时候,父组件如果设置触摸事件 ...
- OSCAR 2022 开源产业大会PolarDB-X、 PolarDB-PG获奖揭晓
简介: 作为全球数据库领导者,阿里云数据库坚定拥抱开源.此次亮相大会,旗下核心开源项目云原生分布式数据库PolarDB-X通过了信通院的 "可信开源项目评估,并以正式成员身份,加入中国信通院 ...