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;
}

  

时间: 2024-10-26 10:16:56

svg动画导致持续占用CPU的相关文章

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

原文出处:http://www.blogjava.net/hankchen 现象: 在tomcat中部署java的web应用程序,过一段时间后出现tomcat的java进程持续占用cpu高达100%,导致web程序访问受阻. 可能原因分析: 可能程序确实在进行数据计算:或程序进入死循环: 解决方法: 1.先用top查看占用cpu的进程id 2.再用ps -ef | grep PID定位具体的进程主体:如是否是tomcat启动的java程序 3.用ps -mp pid -o THREAD,tid,

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

由于使用的华为云的CDN加速,结果发现我的阿里云服务器突然卡顿,网页打开极慢.登陆华为云CDN管理后台发现最高带宽占用30M,流量短时间内达到10GB以上,这么大的流量我的服务器肯定扛不住啊.于是还跟华为云进行了一个撕逼,然后果断弃了华为云. 但是更换了其他CDN或者WAF之后,CPU占用依然居高不下,网上找了很多办法都不管用. 看了下是 PHP CGI 进程占用CPU最多,而且经过检测发现是 浏览器内核检测 网站的 PHP CGI 占用最高,其他的很少.然而看第三方网站统计,并没有很大的访问量

nova-conductor单个进程占用CPU 100%

nova-conductor进程在运行时,其中单个进程会周期性的占用CPU 100%的使用率,周期大约2分钟.经调试和排查,发现原因在于nova-conductor在执行某一数据库操作时,请求数据量巨大, 仅数据库查找耗时10s,返回数据大小在2MB.导致数据在进行序列化和解序列化时耗尽CPU,并持续时间较长.详情如下: 操作请求:object_class_action 请求参数:{u'objver': u'1.6', u'objmethod': u'get_by_filters', u'arg

【转载】解决mysqld-nt.exe大量占用CPU问题

服务器主机(Windows 2003 + IIS + PHP + MYSQL )近来 MySQL 服务进程 (mysqld-nt.exe) CPU 占用率总为 100% 高居不下.此主机有10个左右的 database, 分别给十个网站调用.据朋友测试,导致 mysqld-nt.exe cpu 占用奇高的是网站A,一旦在 IIS 中将此网站停止服务,CPU 占用就降下来了.一启用,则马上上升. MYSQL CPU 占用 100% 的解决过程 今天早上仔细检查了一下.目前此网站的七日平均日 IP

tomcat7+java压测过程中占用CPU过高排查故障和解决办法

环架构境: 前端haproxy做为反向代理,后端N+1台tomcat+java服务 出现问题: 环境是新搭建的,本周在做压测刚开始的时候正常,随着量的上涨,导致CPU一直暴涨. 解决办法和思路: 1.)先通过top命令查看占用cpu高的PID # 根据top命令查看发现PID为2195和975的的进程占用CPU高达%200+,明显出现故障 2.)通过top -H -p pid命令查看,发现2275 3302 3375这几个进程占用CPU时间8分钟 3.)把线程pid转换为16进制,例如:上面的p

SQL Server 占用CPU较高的解决方法

触发原因:月底系统结账的时候对ERP的操作较多,有用户反馈系统之间的数据传输很久没有同步.随即到服务器上查看,没有发现有程序导致的问题,看了一下CPU的使用率,发现SQL Server占用率在百分之九十以上. 解决过程:首先Baidu了一下,看了一下可能的原因应该是索引问题.之前有仔细看过SQL Server索引相关的书籍和查找优化索引的方法.所以立即使用SQL Server Profiler开始检测对CPU使用率高的SQL statement. 经过检测发现更新数据传输的语句占用CPU很高(u

Win10 WMI Provider Host进程占用CPU过高的解决方法

在使用系统过程中,偶尔会出现由于某些进程而导致CPU等硬件资源占用过多,进而出现系统卡顿的情况.一个Win10用户发现“WMI Provider Host“占用了过多CPU资源导致系统卡顿,该如何解决这个问题呢? 解决方法: 可以尝试关闭Windows防火墙服务来解决这个问题. 1.按住win+R,输入services.msc,回车. 2.在服务里面找到Windows Firewall,双击,在启动类型中选择“禁止”. 3.重启Win10系统,然后测试问题是否得到解决. 有的用户不知道是哪个进程

php-cgi进程占用cpu资源过大原因分析及解决

一,开启日志记录,为以后排查做准备 1.1 开启php-fpm.conf的错误日志和慢执行日志和常规日志, 采样一个小时,就可以根据这些日志的内容进行分析问题error_log = /tmp/error.log //错误日志access.log = /tmp/access.$pool.log //常规日志,记录每次访问时间,记录不同参数,以防止恶意攻击,后面会详细解析access.format = "%R – %u %t \"%m %r%Q%q\" %s %f %{mili}

记一次java程序占用cpu超高排查

1.首先通过top命令查看占用cpu过高的pid #top top - 18:07:25 up 48 days,  1:07,  3 users,  load average: 11.94, 11.90, 9.46Tasks: 271 total,   1 running, 270 sleeping,   0 stopped,   0 zombie%Cpu(s): 74.2 us,  0.8 sy,  0.0 ni, 24.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.