Download presentation
Presentation is loading. Please wait.
Published byYandi Iwan Sudirman Modified over 5 years ago
1
CS5123 Software Validation and Quality Assurance
Lecture 12 Common Bug Patterns-Performance
2
Major Performance Concerns
Time efficiency Useless function executions In-efficient API invocations Improper parallel execution Memory efficiency Memory Leaks Unused code / data 2
3
Useless function executions
3
4
Useless function executions
4
5
In-efficient API invocations
5
6
In-efficient API invocations
6
7
In-efficient API invocations
SBSC: Method concatenates strings using + in a loop Bad: String s = ""; for (int i = 0; i < field.length; ++i) { s = s + field[i]; } Better: StringBuffer buf = new StringBuffer(); buf.append(field[i]); String s = buf.toString(); 7
8
Improper parallel execution
8
9
Enhancing Time Efficiency
Focus on the frequently executed part of the code Sometimes need to use profilers to find it Adding guard to code that is not always required Understand the performance specification of API methods (i.e., what the method actually does) Be careful of redundant locks in concurrency 9
10
Major Performance Concerns
Time efficiency Useless function executions In-efficient API invocations Improper parallel execution Memory efficiency Memory Leaks Unused code / data 10
11
Memory Leaks A memory leak is said to have occurred when:
the last pointer to a malloc'd object is reset or the last pointer to a malloc'd object is a local variable in a function from which a return is made. In these cases the malloc'd memory is no longer accessible. Excessive leaking can lead to poor performance and, in the extreme, program failure.
12
Memory Leaks Programmers must recognize when the last pointer to malloc'd storage is about to be lost and use the free() function call to release the storage before it becomes impossible to do so.
13
Problem 1: the instant leak
This is an example of an instant leak. The memory is allocated at the time temp is declared and leaked when temp is reassigned the address of the first object in the list. int *temp = (int *) malloc(N * sizeof(int)); temp = list->head; while (temp != NULL) -- process list of objects -- Two possible solutions: Insert free(temp) before temp = list->head; This eliminates the leak, but what benefit is there to allocating storage and instantly freeing it???
14
Problem 1: the instant leak (cont'd)
Possible solution: Instead of allocating memory for temp change the declaration to obj_t *temp = NULL; This is the correct solution Rules of thumb: A rational rule of thumb is never malloc memory unless you are going to write into it! Another good rule of thumb is to never declare a pointer without initializing it.
15
Problem 2: The traditional leak
In this traditional leak, storage is also allocated for univec at the time it is declared. The call to vl_unitvec3() writes into that storage. If the storage is not malloc'd, then univec will not point to anything useful and the call to vl_unitvec3() will produce a seg-fault or will overwrite some other part of the program's data. So this malloc() is necessary. { double *univec = malloc(3 * sizeof(double)); vl_unitvec3(dir, univec); : more stuff involving univec return; }
16
Problem 2: The traditional leak
{ double *univec = malloc(3 * sizeof(double)); vl_unitvec3(dir, univec); : more stuff involving univec return; } Although this malloc is necessary, the instant the return statement is executed, the value of univec becomes no longer accessible and the memory has been leaked. The correct solution is to add free(univec); just before the return;
17
Problem 2: The traditional leak
A rational rule of thumb is: malloc'd storage must be freed before the last pointer to it is lost.
18
Problem 3: Overcompensation
The concern about leakage might lead to an overcompensation. For example, an object loader might do the following: obj_t *new_obj; : new_obj = malloc(sizeof(obj_t)); if (list->head == NULL) { list->head = list->tail = new_obj; } else list->tail->next = new_obj; list->tail = new_obj; free(new_obj);
19
Problem 3: Overcompensation
obj_t *new_obj; : if (…) else { list->tail->next = new_obj; list->tail = new_obj; } free(new_obj); This problem is the reverse of a memory leak . A live pointer to the object exists through the list structure, but the storage has been freed.
20
Problem 3: Overcompensation
else { list->tail->next = new_obj; list->tail = new_obj; } free(new_obj); The results of this are: Usually attempts to reference the freed storage will succeed. The storage will eventually be assigned to another object in a later call to malloc(). Then “both” objects will occupy the same storage.
21
Problem 3: Overcompensation
else { list->tail->next = new_obj; list->tail = new_obj; } free(new_obj); Rational rule of thumb: Never free an object while live pointers to the object exist. Any pointers to the freed storage that exist after the return from free() should be set to NULL. To fix this problem, the free(new_obj) must be deleted from the code. If the objects in the object list are to be freed, it is safe to do so only at the end of processing. It is not imperative to do so at that point because the Operating System will reclaim all memory used by the process when the program exits.
22
Problem 3b: Overcompensation revisited
The free() function must be used only to free memory previously allocated by malloc() unsigned char buf[256]; : free(buf); is a fatal error.
23
Problem 3b: Overcompensation revisited
The free() function must not be used to free the same area twice. buf = (unsigned char *)malloc(256); : free(buf); is also a fatal error.
24
General Solution to Freeing Memory
Even for some complicated programs, it is usually easy for an experienced programmer to know when to free() dynamically allocated storage. In programs as complicated as the Linux kernel it is not. A technique known as reference counting is used.
25
General Solution to Freeing Memory
typedef struct obj_type { int refcount; : } obj_t; At object creation time: new_obj = malloc(sizeof(obj_t)); new_obj->refcount = 1; When a new reference to the object is created my_new_ptr = new_obj; my_new_ptr->refcount += 1;
26
General Solution to Freeing Memory
When a reference is about to be reused or lost my_new_ptr->refcount -= 1; if (my_new_ptr->refcount == 0) free(my_new_ptr); my_new_ptr = NULL; In a multithreaded environment, such as in an OS kernel, it is mandatory that the testing and update of the reference counter be done atomically.
27
Java Memory Leak Memory leaks still exist in Java !!
Lost objects: unreachable but not freed Useless objects: reachable but not used again A Java memory leak can also cause severe problems Performance degradation OutofMemory exception 27
28
Unused Fields Class fields are the major elements that occupy system memory Class fields may have huge number of copies at runtime Objects of subclass often contains all fields of the super classes Objects are sometimes fakely used (e.g., only has a getter) Box types consume much more memory than primitive fields 28
29
Enhancing Memory Efficiency
Avoid memory leak Empty large maps and lists when they are no longer required Understand the memory consumption of objects. Checking for unused fields 29
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.