Hướng dẫn wordpress memory leak - rò rỉ bộ nhớ wordpress

Giới thiệu

Cách đây vài tháng, tôi gặp phải lỗi “Memory Leak - thất thoát bộ nhớ” trong Node.js. Tôi đã tìm thấy một vài tài liệu có liên quan đến vấn đề này. Nhưng sau khi đọc một cách tỉ mỉ xong, tôi vẫn cảm thấy bối rối, không biết thực sự nên làm gì để debug được lỗi này.

Trong bài này tôi muốn hướng dẫn các bạn phát hiện các vấn đề về “Memory Leak”  trong Node.js. Tôi sẽ phác thảo một cách đơn giản các tiếp cận, theo ý kiến của tôi thì đó sẽ là điểm khởi đầu  để debug của bất kỳ vấn đề “Memory Leak” trong Node.js. Đối với một số trường hợp thì cách tiếp cận này sẽ là không đủ nên tôi sẽ link đến một vài nguồn khác mà bạn có thể xem.

Học thuyết tối thiểu

JavaScript là một ngôn ngữ “garbage collected” [tự động dọn dẹp biến nếu biến không còn cần thiết nữa]. Vì vậy, tất cả các bộ nhớ được sử dụng bởi một quá trình Node đang được tự động phân bổ và thu hồi 4 bởi engine  JavaScript V8.

Khi nào thì Javascript V8 sẽ thu hồi bộ nhớ đã cấp phát? Cơ chế này chứa một đồ thị các biến của chương trình, bắt đầu từ nút gốc. Có 4 kiểu dữ liệu trong JavaScript : Boolean, String, Number, Object.  Với 3 kiểu dữ liệu đầu tiên, hệ thống sẽ lưu trữ các giá trị được gán cho biến đó. Còn đối với kiểu Object, và các thức khác trong JS có kiểu là Object [ vd : Type of Array = object ], thì hệ thống sẽ lưu trữ con trỏ tới object đóBoolean, String, Number, Object.  Với 3 kiểu dữ liệu đầu tiên, hệ thống sẽ lưu trữ các giá trị được gán cho biến đó. Còn đối với kiểu Object, và các thức khác trong JS có kiểu là Object [ vd : Type of Array = object ], thì hệ thống sẽ lưu trữ con trỏ tới object đó

Engine V8 Javascript sẽ duyệt trong Memory Graph [một đồ thị gồm nhiều nút, đường nối giữa các nút là mối liên hệ tham chiếu hoặc sử dụng nhau] , sẽ cố xác định những nhóm dữ liệu mà nút gốc không thể tìm đến. Nếu gặp trường hợp này thì, V8 sẽ giả định rằng dữ liệu này sẽ không còn được sử dụng nữa và sẽ thu hồi bộ nhớ. Quá trình này gọi là Garbage Collected [dọn rác]Garbage Collected [dọn rác]

Khi nào gặp phải trường hợp “Memory Leak”?

“Memory Leak” trong NodeJs gặp phải khi mà có một dữ liệu không cần thiết mà nút gốc vẫn có thể tìm tới  được . V8 sẽ cho rằng dữ liệu này vẫn đang được sử dụng và sẽ không giải phóng bộ nhớ. Để debug được lỗi này thì chúng ta cần phải xác định được dữ liệu  bị lưu giữ do nhầm lẫn, và chắn chắn rằng V8 có thể dọn sạch nó.

Cũng phải nói rằng Garbage Collection không phải lúc nào cũng chạy. Thông thường V8 chỉ cho GC chạy khi thích hợp. Ví dụ như, GC có thể chạy định kỳ hoặc nó có thể kích hoạt khi cảm nhận thấy bộ nhớ còn lại đang xuống thấp. Mỗi node sẽ có một không gian bộ nhớ nhất định trong mỗi tiến trình, vì vậy V8 sẽ sử dụng chúng một cách khôn ngoan nhất.

Các trường hợp sau này khi mà hết số lượt sử dụng GC , có thể là dấu hiệu cho thấy hệ thống đang giảm hiệu suất một cách đáng kể.

Ví dụ bạn có một ứng dụng bị tràn bộ nhớ nhiều lần. Tiến trình bị hết bộ nhớ, và số lần kích hoạt GC đã hết. Nhưng vẫn còn nhiều dữ liệu được tìm tới bởi nút gốc, chỉ một phần nhỏ dữ liệu được dọn về cùng một chỗ.

Và có thể ngay sau đó, các tiến trình có thể bị “out-of-memory”  lần nữa, và GC lại sẽ bị tiếp tục kích hoạt. Trước khi bạn phát hiện ra, thì app của bạn sẽ đi vào một vòng lặp như trên, chỉ là cố gắng giữ cho các tiến trình hoạt động, trong khi V8 phải dành phần lớn thời gian để xử lý GC, còn rất ít tài nguyên dành cho chương trình thực sự

Bước 1 : Ghi lại và xác nhận các vấn đề gặp phải

Như đã nói ở trên, V8 có một logic vô cùng phức tập mà nó sử dụng để quyết định khi nào thì GC sẽ được kích hoạt.  Vì vậy, mặc dù có thể chúng ta có thể thấy được rằng bộ nhớ của tiến trình chiếm ngày càng tăng, chúng ta không thể chắc chắn rằng hệ thống bị tràn bộ nhớ hay là chương trình đang chạy đúng, cho tơi khi GC được khởi chạy.

Thật là may, Node cho phép chúng ta có thể tự kích hoạt GC, và đó có thể là điều chúng ta có thể làm để cố gắng xác nhận là đang gặp phải trường hợp tràn bộ nhớ. Điều này có thể được thực hiện bằng cách thêm lựa chọn –expose-gc. Một khi tiến trình đã được khởi chạy với option –expose-gc thì chúng ta có thể gọi GC bằng cách gọi hàm global.gc[].–expose-gc. Một khi tiến trình đã được khởi chạy với option –expose-gc thì chúng ta có thể gọi GC bằng cách gọi hàm global.gc[].

Bạn cũng có thể kiểm tra lượng bộ nhớ mà tiến trình của bạn chiếm bằng cách gọi process.memoryUsage[].heapUsed.

Ví dụ

"use strict";
require['heapdump'];
 
var leakyData = [];
var nonLeakyData = [];
 
class SimpleClass {
  constructor[text]{
    this.text = text;
  }
}
 
function cleanUpData[dataStore, randomObject]{
  var objectIndex = dataStore.indexOf[randomObject];
  dataStore.splice[objectIndex, 1];
}
 
function getAndStoreRandomData[]{
  var randomData = Math.random[].toString[];
  var randomObject = new SimpleClass[randomData];
 
  leakyData.push[randomObject];
  nonLeakyData.push[randomObject];
 
  // cleanUpData[leakyData, randomObject]; //

Bài Viết Liên Quan

Chủ Đề