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的更多相关文章

  1. shopex-百度爬虫抓取过于频繁导致php-cgi占用CPU过高的解决办法

    步骤 1.开启slowlog:php-fpm里修改配置 观察slowlog里的超时文件,然后修改相应超时文件 2.1修改完后,仍然无效,查看access.log,发现大量如下的请求 220.181.1 ...

  2. JAVA进程占用CPU分析

    在一次生产环境中,服务器负载报警,SSH登录上看到CPU占用很高. 1.执行top命令,看到进程号为9737的进程持续占用CPU 2.怀疑是否是进程配置的内存不够了,引发了fullGC导致CPU占用高 ...

  3. tomcat+java的web程序持续占cpu问题调试

    原文出处:http://www.blogjava.net/hankchen 现象: 在tomcat中部署java的web应用程序,过一段时间后出现tomcat的java进程持续占用cpu高达100%, ...

  4. tomcat+java的web程序持续占cpu高问题调试【转】

    转自 tomcat+java的web程序持续占cpu问题调试 - 像风一样的自由 - CSDN博客http://blog.csdn.net/five3/article/details/28416771 ...

  5. PHP CGI 进程占用CPU过高导致CPU使用达到100%的另类原因

    由于使用的华为云的CDN加速,结果发现我的阿里云服务器突然卡顿,网页打开极慢.登陆华为云CDN管理后台发现最高带宽占用30M,流量短时间内达到10GB以上,这么大的流量我的服务器肯定扛不住啊.于是还跟 ...

  6. 记一次JAVA进程导致Kubernetes节点CPU飙高的排查与解决

    一.发现问题 在一次系统上线后,我们发现某几个节点在长时间运行后会出现CPU持续飙升的问题,导致的结果就是Kubernetes集群的这个节点会把所在的Pod进行驱逐(调度):如果调度到同样问题的节点上 ...

  7. 服务器CPU又爆了?Linux快速排查Java程序占用CPU很高的方法

    这个问题可以说是 Java 面试的高频面试题了,有很多面试官都喜欢问这个问题,问题可能是下面这样的. 线上一台服务器 CPU 使用率100% 了,如果你碰到这样的情况,如何排查并找到问题原因? 1.场 ...

  8. memcache占用CPU过高的解决办法

    Simon最近为公司服务器操碎了心 , 先是mysqld进程占用CPU过高 , 导致服务器性能变低 ,网站打开太慢.通过增加max_connections及table_cache解决了问题 ,随后发现 ...

  9. 关于linux系统CPU篇--->不容易发现的占用CPU较高进程

    1.系统的CPU使用率,不仅包括进程用户态和内核态的运行,还包括中断处理,等待IO以及内核线程等等.所以,当你发现系统的CPU使用率很高的时候,不一定能找到相对应的高CPU使用率的进程 2.案例分析, ...

  10. 转 JVM找出占用CPU最高的线程

    这两天客户这边有一台服务器一到下午3点左右就开始卡住,页面无法访问,服务器CPU占用达到300%多开始以为只是可能只是意外事件,重启一下就好,但是发现重启之后没几分钟服务器马上又反应无法访问,我就开始 ...

随机推荐

  1. oracle 数据库连接

    前言 关于oracle 数据库如何连接,我一开始以为和mysql 和 sql server一样,写好连接语句然后调用相应的dll. 知道我遇到了两个错误: 1.64位程序不能去驱动32位客户端 2.O ...

  2. 错误 内存溢出 vendor/composer/autoload_real.php on line 66

    前言 首先声明我没怎么写过php,只是当时室友做php的时候跟他一起学了几分钟. 有时候部署一些php项目的时候,发生一些错误,但是百度一下五花八门的. 这个错误的完整版是: Fatal error: ...

  3. 重新整理asp.net core 实操篇——简介

    前言 实操篇和底层刨析分开的,<重新整理.net core 计1400篇>是探索底层概念. 介绍asp.net core之前先介绍.net core. .NET Core 是一个通用的开放 ...

  4. Django框架——csrf跨站请求伪造、csrf校验、csrf相关装饰器、auth认证、auth认证相关模块及操作

    csrf跨站请求伪造 钓鱼网站:模仿一个正规的网站 让用户在该网站上做操作 但操作的结果会影响到用户正常的网站账户 但是其中有一些猫腻 eg:英语四六级考试需要网上先缴费 但是你会发现卡里的钱扣了但是 ...

  5. 力扣176(MySQL)-第二高的薪水(中等)

    题目: id 是这个表的主键.表的每一行包含员工的工资信息. 编写一个 SQL 查询,获取并返回 Employee 表中第二高的薪水 .如果不存在第二高的薪水,查询应该返回 null . 查询结果如下 ...

  6. 力扣68(java)-文本左右对齐(困难)

    题目: 给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本. 你应该使用 "贪心算法" ...

  7. 暑期集训 Day11 —— 模拟赛复盘

    ${\color{Green} \mathrm{Problem\ 1 :Subarray }} $ 签到失败... 直接二进制分组,找出所有二进制位=0 的方法. 死因: 二进制分组没想出来... $ ...

  8. dotnet C# 多次对一个对象调用构造函数会发生什么

    今天来玩一点变态的,使用反射获取到某个类型的构造函数,接着多次对此类型的某个对象调用构造函数方法.请问此时会发生什么 假定有一个类型 Foo 的定义如下 class Foo : IDisposable ...

  9. 259k+ Star!这是我见过最全的开发者技术学习路线!

    大家好,我是 Java陈序员. 自从上班后,身体是一天不如一天了,也很少有时间可以去学习新技术了.程序员如果技术跟不上,很容易就被淘汰. 而碎片化的学习效率又不高,往往今天学了,明天就忘了.有时候更是 ...

  10. VSCode+VUE+ESLint以达到保存自动格式化

    首先打开VSCode在.eslintrc.js中加入以下代码(不知道怎么找可以ctrl+shift+p进行搜索),添加 vscode 终端启动服务 // 添加⾃定义规则 'prettier/prett ...