Các bài cùng serial: Tối ưu xử lý ảnh dung lượng lớn trong Node.js
- Tối ưu xử lý bộ nhớ khi xử lý ảnh trong Node.js(bạn đang xem)
- Cách giải phóng bộ nhớ sau mỗi ảnh được xử lý khi dùng sharp trong Node.js
- Cách giải phóng bộ nhớ sau mỗi lần trim ảnh với thư viện trim-image trong Node.js
Tối ưu xử lý bộ nhớ khi xử lý ảnh trong Node.js với hai thư viện:
trim-image
– Dùng để cắt bỏ viền ảnh thừa.sharp
– Một thư viện mạnh mẽ để xử lý ảnh nhanh chóng, hỗ trợ nhiều định dạng và tối ưu bộ nhớ tốt hơn.
✅ Bài sẽ gồm:
1️⃣ Giới thiệu vấn đề & giải pháp tổng quát
2️⃣ Tối ưu trim-image
để tránh full bộ nhớ
3️⃣ Tối ưu sharp
để xử lý ảnh nhanh hơn & tiết kiệm RAM
4️⃣ So sánh trim-image
vs sharp
& lựa chọn tối ưu
🔥 Phần 1: Giới thiệu vấn đề và giải pháp tổng quát
- Vì sao xử lý ảnh số lượng lớn dễ gây lỗi out of memory?
- So sánh
trim-image
vàsharp
:- Khi nào nên dùng
trim-image
? - Khi nào nên dùng
sharp
?
- Khi nào nên dùng
- Các cách tối ưu bộ nhớ trong Node.js:
- Giải phóng bộ nhớ bằng Garbage Collector (
global.gc()
) - Hạn chế số lượng ảnh xử lý đồng thời (
p-limit
) - Xử lý ảnh theo từng phần bằng Streams
- Dùng Worker Threads để tối ưu CPU đa luồng
- Giải phóng bộ nhớ bằng Garbage Collector (
🔥 Phần 2: Tối ưu bộ nhớ khi xử lý ảnh với trim-image
- Vấn đề thường gặp:
trim-image
không tự động giải phóng bộ nhớ khi xử lý hàng loạt ảnh - Giải pháp:
✅ Dùngglobal.gc()
để ép Garbage Collector thu hồi bộ nhớ
✅ Sử dụngp-limit
để giới hạn số ảnh xử lý đồng thời
✅ DùngWorker Threads
để tách việc xử lý ảnh ra khỏi main thread
📌 Ví dụ code tối ưu với trim-image
:
const pLimit = require('p-limit');
const trimImage = require('trim-image');
const limit = pLimit(2); // Giới hạn 2 ảnh chạy cùng lúc
async function processImage(input, output) {
return new Promise((resolve, reject) => {
trimImage(input, output, (err) => {
if (err) return reject(err);
console.log(`✅ Trimmed: ${output}`);
// Giải phóng bộ nhớ
if (global.gc) global.gc();
resolve();
});
});
}
// Danh sách ảnh cần xử lý
const images = [
{ input: 'input1.jpg', output: 'output1.jpg' },
{ input: 'input2.jpg', output: 'output2.jpg' },
{ input: 'input3.jpg', output: 'output3.jpg' }
];
// Xử lý ảnh với giới hạn số lượng
async function processImages() {
const tasks = images.map(img => limit(() => processImage(img.input, img.output)));
await Promise.all(tasks);
}
processImages();
🔥 Phần 3: Tối ưu bộ nhớ khi xử lý ảnh với sharp
- Lý do dùng
sharp
thay vìtrim-image
trong một số trường hợpsharp
có thể xử lý ảnh theo luồng (streaming), giúp tiết kiệm RAMsharp
có thể nén ảnh, thay đổi định dạng để giảm dung lượng
- Giải pháp:
✅ Dùng Streams để tránh load toàn bộ ảnh vào RAM
✅ Dùngp-limit
để giới hạn số ảnh xử lý đồng thời
✅ Xóa buffer ảnh khỏi bộ nhớ sau khi xử lý
📌 Ví dụ code tối ưu với sharp
:
const sharp = require('sharp');
const fs = require('fs');
const pLimit = require('p-limit');
const limit = pLimit(2); // Giới hạn 2 ảnh xử lý cùng lúc
async function processImage(input, output) {
return new Promise((resolve, reject) => {
const readStream = fs.createReadStream(input);
const writeStream = fs.createWriteStream(output);
readStream
.pipe(sharp().trim())
.pipe(writeStream)
.on('finish', () => {
console.log(`✅ Trimmed: ${output}`);
resolve();
})
.on('error', reject);
});
}
// Danh sách ảnh cần xử lý
const images = [
{ input: 'input1.jpg', output: 'output1.jpg' },
{ input: 'input2.jpg', output: 'output2.jpg' }
];
async function processImages() {
const tasks = images.map(img => limit(() => processImage(img.input, img.output)));
await Promise.all(tasks);
}
processImages();
🔥 Phần 4: So sánh hiệu suất trim-image
vs sharp
- Bài test benchmark với nhiều ảnh khác nhau
- Khi nào dùng
trim-image
, khi nào dùngsharp
? - Tóm tắt phương pháp tối ưu bộ nhớ tốt nhất
Loạt bài này sẽ giúp bạn xử lý hàng loạt ảnh mà không lo hết RAM hoặc quá tải CPU! 🚀