Skip to main content

What are some best practices for reducing memory usage in C?

Thiếu memory khi lập trình Arduino và cách giải quyết.

Lacking memory with Arduino program.

Đây là một số gợi ý để giải quyết nếu bạn đã từng thấy warning dưới:

Have you ever seen any below warning?
- Low memory available, stability problems may occur.
- Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint.
If the answer is YES, i would like to suggest some solutions for saving memory in this articles.

Các nguyên nhân:

Some root causes:

1. Khai báo biến local tràn lan.

2. Dùng hàm lcd.print or serial.print tùy tiện.

3. Cấp phát động tùy tiện, ko tính toán kỹ lưỡng số lượng phần từ trong mảng cần dùng.

....

Một số gợi ý để tiết kiệm memory 

Some suggestions to save memory.

- Sử dụng một số kỹ thuật như #pragma pack(), union, bit field, cấp phát động.

            Using some C technique #pragma pack(), union, bit field, dynamic memory allocation.

- Sử dụng con trỏ một cách khéo léo.

            Using smart pointer.

- Chuyển các chuỗi hiển thị vào flash, thay vì chạy từ RAM.

            Moving constant string to flash.

- ...


Chi tiết:
Detail:
1.Sử dụng pragma pack để loại bỏ các byte thừa khi khai báo struct
1. Use #pragma pack(1) to byte align your structures



Ví dụ:


int calibration_req(){

  int ret = -1;
  
  ret = system("/usr/sbin/touch-calibration &") ;
  
  return ret;
}
Bộ nhớ sẽ lưu cấu trúc trên như sau:
"Shape" of Above structure in memory.
|   1   |   2    |   3    |   4    |
| AA(1) |padbyte |padbyte |padbyte |
| BB(1) | BB(2)  | BB(3)  | BB(4)  |
| CC(1) |padbyte |padbyte |padbyte |
=> sizeof(Test) là 12 bytes, do hầu hết các compiler sẽ tự động thêm các byte (padding byte) để cho phù hợp với địa chỉ trong bộ nhớ. Ví dụ trên là cho bộ nhớ có địa chỉ 32 bit.
Nếu sử dụng #pragma pack(1)
|   1   |
| AA(1) |
| BB(1) |
| BB(2) |
| BB(3) |
| BB(4) |
| CC(1) |

Nếu sử dụng #pragma pack(2)

|   1   |   2   |
| AA(1) | padbyte |
| BB(1) | BB(2)   |
| BB(3) | BB(4)   |
| CC(1) | padbyte |

Cách dùng:
How to use:
#pragma pack(1)
struct Test;

2. Sử dụng union cho các structure có các kiểu dữ liệu khác nhau
2. Use unions where a structure can contain different types of data
Ví dụ:
typedef struct {
            int                    mode;
            int                    blLevel;
} CMD_PRM_1_t;
typedef struct {
            DateTime          initDateTime;
            char[32]            alarmDispText;
} CMD_PRM_2_t;
typedef enum {
            CMD_0              = 0,
            CMD_1              = 1
} CMD_t;
typedef struct {
  CMD_t command_id;
  union{
    CMD_PRM_1_t      lcdSetting;
    CMD_PRM_2_t      alarmSetting;
 } prm;
} CMD_INFO_t;
Cách khai bảo này có nhiều lợi điểm:
Advantage:

1.Linh hoạt trong việc thay đổi cấu trúc command ( bao gồm command_id và command_prm)
More flexibility to change command structure.

2. Chỉ dùng 1 struct CMD_INFO_t cho tất cả các hàm liên quan đến xử lý command.
Interface with only one struct CMD_INFO_t to react with any command.

3. Có thể define nhiều kiểu parameter trong union nhưng chỉ có MỘT member có thể có giá trị trong một thời điểm => chỉ sử dụng 1 memory location cho nhiều mục đích.
Able to declare multiple parameter in union. But only one member is set value in given time.

3. Sử dụng bit field để lưu các cờ và số nguyên nhỏ.
3. Use bit fields rather than ints to store flags and small integers.

Ví dụ:
unsigned int mainStatusFlag;     //0: Idle, 1: Run, 2 OnHold
unsigned receiveDataFlag;         //0: Receive, 1 Not receive
unsigned int ledState                             //0: green, 1:red, 2:violet, 3:yellow, 4:orange, 5:grey
=> 3 biến trên mất ít nhất 3 bytes.

struct
{
            unsigned int      maiStatusFlag:2;
            unsigned int      receiveDataFlag:1;
            unsigned int      ledState:3
            unsigned int      reserve:2
}Flag_t;
=> Cấu trúc trên tốn 1 byte bộ nhớ.

4. Sử dụng string pool để chứa các chuỗi const cần hiển thị.
4. Implement a string pool and use pointers.
Ví dụ khi ta muốn hiển thị một string lên lcd
Thông thường ta có thể viết lcd.print("Hello Trumpy");

Việc này tiêu tốn một lượng memory nhất định để store string "Hello Trumpy" trước khi hiển thị ra. Với những ứng dụng đỏi hỏi phải hiển thị string nhiều, nó sẽ đỏi hỏi kha khá memory.

Cách xử lý:
- Chuyển các string này vào bộ nhớ flash. Sau đó dùng con trỏ để trỏ đến đó mỗi khi cần hiển thị

Khai báo:
const char EN0 [] PROGMEM = "Hello Trumpy";
const char EN0 [] PROGMEM = "I love arduino";
const char* const librarieEN[] PROGMEM = {EN0, EN1};

Sử dụng:
lcd.print( (const __FlashStringHelper *) pgm_read_word(&(librarieEN[EN0])) );
lcd.print( (const __FlashStringHelper *) pgm_read_word(&(librarieEN[EN1])) );

Với cách này, memory sẽ giảm đáng kế do dư liệu hiển thị được đọc trực tiếp từ flash và dữ liệu hiển thị cũng được tổ chức tốt hơn.

5. Sử dụng cấp phát động. Tính toán kỹ lưỡng số lượng phần tử trước khi cấp phát bộ nhớ.
5. When using dynamic memory allocation, compute the number of elements required in advance to avoid reallocs.

Tham khảo
Reference

https://learn.adafruit.com/memories-of-an-arduino/optimizing-sram

Comments

Popular posts from this blog

[Git] Handle trailing space when patching with git

After complete coding one module in development branch. Next phase is merging. Obviously, you can merge source code automatically without no errors happen. However, life is not dream. Create a patch git diff HEAD > newTariff.patch Apply patch git apply newTariff.patch then problem happens Problem git apply newTariff.patch:106: trailing whitespace. patch does not apply Route cause: Nguyên nhân: Do trong source code có những dấu space thừa (ô vuông màu đỏ hình dưới) Some whitespaces is existed in your patch. (red area in below pictures) Fix Clean white space and patch again. Cách khắc phục Xóa những dấu space này đi và thực hiện patch lại Make up after complete coding. Find and clean whitespace before create patch file. Sửa sau khi code xong Kiểm tra sau khi code xong có lỗi này không git diff HEAD --check Prevent whitespace by manually when typing source code Sửa ngay khi đang code =>Bật chức năng hiển thị các dấu whitespace, hoặc remove trailing ...

How to test frame buffer in linux

The intended goal of this article is to provide the user with enough information so they can display an image onto a screen of their choosing. How to re-build frame buffer testing application. Base knowledge http://trac.gateworks.com/wiki/OpenEmbedded/Video_Out Frame buffer test application - rebuild fb-test-app step 1: Download soure code ( git installed on your machine and account in git-hub is required) https://github.com/prpplague/fb-test-app Command in git: git init git clone https://github.com/prpplague/fb-test-app.git step 2: Change makefile vi Makefile //open Makefile by vim editor :set nu //show line number replace from line 6 to line 12 by folow code: CC=arm-linux-gnueabi-gcc CFLAGS=-02 -Wall Save change command :wq step 3: Rebuid Type “make” command step 4: Copy execute file to target system by filezilla or something like that step 5: Remote target by root account, change mode of execute file (what copied from host) ...

[Vi] Công nghệ phát triển ngược đời - How is AI harming my world

Tiếng cười khanh khách của mấy cậu sinh viên quốc tế người Bắc Ấn sau bài kiểm tra cuối khóa (a final exam) làm gã thấy buồn một góc tâm hồn. Sự trống rỗng ngay lập tức xâm chiếm lấy tâm trí gã sau khi nộp bài môn thi cuối cùng của kỳ học. Gã hiểu gã quá mà, gã đang cố gắng giải thích cho nỗi nhục của chính bản thân ở bên trong. Đầu gã thoáng nghĩ về cái lần thi cuối kỳ một môn học ở bậc thạc sỹ nơi quê nhà hơn mười năm về trước, cái ánh mắt khinh bỉ đến ám ảnh của một anh dọn vệ sinh dành cho những học viên cao học đang quay cóp trong giờ thi của một trường đại học hàng đầu quốc gia như vết dao khứa vào lòng tự trọng của gã. Vết thương vẫn nhói đau lại khi những mùa thi đến. Một lão già sinh viên quốc tế ranh ma. Gã đang học lại cái thứ mà gã đã học từ hai mươi năm về trước với một thứ ngôn ngữ không mới và cái tâm bằng sắt nung. Kinh nghiệm làm việc chuyên môn lâu năm cộng với việc vừa được trang bị thứ vũ khí khoa học tối tân AI (Trí truệ nhân tạo) khiến lão trở thành sát thủ trong ...