2013-06-03 30 views
31

Tôi đã nhận thấy rằng bộ nhớ của trình duyệt bắt đầu tăng lên trong khi tôi đang ở dạng (điều này đáng chú ý từ trình quản lý tác vụ). Trong IE 9, điều này dễ dàng vượt quá 500MB sau khi sử dụng một số, trong khi chrome là khả năng đàn hồi hơn (đi đến 200MB sử dụng cùng một thử nghiệm).Rò rỉ bộ nhớ Javascript: Cây DOM bị tách

Tôi đang sử dụng công cụ nhà phát triển Chrome để gỡ lỗi sự cố này. Tôi đã nhận thấy rằng có một số lượng lớn các cây tách rời DOM:

detached dom tree screenshot

Tôi giả định rằng điều này có thể khẳng định rằng có một rò rỉ bộ nhớ. Điều đó có đúng không? Thứ hai, tôi sẽ cần phải tìm hiểu làm thế nào để xác định nguyên nhân gốc rễ của vấn đề. Tôi biết rằng bạn nên sử dụng cây giữ lại để xác định những gì đang ngăn chặn các mục đó khỏi bị khai hoang. Nhưng tôi không thể tìm ra cách sử dụng cây giữ lại. Ví dụ, cây giữ lại trong ảnh chụp màn hình ở trên có nghĩa là gì?

Bất kỳ hỗ trợ nào sẽ được đánh giá rất nhiều.

+2

Bạn có thể làm rõ 'bộ nhớ của trình duyệt bắt đầu tăng lên trong khi tôi đang ở trong biểu mẫu' với một số mã không? Điều đó giúp tìm rò rỉ bộ nhớ. – Ikrom

+0

[câu hỏi/câu trả lời khác] này (http://stackoverflow.com/questions/11930050/finding-js-memory-leak-in-chrome-dev-tools) có giúp bạn không? – msung

Trả lời

25

Có nhiều cân nhắc cần ghi nhớ khi bạn viết mã tham chiếu đến các phần tử DOM. Nhưng tất cả về cơ bản chỉ tóm tắt một vài điểm đơn giản -

a. Trong các hàm địa phương của bạn, hãy luôn xóa tham chiếu

var menu = $('body #menu'); 
// do something with menu 
. 
. 
. 
menu = null; 

b. Không bao giờ lưu trữ các tham chiếu như một phần của dữ liệu phần tử .data()

c. Cố gắng không để sử dụng DOM tài liệu tham khảo bên trong bộ xử lý đóng cửa/inline, thay vì vượt qua định danh

function attachClick(){ 
     var someDiv = $('#someDiv'); 

     someDiv.click(function(){ 
     var a = someDiv....; 
     //Wrong. Instead of doing this.. 
     }); 


     someDiv.click(function(){ 
     var a = $('#someDiv'); 
     //Pass the identifier/selector and then use it to find the element 
     });  


     var myFunc = function(){ 
     var a = someDiv; 
     //using a variable from outside scope here - big DON'T!    
     } 
    } 

Vâng, người ta có thể tranh luận rằng việc tìm kiếm các yếu tố có thể làm chậm trang xuống, nhưng sự chậm trễ là rất tối thiểu khi so sánh với hiệu suất đạt mức khổng lồ đống nguyên nhân đặc biệt. trong các ứng dụng trang đơn lớn. Do đó, # 3 chỉ nên được sử dụng sau khi cân nhắc ưu và nhược điểm. (Nó đã góp phần đáng kể trong trường hợp của tôi)

CẬP NHẬT

d. Tránh các hàm ẩn danh - Đặt tên cho trình xử lý sự kiện và các hàm cục bộ của bạn sẽ giúp bạn rất nhiều trong khi định hình/xem các ảnh chụp nhanh heap.

+0

Tôi sẽ không đồng ý với (c), thời gian duy nhất điều này sẽ gây ra vấn đề nếu cuộc gọi hàm tiếp theo trả về kết thúc hoặc thực hiện thao tác giữ lại tham chiếu đến phần tử dom đã được chuyển (hoặc jQuery bọc phần tử) - tức lànhư lưu trữ phần tử trong danh sách tĩnh hoặc tạo một số tham chiếu vòng tròn. Bạn có một ví dụ về nơi mà chỉ cần đi qua một phần tử để một phương pháp sẽ gây ra một vấn đề? – Pebbl

+2

@pebbl: Tôi đã kiểm tra bằng mã của mình. Bạn đúng. Tôi có nghĩa là đóng cửa và không chỉ đơn giản là đưa chúng vào phương pháp. Ví dụ đã sửa ở trên. –

+0

Ah, hay. Cảm ơn bạn đã làm rõ, rõ ràng hơn nhiều. – Pebbl

2

Có vẻ như mã của bạn tạo nhiều subtrees DOM và giữ tham chiếu đến nó từ javascript. Bạn cần phải chọn một yếu tố từ một cây dom tách rời. Theo ảnh chụp bạn nên chọn phần tử Văn bản. Và nhìn vào cây thuộc hạ.

Cây này hiển thị cho bạn tất cả các đường dẫn giữ đối tượng còn sống. Ít nhất một đường dẫn, thường là đường dẫn ngắn nhất, sẽ dẫn bạn đến đối tượng cửa sổ. Nếu bạn quen thuộc với mã thì bạn có thể dễ dàng tìm thấy đối tượng trong đường dẫn đó phải bị xóa nhưng không. Có thể có nhiều đối tượng như vậy trong đường dẫn. Vật thể có khoảng cách nhỏ nhất thú vị hơn.

Các vấn đề liên quan