Six, electricity consumption

Power on mobile devices has always been a sensitive issue. If users find serious power consumption and heat of mobile phones when using an App, they are likely to uninstall the App immediately. So you need to be concerned about power consumption during the development phase.

When it comes to high power consumption, we immediately think, are we using location, are we using frequent network requests, are we doing something over and over again?

There are basically no problems during development, so you can use Instrucments’ Energy Log tool to locate problems. But online problems require code to monitor power consumption as part of APM’s capabilities.

1. How to get power

In iOS, IOKit is a proprietary framework for obtaining hardware and device details, as well as the underlying framework for communication between hardware and kernel services. So we can obtain hardware information through IOKit, and thus obtain electricity information. The steps are as follows:

  • First found in apple’s opensource opensourceIOPowerSources.h,IOPSKeys.h. In XcodePackage ContentsfindIOKit.framework. Path for/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Framew orks/IOKit.framework
  • Then import iopowerSources. h, iopskeys. h, IOKit. Framework into the project
  • Set batteryMonitoringEnabled of UIDevice to true
  • The obtained power consumption is accurate to 1%

2. Locate the fault

Normally, after we have solved many problems through the Energy Log in Instrucments, the App will go live and the online power consumption will need to be resolved using APM. It could be a two-party library, a three-party library, or a colleague’s code.

After detecting power consumption, find the thread with the problem first, and then stack dump, restore the crime scene.

In the previous section we saw the structure of thread information, thread_basic_info has a field that records the percentage of CPU usage, CPU_usage. So we can find the problem thread by iterating through the current thread to determine which thread has the highest CPU usage. The stack is then dumped to locate the code where the power consumption occurred. See Section 3.2 for details.

- (double)fetchBatteryCostUsage { // returns a blob of power source information in an opaque CFTypeRef CFTypeRef blob = IOPSCopyPowerSourcesInfo(); // returns a CFArray of power source handles, each of type CFTypeRef CFArrayRef sources = IOPSCopyPowerSourcesList(blob); CFDictionaryRef pSource = NULL; const void *psValue; // returns the number of values currently in an array int numOfSources = CFArrayGetCount(sources); // error in CFArrayGetCount if (numOfSources == 0) { NSLog(@"Error in CFArrayGetCount"); The return - 1.0 f; } // calculating the remaining energy for (int i=0; i<numOfSources; i++) { // returns a CFDictionary with readable information about the specific power source pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i)); if (! pSource) { NSLog(@"Error in IOPSGetPowerSourceDescription"); The return - 1.0 f; } psValue = (CFStringRef) CFDictionaryGetValue(pSource, CFSTR(kIOPSNameKey)); int curCapacity = 0; int maxCapacity = 0; double percentage; psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSCurrentCapacityKey)); CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity); psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSMaxCapacityKey)); CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity); Percentage = ((double) curCapacity/(double) maxCapacity * 100.0F); NSLog(@"curCapacity : %d / maxCapacity: %d , percentage: %.1f ", curCapacity, maxCapacity, percentage); return percentage; } the return - 1.0 f; }Copy the code

3. What can we do about power consumption in the development stage

CPU intensive computing is the main cause of power consumption. So we need to be careful about how we use the CPU. Try to avoid making the CPU useless. For complex operations with large amounts of data, you can make use of the capabilities of the server and GPU. If the design must be done on the CPU, then GCD technology can be used. Dispatch_block_create_with_qos_class (<#dispatch_block_flags #>, dispatch_qOS_class_t qOS_class, <#int relative_priority#>, <#^(void)block#>)() and specify the queue’s qos as QOS_CLASS_UTILITY. The task is submitted to a block in the queue. In QOS_CLASS_UTILITY mode, the system optimizes power for large data calculations

In addition to heavy CPU processing, I/O operations are also the main cause of power consumption. A common solution in the industry is to defer the operation of “writing fragmented data to disk storage”, aggregating it in memory first, and then storing it on disk. Fragmentation data is aggregated and stored in memory. IOS provides NSCache.

– (**void**)cache:(NSCache *)cache willEvictObject:(**id**)obj; – (**void**)cache:(**id**)obj; Method to perform I/O operations on the data inside the method to delay the aggregated data I/O. Fewer I/ OS mean less power consumption.

To use NSCache, see SDWebImage, an image loading framework. In the image read cache processing, do not directly read the disk file (I/O), but use the system NSCache.

- (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key {
    return [self.memoryCache objectForKey:key];
}

- (nullable UIImage *)imageFromDiskCacheForKey:(nullable NSString *)key {
    UIImage *diskImage = [self diskImageForKey:key];
    if (diskImage && self.config.shouldCacheImagesInMemory) {
        NSUInteger cost = diskImage.sd_memoryCost;
        [self.memoryCache setObject:diskImage forKey:key cost:cost];
    }

    return diskImage;
}
Copy the code

As you can see, the main logic is to read the image from disk first. If memory caching is enabled, the image is saved to NSCache and the image is read from NSCache. NSCache’s totalCostLimit and countLimit properties,

– (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g; The cache condition () method is used to set the cache condition. Therefore, we can use this strategy for reference when we write disk and memory files to optimize power consumption.

The content of the article is too long, divided into several chapters, please click to view, if you want to view the whole coherent, please visit here