পারফরমেন্স অপ্টিমাইজেশন
Sharp ইতিমধ্যে একটি উচ্চ-পারফরমেন্স ইমেজ প্রসেসিং লাইব্রেরি, তবে কিছু অপ্টিমাইজেশন কৌশলের মাধ্যমে আপনি আরও পারফরমেন্স উন্নত করতে পারেন।
বেঞ্চমার্ক টেস্ট
অন্যান্য ইমেজ প্রসেসিং লাইব্রেরির তুলনায় Sharp-এর পারফরমেন্স সুবিধা:
- ImageMagick-এর চেয়ে 4-5 গুণ দ্রুত
- GraphicsMagick-এর চেয়ে 4-5 গুণ দ্রুত
- কম মেমরি ব্যবহার
- স্ট্রিম প্রসেসিং সমর্থন
মেমরি অপ্টিমাইজেশন
স্ট্রিম প্রসেসিং ব্যবহার করুন
বড় ফাইলের জন্য, স্ট্রিম প্রসেসিং ব্যবহার করে মেমরি ব্যবহার উল্লেখযোগ্যভাবে হ্রাস করা যায়:
javascript
import fs from 'fs';
// ❌ সুপারিশ করা হয় না: পুরো ফাইল মেমরিতে লোড করুন
const buffer = fs.readFileSync('large-image.jpg');
await sharp(buffer).resize(800, 600).toFile('output.jpg');
// ✅ সুপারিশ করা হয়: স্ট্রিম প্রসেসিং ব্যবহার করুন
fs.createReadStream('large-image.jpg')
.pipe(sharp().resize(800, 600).jpeg())
.pipe(fs.createWriteStream('output.jpg'));চাঙ্ক প্রসেসিং
অতিবড় ফাইলের জন্য, চাঙ্ক প্রসেসিং করা যায়:
javascript
import fs from 'fs';
async function processLargeFile(inputPath, outputPath, chunkSize = 1024 * 1024) {
const pipeline = sharp()
.resize(800, 600)
.jpeg({ quality: 80 });
return new Promise((resolve, reject) => {
const readStream = fs.createReadStream(inputPath, { highWaterMark: chunkSize });
const writeStream = fs.createWriteStream(outputPath);
readStream
.pipe(pipeline)
.pipe(writeStream)
.on('finish', resolve)
.on('error', reject);
});
}
await processLargeFile('large-input.jpg', 'output.jpg');সময়মতো মেমরি মুক্ত করুন
javascript
// প্রসেসিং সম্পন্ন হলে সময়মতো পরিষ্কার করুন
async function processImage(inputPath, outputPath) {
const sharpInstance = sharp(inputPath);
try {
await sharpInstance
.resize(800, 600)
.jpeg({ quality: 80 })
.toFile(outputPath);
} finally {
// ম্যানুয়ালি পরিষ্কার করুন (যদিও Node.js স্বয়ংক্রিয়ভাবে গার্বেজ কালেকশন করবে)
sharpInstance.destroy();
}
}কনকারেন্সি অপ্টিমাইজেশন
কনকারেন্সি সংখ্যা নিয়ন্ত্রণ করুন
javascript
async function processWithConcurrency(files, concurrency = 3) {
const results = [];
for (let i = 0; i < files.length; i += concurrency) {
const batch = files.slice(i, i + concurrency);
const batchPromises = batch.map(file =>
sharp(file)
.resize(300, 200)
.jpeg({ quality: 80 })
.toFile(`processed-${file}`)
);
const batchResults = await Promise.all(batchPromises);
results.push(...batchResults);
}
return results;
}
const files = ['file1.jpg', 'file2.jpg', 'file3.jpg', 'file4.jpg'];
await processWithConcurrency(files, 2);Worker থ্রেড ব্যবহার করুন
CPU-ইনটেনসিভ টাস্কের জন্য, Worker থ্রেড ব্যবহার করা যায়:
javascript
import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
if (isMainThread) {
// মেইন থ্রেড
async function processWithWorkers(files, numWorkers = 4) {
const workers = [];
const results = [];
for (let i = 0; i < numWorkers; i++) {
const worker = new Worker('./image-worker.js', {
workerData: { files: files.slice(i * Math.ceil(files.length / numWorkers), (i + 1) * Math.ceil(files.length / numWorkers)) }
});
worker.on('message', (result) => {
results.push(result);
});
workers.push(worker);
}
await Promise.all(workers.map(worker => new Promise(resolve => worker.on('exit', resolve))));
return results;
}
const files = ['file1.jpg', 'file2.jpg', 'file3.jpg'];
await processWithWorkers(files);
} else {
// Worker থ্রেড
const { files } = workerData;
for (const file of files) {
await sharp(file)
.resize(300, 200)
.jpeg({ quality: 80 })
.toFile(`processed-${file}`);
}
parentPort.postMessage('done');
}ক্যাশে অপ্টিমাইজেশন
প্রসেসিং ফলাফল ক্যাশে করুন
javascript
import crypto from 'crypto';
import fs from 'fs';
class ImageCache {
constructor(cacheDir = './cache') {
this.cacheDir = cacheDir;
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir, { recursive: true });
}
}
generateCacheKey(inputPath, options) {
const content = JSON.stringify({ inputPath, options });
return crypto.createHash('md5').update(content).digest('hex');
}
async getCachedResult(cacheKey) {
const cachePath = `${this.cacheDir}/${cacheKey}.jpg`;
if (fs.existsSync(cachePath)) {
return cachePath;
}
return null;
}
async setCachedResult(cacheKey, resultPath) {
const cachePath = `${this.cacheDir}/${cacheKey}.jpg`;
fs.copyFileSync(resultPath, cachePath);
}
async processImage(inputPath, options) {
const cacheKey = this.generateCacheKey(inputPath, options);
const cached = await this.getCachedResult(cacheKey);
if (cached) {
console.log('ক্যাশে ফলাফল ব্যবহার করুন');
return cached;
}
const outputPath = `output-${Date.now()}.jpg`;
await sharp(inputPath)
.resize(options.width, options.height)
.jpeg({ quality: options.quality })
.toFile(outputPath);
await this.setCachedResult(cacheKey, outputPath);
return outputPath;
}
}
const cache = new ImageCache();
await cache.processImage('input.jpg', { width: 300, height: 200, quality: 80 });অ্যালগরিদম অপ্টিমাইজেশন
উপযুক্ত রিসাইজ অ্যালগরিদম নির্বাচন করুন
javascript
// ফটোর জন্য, lanczos3 কার্নেল ব্যবহার করুন
await sharp('photo.jpg')
.resize(800, 600, { kernel: sharp.kernel.lanczos3 })
.toFile('photo-resized.jpg');
// আইকন বা লাইন আর্টের জন্য, nearest কার্নেল ব্যবহার করুন
await sharp('icon.png')
.resize(32, 32, { kernel: sharp.kernel.nearest })
.toFile('icon-resized.png');
// দ্রুত প্রসেসিং প্রয়োজন এমন ইমেজের জন্য, cubic কার্নেল ব্যবহার করুন
await sharp('image.jpg')
.resize(300, 200, { kernel: sharp.kernel.cubic })
.toFile('image-resized.jpg');JPEG কোয়ালিটি অপ্টিমাইজ করুন
javascript
// ইমেজ কনটেন্ট অনুযায়ী কোয়ালিটি অ্যাডজাস্ট করুন
async function optimizeJPEGQuality(inputPath, outputPath) {
const metadata = await sharp(inputPath).metadata();
// ইমেজ আকার অনুযায়ী কোয়ালিটি অ্যাডজাস্ট করুন
let quality = 80;
if (metadata.width > 1920 || metadata.height > 1080) {
quality = 85; // বড় ইমেজের জন্য উচ্চ কোয়ালিটি ব্যবহার করুন
} else if (metadata.width < 800 && metadata.height < 600) {
quality = 75; // ছোট ইমেজের জন্য নিম্ন কোয়ালিটি ব্যবহার করা যায়
}
await sharp(inputPath)
.jpeg({
quality,
progressive: true, // প্রগ্রেসিভ JPEG
mozjpeg: true // mozjpeg অপ্টিমাইজেশন ব্যবহার করুন
})
.toFile(outputPath);
}নেটওয়ার্ক অপ্টিমাইজেশন
বিভিন্ন আকার প্রি-জেনারেট করুন
javascript
const sizes = [
{ width: 320, suffix: 'sm' },
{ width: 640, suffix: 'md' },
{ width: 1024, suffix: 'lg' },
{ width: 1920, suffix: 'xl' }
];
async function pregenerateSizes(inputPath) {
const promises = sizes.map(size =>
sharp(inputPath)
.resize(size.width, null, { fit: 'inside' })
.jpeg({ quality: 80 })
.toFile(`output-${size.suffix}.jpg`)
);
await Promise.all(promises);
}
await pregenerateSizes('input.jpg');আধুনিক ফরম্যাট ব্যবহার করুন
javascript
// বিভিন্ন ব্রাউজার সমর্থনের জন্য একাধিক ফরম্যাট জেনারেট করুন
async function generateModernFormats(inputPath) {
const promises = [
// ফলব্যাক হিসেবে JPEG
sharp(inputPath)
.resize(800, 600)
.jpeg({ quality: 80 })
.toFile('output.jpg'),
// আধুনিক ব্রাউজারের জন্য WebP
sharp(inputPath)
.resize(800, 600)
.webp({ quality: 80 })
.toFile('output.webp'),
// সর্বশেষ ব্রাউজারের জন্য AVIF
sharp(inputPath)
.resize(800, 600)
.avif({ quality: 80 })
.toFile('output.avif')
];
await Promise.all(promises);
}মনিটরিং এবং ডিবাগিং
পারফরমেন্স মনিটরিং
javascript
import { performance } from 'perf_hooks';
async function measurePerformance(fn) {
const start = performance.now();
const result = await fn();
const end = performance.now();
console.log(`এক্সিকিউশন সময়: ${end - start}ms`);
return result;
}
await measurePerformance(async () => {
await sharp('input.jpg')
.resize(800, 600)
.jpeg({ quality: 80 })
.toFile('output.jpg');
});মেমরি ব্যবহার মনিটরিং
javascript
import { performance } from 'perf_hooks';
function getMemoryUsage() {
const usage = process.memoryUsage();
return {
rss: `${Math.round(usage.rss / 1024 / 1024)}MB`,
heapTotal: `${Math.round(usage.heapTotal / 1024 / 1024)}MB`,
heapUsed: `${Math.round(usage.heapUsed / 1024 / 1024)}MB`,
external: `${Math.round(usage.external / 1024 / 1024)}MB`
};
}
console.log('প্রসেসিংয়ের আগে মেমরি ব্যবহার:', getMemoryUsage());
await sharp('input.jpg')
.resize(800, 600)
.jpeg({ quality: 80 })
.toFile('output.jpg');
console.log('প্রসেসিংয়ের পরে মেমরি ব্যবহার:', getMemoryUsage());সেরা অনুশীলন সারাংশ
- বড় ফাইলের জন্য স্ট্রিম প্রসেসিং ব্যবহার করুন
- কনকারেন্সি সংখ্যা নিয়ন্ত্রণ করুন
- প্রসেসিং ফলাফল ক্যাশে করুন
- উপযুক্ত রিসাইজ অ্যালগরিদম নির্বাচন করুন
- আউটপুট ফরম্যাট এবং কোয়ালিটি অপ্টিমাইজ করুন
- সাধারণ আকার প্রি-জেনারেট করুন
- পারফরমেন্স মেট্রিক্স মনিটর করুন
পারফরমেন্স তুলনা
| অপারেশন | Sharp | ImageMagick | GraphicsMagick |
|---|---|---|---|
| রিসাইজ | 100ms | 450ms | 420ms |
| ফরম্যাট কনভার্শন | 80ms | 380ms | 360ms |
| ফিল্টার প্রয়োগ | 120ms | 520ms | 480ms |
| মেমরি ব্যবহার | কম | বেশি | বেশি |
পরবর্তী ধাপ
- API ডকুমেন্টেশন দেখুন সব উপলব্ধ মেথড জানতে
- উদাহরণ শিখুন আরও ব্যবহার জানতে
- আপডেট লগ দেখুন সর্বশেষ ফিচার জানতে