[Technical dry goods] How to design and develop low power consumption

Nowadays, various large-scale mobile games emerge in an endless stream, which puts forward higher requirements on the battery life and power consumption of mobile phones. Many popular mobile games on the market have perfectly balanced user experience and mobile phone power consumption since the beginning of design and development.

So, what high power consumption scenarios did these popular mobile games solve during the design and development process?

1. Examples of high power consumption scenarios

1、Push

Push, an interaction of notification messages, is a message push mechanism. There are multiple Push channels in the Android system, which leads to frequent wake-up of applications.

The Android system push mechanism includes GCM (Google Cloud Messaging), which is mainly used for message push. Even if the application is not activated, the client can receive messages from the server through GCM. This function is a native function of the Android system, because the server is synchronized. The problem is that the domestic Android version has not been widely promoted and applied; domestic mobile phone manufacturers led by Huawei have launched their own customized Push channels according to their respective system versions; in addition, applications such as WeChat will also have independent Push channels. Through this channel, the server can be connected to the client on the mobile phone for data connection;

On the Android system, because the application has an independent Push channel, multiple application clients and the server keep interacting with each other, and the system can never sleep, resulting in faster system power consumption; this is the current Android system's relatively power-hungry scenario.

2. Wakelock holds the lock for a long time

From the above figure, you can understand the sleep mechanism of the Android system. At the beginning, the system is regular and the lines are red, which means that the system is frequently awakened. If the screen is still after the screen is turned off, the system will enter a light sleep after the phone is placed on the table for a period of time, which is the first Doze state in the above picture. At this time, there is no network access, Syncs and Jobs Deferred are not recommended. , there will be a maintenance window periodically, at which time the application can be woken up; after a while, the system will enter a deep sleep state, at this time there are more restrictions, No wakelocks, No network access, Alarms/Syncs/Jobs Deferred Recommended use, No GPS/Wi-Fi Scans, this is just an ideal sleep state, it is difficult to enter such a state in practice;

When the application sets Wakelock, it can avoid the application process ending due to system hibernation. Wakelock can be used in two ways. The first is that the upper layer of the system applies for Wakelock by using PowerManagerService. During this period, the system will not enter the sleep state, and the application can continue to run. The other way is to use the underlying wake_lock/wake_unlock interface to prevent the system from entering sleep Status, such as some native interfaces or some underlying Wifi and GPS drivers.

Once the lock is opened and then forgotten to be closed, the system will remain in this state and the system will be in an abnormal state of power consumption.

In the process of programming, the program exits abnormally for some reason after acquiring the lock. As a result, Wakelock is always open. At this time, the power consumption of the system is also abnormal. Therefore, special attention should be paid to the use of Wakelock.

Second, the application of compilation technology in low-power development

In theory, all the conversion of one programming language into another language or format is called compilation.

Three common compilation techniques

1. Compile the programming language directly into machine code, typically a compiler such as C/C++

2. Compile the programming language into bytecode, which is executed by the virtual machine

3. Compilers for Domain-Specific Languages ​​(DSLs)

Several feasible aspects of applying compilation technology in production

1. Study the compiler options, or get the best option through iterative compilation, so as to get a performance boost in the product;

2. Add compiler extensions (pragma, _ attribute _) to perform additional compilation checks and auxiliary code generation;

3. Perform static code analysis based on the Abstract Syntax Tree (AST) generated by the compiler front-end, and perform automated code refactoring based on AST rewriting;

4. Cross-function/cross-TU analysis based on the intermediate expression (IR) input by the backend of the compiler;

5. Run-time error discovery based on modification of compilation instructions;

CLANG&LLVM

After the Wakelock is locked, the system is not released in time. During the static detection of the front-end code, CLANG&LLVM compilation can be used for timely detection. CLANG&LLVM is a compiler similar to GCC, but compared with GCC, it has the advantages of more openness, better modularity, and stronger scalability. It has functions such as abstract syntax tree, syntax analysis, and syntax number.

Clang's module architecture

The main modules and functions of Clang

Clang&LLVM advantages:

1. The learning curve is flatter than GCC;

2. Clang & LLVM use BSD License, which is more friendly than GPL;

3. Highly modular, easier to expand and secondary development than GCC;

4. There are well-designed interfaces and modes to facilitate access to internal data, such as: accessing abstract syntax tree (AST) nodes, obtaining control flow graph nodes (CFG Node), obtaining context symbols, etc.;

5. Clang's support for the C++ standard is more complete and faster;

6. Good GCC compatibility, including: GCC built-in extension syntax, built-in keyword support;

7. Higher efficiency (compilation speed, memory overhead, code execution efficiency on some platforms exceeds GCC);

code static analysis

In the coding process, how to identify coding errors through static analysis of the code? What is code static analysis?

Code static analysis, the analyzed program does not need to run, does not depend on the execution environment, and finds defects in the code by analyzing the source code of the program or some form of intermediate code, which is very valuable in large-scale software analysis.

Three different levels of code analysis based on Clang

1. Preprocessor Matcher (Clang PPCallback) preprocessing

By registering callbacks with Clang's Preprocess module, the processing of each Token can be obtained;

The obtained Token is used for text matching, not Path-Sensitive, not Context-Sensitive ;

2. AST Matcher (Clang Tidy) abstract syntax tree analysis

Use RecursiveASTVisitor to traverse the Abstract Syntax Tree (AST) and analyze each Stmt or Decl;

It is suitable for checking some coding standard classes, such as: importing the global namespace in the header file, etc., not Path-Sensitive, not Context-Sensitive ;

3. Symbolic Execution

Perform virtual symbolic execution along each edge (path) of the control flow graph (CFG), save the value and context of the symbol, and record the conditions of the path jump;

It is suitable for checking the functions in the TU for resource leakage, repeated release, etc. It is Path/Context-Sensitive ;

Symbolic execution flow example

Construct a control flow graph CFG according to AST, start from the root node of CFG, and perform virtual execution of statements along each edge of the graph

All possible paths need to be traversed, using symbols to represent the results, rather than logging the actual value at runtime.

When traversing each path, collect all the variable symbolic values ​​(Symbolic Value) visible at this point at each point (Program State), and transform the problem of "resource leakage" into the problem of judging the reachability of the graph.

Symbolic execution flow

Use the Symbolic Value of the record variable in the traversal analysis of the path

FILE* f is visible in all paths, and the Symbolic Value of f is recorded on all nodes (statements) of the path. When the Sink node is reached, it is judged whether the residual handle is not closed according to the Symbolic Value of f.

The graph generated by the nodes in the analysis process is called "ExplodedGraph", and the problem in this example is transformed into a graph reachability problem.

Core Concepts in Exploded Node

There are many nodes in BasicBlock, and each node can have two states. One state is Program Point, that is, the location information of the program, that is, the location analysis of the current instruction. Another state is Program State, which is used to record information such as the current environment, constraints, variable ranges, and user-defined ranges.

Analysis Checker

During the use of the Clang mechanism, the Clang framework provides many hook methods. During the traversal of the control flow graph, each statement is triggered when it is accessed. It is a typical Inversion of Control (IoC) mode. Register your own check on the point, and Checker will participate in and affect the creation of Exploded Graph. In order to reduce path explosion, Checker can create Sink Node to do path support and cut.

In the above figure, according to the Clang framework, during the Wakelock check process, developers can register Check1 and Check2 according to different conditions. Checker can create a Sink Node to support and cut the path of the registered Check.

Checker Point

checkPreStmt (const ReturnStmt *S, CheckerContext &C) const

Called before the Return statement in the function is ready to execute (fires for every Return statement);

evalCall (const CallExpr* CE, CheckerContext &C) const

Trigger execution when a function call statement is encountered;

checkEndFunction (CheckerContext &C) const

Trigger the call after the execution of the entire function path is completed;

checkBind (Sval L, Sval R, const Stmt* S, CheckerContext &C) const

When a value is bound to an address in a statement to trigger a call (for example, after the assignment operation "=" in C language is executed), the specific value can be obtained;

An example of the Bluetooth lock check process:

int bluesleepproc(struct bluetoothsleepdata *bsdata) 
{
 intretval = 0;
wake_lock(&bs_data->wake_lock);     //增加evalCall检查点,记录当前已经持锁的信息
 retval =request_irq(bs_data->host_wake_irq, bluesleep_hostwake_isr,
IRQF_DISABLED | IRQF_TRIGGER_RISING |
IRQF_NO_SUSPEND, "bluetoothhostwake", bs_data);   
if (retval < 0) {
   pr_err("%s: couldn't acquire BT_HOST_WAKE IRQ",__func__);     
   goto err_request_irq;  
}
if (!test_bit(BT_PROTO,&bs_data->flags)) {    
   up(&bs_data->bt_seam);     
   pr_err("%s: bluesleep already stop\n", __func__);      
   return -1;  //增加checkEndFunction检查点,因为没释放持锁,所以report warning
}
errrequestirq:
wake_unlock(&bs_data->wake_lock);    //增加evalCall检查点,正常释放持锁信息
pr_info("%s, bluetooth power manage unitstop -.\n", __func__);
return retval;
} //函数的每个分支结束时,都会触发调用checkEndFunction

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324455215&siteId=291194637