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. MMDeploy部署实战系列【第三章】:MMdeploy pytorch模型转换onnx,tensorrt

    MMDeploy部署实战系列[第三章]:MMdeploy pytorch模型转换onnx,tensorrt 这个系列是一个随笔,是我走过的一些路,有些地方可能不太完善.如果有那个地方没看懂,评论区问就 ...

  2. 笔记本电脑上的聊天机器人: 在英特尔 Meteor Lake 上运行 Phi-2

    对应于其强大的能力,大语言模型 (LLM) 需要强大的算力支撑,而个人计算机上很难满足这一需求.因此,我们别无选择,只能将它们部署至由本地或云端托管的性能强大的定制 AI 服务器上. 为何需要将 LL ...

  3. Web前端 -- NPM包管理器

    初始化: #建立一个空文件夹,在命令提示符进入该文件夹 执行命令初始化 npm init #按照提示输入相关信息,如果是用默认值则直接回车即可. #name: 项目名称 #version: 项目版本号 ...

  4. Java使用ganymed工具包执行LINUX命令教程

    了解更多开发技巧,请访问,架构师小跟班官网:https://www.jiagou1216.compackage com.jiagou;import ch.ethz.ssh2.Connection;im ...

  5. javascript现代编程之四——数值的进制和表示方法

    在JavaScript中,数值可以以不同的进制表示: 十进制:这是我们最常用的进制系统.例如:let decimal = 123; 二进制:数值前面加上 0b 或者 0B.例如:let binary ...

  6. 【c++】类valarray介绍

    valarray类用于处理数组中的数值,如将所有元素相加,找出最大.最小值,数组长度. 如何使用valarray类: 1.首先需要声明头文件        #include<valarray&g ...

  7. Ubuntu22.04版本安装对应版本ROS教程 (小白2024年)

    参考资料:(我是开了加速器,毕竟中间使用了github访问网址,国内免费加速器Steam++,开个github网站加速即可,不开我不知道行不行可以自己一试) ubuntu22.04安装ROS2 详细教 ...

  8. 剑指offer05(Java)-替换空格(简单)

    题目: 请实现一个函数,把字符串 s 中的每个空格替换成"%20". 示例 1: 输入:s = "We are happy."输出:"We%20are ...

  9. PolarDB开源未来将有哪些新动向?阿里云数据库开源负责人来解答

    简介: 在10月25日由阿里云开发者社区.PolarDB开源社区.infoQ联合举办的「开源人说」第三期--<数据库PolarDB专场>沙龙上,阿里云数据库开源负责人.数据库资深技术专家王 ...

  10. 延迟绑定与retdlresolve

    延迟绑定与retdlresolve 我们以前在ret2libc的时候,我们泄露的libc地址是通过延迟绑定实现的,我们知道,在调用libc里面的函数时候,它会先通过plt表和gor表绑定到,函数真实地 ...