Làm thế nào để có được kích thước của một đối tượng JavaScript?


296

Tôi muốn biết kích thước chiếm bởi một đối tượng JavaScript.

Thực hiện chức năng sau:

function Marks(){
  this.maxMarks = 100;
}

function Student(){
  this.firstName = "firstName";
  this.lastName = "lastName";
  this.marks = new Marks();
}

Bây giờ tôi khởi tạo student :

var stud = new Student();

để tôi có thể làm những thứ như

stud.firstName = "new Firstname";

alert(stud.firstName);

stud.marks.maxMarks = 200;

Vân vân.

Bây giờ, stud đối tượng sẽ chiếm một số kích thước trong bộ nhớ. Nó có một số dữ liệu và nhiều đối tượng hơn.

Làm thế nào để tôi tìm ra bao nhiêu bộ nhớ mà studđối tượng chiếm? Một cái gì đó giống như mộtsizeof() trong JavaScript? Nó sẽ thực sự tuyệt vời nếu tôi có thể tìm thấy nó trong một cuộc gọi chức năng duy nhất như thế nào sizeof(stud).

Tôi đã tìm kiếm trên Internet hàng tháng trời không thể tìm thấy nó (được hỏi trong một vài diễn đàn mà không có câu trả lời).


41
Có (sẽ phát sinh) rất nhiều lý do tại sao tôi cần tìm kích thước của một đối tượng trong JavaScript. Tôi chưa quen với JavaScript vì vậy tôi không tuân theo các thực tiễn tốt nhất. Tôi vẫn đang học chúng. Tôi đã phát triển một phần mở rộng firefox mà tôi chắc chắn đang sử dụng nhiều bộ nhớ hơn mức cần thiết. Tôi đang làm việc trên một số cách để (hy vọng) giảm việc sử dụng bộ nhớ .. tôi đang nói về hàng ngàn trường hợp nhiều đối tượng trên mỗi tab, vì vậy bộ nhớ có vấn đề! Vấn đề là, tôi muốn biết liệu những nỗ lực giảm trí nhớ của tôi có thực sự giúp giảm trí nhớ không .. và bao nhiêu.

1
Nếu bạn đã xây dựng tiện ích mở rộng FF, tôi khuyên bạn nên điều tra ở cấp độ ngôn ngữ cao hơn JS - hãy xem tác động lên chính FF là gì.
annakata

2
Ngôn ngữ cấp cao hơn JS? Điều đó sẽ là gì trong trường hợp này?

24
Đó không phải là kích thước quan trọng. Đó là cách bạn sử dụng nó. PS: Thật là một stud!
Thomas Eding

13
@SpencerRuport Số một lý do để biết kích thước đối tượng sẽ dành cho các ứng dụng có khả năng ngoại tuyến html5 trong đó đôi khi bạn có không gian lưu trữ hạn chế (5-10Mb có thể bị ăn hết nhanh chóng cho ứng dụng cần nhiều dữ liệu).
David

Câu trả lời:


181

Tôi đã tái xác nhận mã trong câu trả lời ban đầu của tôi . Tôi đã loại bỏ đệ quy và loại bỏ chi phí tồn tại giả định.

function roughSizeOfObject( object ) {

    var objectList = [];
    var stack = [ object ];
    var bytes = 0;

    while ( stack.length ) {
        var value = stack.pop();

        if ( typeof value === 'boolean' ) {
            bytes += 4;
        }
        else if ( typeof value === 'string' ) {
            bytes += value.length * 2;
        }
        else if ( typeof value === 'number' ) {
            bytes += 8;
        }
        else if
        (
            typeof value === 'object'
            && objectList.indexOf( value ) === -1
        )
        {
            objectList.push( value );

            for( var i in value ) {
                stack.push( value[ i ] );
            }
        }
    }
    return bytes;
}

35
bạn cũng có thể muốn nghĩ về các khóa đối tượng
zupa

8
Bất cứ ai hạ cánh ở đây tìm kiếm loại nhỏ nhất cho mục đích sai / đúng, nó dường như không được xác định / null.
zupa

3
"よんもじ".lengthlà 4 trong Javascript, nhưng bạn có chắc là 8 byte không, vì mã của bạn trả về nó?
syockit

8
Vâng. Các ký tự trong JavaScript được lưu trữ theo Thông số kỹ thuật Phiên bản 3 của ECMA-262 - bclary.com/2004/11/07/#a-4.3.16
thomas-peter

4
Hàm này không tính các tham chiếu ẩn trong các bao đóng. Ví dụ var a={n:1}; var b={a:function(){return a}}; roughSizeOfObject(b)- ở đây bgiữ tham chiếu đến a, nhưng roughSizeOfObject()trả về 0.
Roman Pominov

117

Google Chrome Heap Profiler cho phép bạn kiểm tra việc sử dụng bộ nhớ đối tượng.

Bạn cần có khả năng xác định vị trí của đối tượng trong dấu vết có thể khó khăn. Nếu bạn ghim đối tượng vào Window toàn cầu, bạn có thể dễ dàng tìm thấy từ chế độ liệt kê "Ngăn chặn".

Trong ảnh chụp màn hình đính kèm, tôi đã tạo một đối tượng gọi là "testObj" trên cửa sổ. Sau đó tôi nằm trong hồ sơ (sau khi ghi) và nó hiển thị kích thước đầy đủ của đối tượng và mọi thứ trong đó dưới "kích thước giữ lại".

Thêm chi tiết về sự cố bộ nhớ .

Trình hồ sơ Chrome

Trong ảnh chụp màn hình ở trên, đối tượng hiển thị kích thước được giữ lại là 60. Tôi tin rằng đơn vị là byte ở đây.


13
Câu trả lời này đã giải quyết vấn đề của tôi cùng với: developers.google.com/chrome-developer-tools/docs/ ,. Mẹo nhanh: chụp ảnh nhanh Heap Snapshot, chạy tác vụ mà bạn nghi ngờ đang rò rỉ, chụp nhanh Heap Snapshot mới và chọn comparisonchế độ xem ở phía dưới. Rõ ràng những vật thể được tạo ra giữa hai ảnh chụp nhanh.
Johnride

1
Đây có lẽ là giải pháp sạch nhất.
Luca Steeb

So sánh, được đề cập bởi @Johnride, hiện là một menu thả xuống ở trên cùng.
frandroid

Shallow sizedường như 40 cho cả hai { a:"55c2067aee27593c03b7acbe", b:"55c2067aee27593c03b7acbe", c:null, d:undefined }{ c:null, d:undefined }các đối tượng. Là nó ổn?
efkan

1
Bạn cũng có thể sử dụng Google Chrome Heap Profiler từ nút. Nếu bạn có nút v8 trở lên, hãy khởi động nó bằng node --inspectvà trong Chrome, hãy nhập about:inspectvào thanh URL và tìm cách mở trình kiểm tra nút. Tạo đối tượng của bạn trong nút CLI và sau đó chụp ảnh nhanh.
Gregor

74

Tôi chỉ viết điều này để giải quyết một vấn đề tương tự (ish). Nó không chính xác làm những gì bạn có thể đang tìm kiếm, tức là nó không tính đến cách trình thông dịch lưu trữ đối tượng.

Nhưng, nếu bạn đang sử dụng động cơ V8, nó sẽ cung cấp cho bạn một xấp xỉ khá ok vì các nguyên mẫu tuyệt vời và các lớp ẩn chiếm hầu hết các chi phí.

function roughSizeOfObject( object ) {

    var objectList = [];

    var recurse = function( value )
    {
        var bytes = 0;

        if ( typeof value === 'boolean' ) {
            bytes = 4;
        }
        else if ( typeof value === 'string' ) {
            bytes = value.length * 2;
        }
        else if ( typeof value === 'number' ) {
            bytes = 8;
        }
        else if
        (
            typeof value === 'object'
            && objectList.indexOf( value ) === -1
        )
        {
            objectList[ objectList.length ] = value;

            for( i in value ) {
                bytes+= 8; // an assumed existence overhead
                bytes+= recurse( value[i] )
            }
        }

        return bytes;
    }

    return recurse( object );
}

1
@Liangliang Zheng - vòng lặp vô hạn điểm tuyệt vời, cảm ơn. Hy vọng bạn không phiền nếu tôi biểu diễn lại một chút và cập nhật thông tin của mình sau khi làm việc (?)
thomas-peter

Tôi sẽ kiểm tra băng ghế tối nay với node.js và nhận được một số hệ số tốt hơn.
thomas-peter

Dòng 'byte + = recurse (value [i])', đưa ra lỗi trong FF 14.01: NS_ERROR_FAILURE: Thành phần trả về mã lỗi: 0x80004005 (NS_ERROR_FAILURE) [nsIDOMHTMLInputEuity.selectionStart]. Trên một trong các Đối tượng của tôi, nếu tôi thử một đối tượng khác, thì đó không phải là lỗi trình duyệt hoặc mã không hoạt động đối với mọi đối tượng (đối tượng không hoạt động có chứa các chức năng, đối tượng không hoạt động ' t)
TrySpace

1
Từ Tom này sang Tom khác, điều này trở nên siêu hữu ích như một chỉ báo sơ bộ về nơi tôi cần để cắt vòng eo đối tượng của mình. Vì vậy, sai lầm của bạn đã tìm hiểu về mối quan hệ của bạn với Javascript? Cô ấy là một tình nhân bảo trì cao.
Hội trường Tom W

4
Đó là PHP (gulp) mà tôi phải tìm kiếm - Tôi đã ngừng yêu cô ấy từ lâu nhưng cô ấy đã trả các hóa đơn. Dù sao, cảm ơn Tom, phản hồi như thế là tốt hơn so với điểm danh tiếng.
thomas-peter

55

Đôi khi tôi sử dụng điều này để gắn cờ các đối tượng thực sự lớn có thể sẽ đến máy khách từ máy chủ. Nó không đại diện cho dấu chân trong bộ nhớ. Nó chỉ giúp bạn có được khoảng bao nhiêu chi phí để gửi nó, hoặc lưu trữ nó.

Cũng lưu ý, nó chậm, chỉ dev. Nhưng để có được câu trả lời trên sân bóng với một dòng mã, nó rất hữu ích cho tôi.

roughObjSize = JSON.stringify(bigObject).length;

2
Từ các thử nghiệm của tôi, phương thức này nhanh hơn đáng kể so với trường hợp kích thước đối tượng vì nó không có lệnh gọi _.isObject () chậm từ lodash. Ngoài ra, các kích thước được trả về là khá tương đương cho các ước tính sơ bộ. Gist gist.github.com/owenallenaz/ff77fc98081708146495 .
Hạt nhân


5
Không thể sử dụng với các cấu trúc vòng tròn VM1409:1 Uncaught TypeError: Converting circular structure to JSON:( vẫn hữu ích mặc dù
givanse

đây không phải là kích thước nhị phân tính bằng byte nhưng sử dụng đơn giản để có kích thước gần đúng
datdinhquoc

Điều này khá tuyệt nếu 1) bạn chỉ cần ước tính ballpark 2) bạn biết bạn không có bất kỳ tài liệu tham khảo vòng tròn nào 3) bạn có thể bỏ qua các giá trị lớn và làm rối chúng một cách riêng biệt. Tất cả những điều này đều đúng trong trường hợp của tôi vì vậy hoạt động hoàn hảo, tôi chỉ có một chuỗi lớn ở một nơi mà tôi chỉ có thể đo chiều dài.
OZZIE

44

Đây là một giải pháp nhỏ gọn hơn cho vấn đề:

const typeSizes = {
  "undefined": () => 0,
  "boolean": () => 4,
  "number": () => 8,
  "string": item => 2 * item.length,
  "object": item => !item ? 0 : Object
    .keys(item)
    .reduce((total, key) => sizeOf(key) + sizeOf(item[key]) + total, 0)
};

const sizeOf = value => typeSizes[typeof value](value);

3
Vì vậy, đây là kích thước tính bằng KB? hay bit?
vincent thorpe

2
@ vincent-thorpe Nó tính bằng byte.
Dan

2
Kịch bản đẹp, cần sửa đổi cho các tài liệu tham khảo theo chu kỳ mặc dù.
Jim Pedid

1
Tôi vừa kiểm tra thuật toán của bạn trên một mảng dữ liệu khổng lồ trong một quy trình nút, nó báo cáo 13GB, nhưng nút đang tiêu thụ 22GB, bạn có ý tưởng nào về sự khác biệt đến từ đâu không? Không còn gì trong ký ức.
Josu Goñi

3
@ JosuGoñi, họ không tính toán chính đối tượng lấy bao nhiêu, chỉ có giá trị của nó. Tất cả các đối tượng chiếm nhiều không gian hơn chỉ là giá trị của chúng, nếu không typeof ...sẽ không hoạt động.
Alexis Wilke

42

Có một mô-đun NPM để lấy kích thước đối tượng , bạn có thể cài đặt nó vớinpm install object-sizeof

  var sizeof = require('object-sizeof');

  // 2B per character, 6 chars total => 12B
  console.log(sizeof({abc: 'def'}));

  // 8B for Number => 8B
  console.log(sizeof(12345));

  var param = { 
    'a': 1, 
    'b': 2, 
    'c': {
      'd': 4
    }
  };
  // 4 one two-bytes char strings and 3 eighth-bytes numbers => 32B
  console.log(sizeof(param));

sizeof (ngày mới ()) === 0 và sizeof ({}) === 0. Điều đó có được dự định không?
Philipp Claßen

1
@ PhilippClaßen Rõ ràng là như vậy. Cả hai đối tượng không có thuộc tính.
Robert

18

Đây là một phương pháp hacky, nhưng tôi đã thử nó hai lần với các số khác nhau và nó có vẻ phù hợp.

Những gì bạn có thể làm là thử và phân bổ một số lượng lớn các đối tượng, như một hoặc hai triệu đối tượng thuộc loại bạn muốn. Đặt các đối tượng trong một mảng để ngăn bộ thu gom rác phát hành chúng (lưu ý rằng điều này sẽ thêm một chút bộ nhớ vì mảng đó, nhưng tôi hy vọng điều này không quan trọng và bên cạnh đó nếu bạn lo lắng về các đối tượng nằm trong bộ nhớ , bạn lưu trữ chúng ở đâu đó). Thêm một cảnh báo trước và sau khi phân bổ và trong mỗi cảnh báo kiểm tra xem quá trình Firefox đang chiếm bao nhiêu bộ nhớ. Trước khi bạn mở trang bằng thử nghiệm, hãy đảm bảo bạn có một phiên bản Firefox mới. Mở trang, lưu ý sử dụng bộ nhớ sau khi cảnh báo "trước" được hiển thị. Đóng cảnh báo, chờ bộ nhớ được phân bổ. Trừ bộ nhớ mới từ bộ nhớ cũ và chia nó cho số lượng phân bổ.

function Marks()
{
  this.maxMarks = 100;
}

function Student()
{
  this.firstName = "firstName";
  this.lastName = "lastName";
  this.marks = new Marks();
}

var manyObjects = new Array();
alert('before');
for (var i=0; i<2000000; i++)
    manyObjects[i] = new Student();
alert('after');

Tôi đã thử điều này trong máy tính của mình và quá trình này có 48352K bộ nhớ khi cảnh báo "trước" được hiển thị. Sau khi phân bổ, Firefox có 440236K bộ nhớ. Đối với phân bổ 2 triệu, đây là khoảng 200 byte cho mỗi đối tượng.

Tôi đã thử lại lần nữa với phân bổ 1 triệu và kết quả tương tự: 196 byte cho mỗi đối tượng (tôi cho rằng dữ liệu bổ sung trong 2 mill đã được sử dụng cho Array).

Vì vậy, đây là một phương pháp hacky có thể giúp bạn. JavaScript không cung cấp phương thức "sizeof" vì một lý do: mỗi triển khai JavaScript là khác nhau. Ví dụ, trong Google Chrome, cùng một trang sử dụng khoảng 66 byte cho mỗi đối tượng (ít nhất là đánh giá từ trình quản lý tác vụ).


Này .. cảm ơn vì kỹ thuật. Tôi đã có được điều đó vì kế hoạch B không có cách nào trực tiếp để đo mức sử dụng bộ nhớ.

4
Mỗi triển khai C và C ++ cũng khác nhau. ;) Kích thước của kiểu dữ liệu trong C hoặc C ++ là cụ thể triển khai. Tôi thấy không có lý do gì JavaScript không thể hỗ trợ một toán tử như vậy, mặc dù nó không phục vụ cùng một mục đích hoặc có cùng ý nghĩa như trong C hoặc C ++ (là các ngôn ngữ cấp thấp hơn và đo kích thước thực tế của một cố định- loại dữ liệu kích thước tại thời gian biên dịch trái ngược với kích thước biến của đối tượng JavaScript động tại thời gian chạy).
bambams

12

Xin lỗi tôi không thể nhận xét, vì vậy tôi chỉ tiếp tục công việc từ tomwrong. Phiên bản nâng cao này sẽ không đếm đối tượng nhiều hơn một lần, do đó không có vòng lặp vô hạn. Thêm vào đó, tôi cho rằng khóa của một đối tượng cũng nên được tính, đại khái.

function roughSizeOfObject( value, level ) {
    if(level == undefined) level = 0;
    var bytes = 0;

    if ( typeof value === 'boolean' ) {
        bytes = 4;
    }
    else if ( typeof value === 'string' ) {
        bytes = value.length * 2;
    }
    else if ( typeof value === 'number' ) {
        bytes = 8;
    }
    else if ( typeof value === 'object' ) {
        if(value['__visited__']) return 0;
        value['__visited__'] = 1;
        for( i in value ) {
            bytes += i.length * 2;
            bytes+= 8; // an assumed existence overhead
            bytes+= roughSizeOfObject( value[i], 1 )
        }
    }

    if(level == 0){
        clear__visited__(value);
    }
    return bytes;
}

function clear__visited__(value){
    if(typeof value == 'object'){
        delete value['__visited__'];
        for(var i in value){
            clear__visited__(value[i]);
        }
    }
}

roughSizeOfObject(a);

Tôi nghĩ rằng điều này chính xác hơn vì nó là các phím đếm, mặc dù nó đếm phím '__visited__'
Sam Hasler

Kiểm tra typeof value === 'object'là không đủ và bạn sẽ có ngoại lệ nếu giá trị là null.
floribon

Điều này thật tuyệt vời cho đối tượng của tôi (mà tôi khá tự tin có cách trên 5mb), so với bất kỳ câu trả lời bị lừa nào của @ tomwrong. Nó cũng chính xác hơn (như đã nói 3mb hoặc hơn) nhưng vẫn còn quá xa thực tế. Bất kỳ manh mối về những gì nó có thể không được tính?
cregox

Không làm việc cho tôi. Đối tượng levelchứa dữ liệu nhưng roughSizeOfObject(level)trả về không. (Tất nhiên, mức độ biến của tôi không bị nhầm lẫn với đối số của bạn. Tôi không nghĩ rằng bóng đổ biến sẽ gây ra vấn đề ở đây và cả khi tôi đổi tên 'cấp độ' trong tập lệnh của mình, tôi cũng nhận được kết quả tương tự.) : snipboard.io/G7E5yj.jpg
Luc

10

Có cùng một vấn đề. Tôi đã tìm kiếm trên Google và tôi muốn chia sẻ với cộng đồng stackoverflow giải pháp này.

Quan trọng :

Tôi đã sử dụng chức năng được chia sẻ bởi Yan Qing trên github https://gist.github.com/undredh/4975495

function memorySizeOf(obj) {
    var bytes = 0;

    function sizeOf(obj) {
        if(obj !== null && obj !== undefined) {
            switch(typeof obj) {
            case 'number':
                bytes += 8;
                break;
            case 'string':
                bytes += obj.length * 2;
                break;
            case 'boolean':
                bytes += 4;
                break;
            case 'object':
                var objClass = Object.prototype.toString.call(obj).slice(8, -1);
                if(objClass === 'Object' || objClass === 'Array') {
                    for(var key in obj) {
                        if(!obj.hasOwnProperty(key)) continue;
                        sizeOf(obj[key]);
                    }
                } else bytes += obj.toString().length * 2;
                break;
            }
        }
        return bytes;
    };

    function formatByteSize(bytes) {
        if(bytes < 1024) return bytes + " bytes";
        else if(bytes < 1048576) return(bytes / 1024).toFixed(3) + " KiB";
        else if(bytes < 1073741824) return(bytes / 1048576).toFixed(3) + " MiB";
        else return(bytes / 1073741824).toFixed(3) + " GiB";
    };

    return formatByteSize(sizeOf(obj));
};


var sizeOfStudentObject = memorySizeOf({Student: {firstName: 'firstName', lastName: 'lastName', marks: 10}});
console.log(sizeOfStudentObject);

Bạn nghĩ gì về nó?


3
Điều này bỏ lỡ các chức năng. Nếu tôi thêm một chức năng, đối tượng sẽ không hiển thị lớn hơn nữa
Don Rhummy

Không đếm khóa
ebg11

7

tôi muốn biết nếu những nỗ lực giảm trí nhớ của tôi thực sự giúp giảm trí nhớ

Theo dõi nhận xét này, đây là những gì bạn nên làm: Cố gắng tạo ra vấn đề về bộ nhớ - Viết mã tạo ra tất cả các đối tượng này và tăng giới hạn trên cho đến khi bạn gặp sự cố (Sự cố trình duyệt, Đóng băng trình duyệt hoặc Lỗi ngoài- lỗi bộ nhớ). Tốt nhất bạn nên lặp lại thử nghiệm này với các trình duyệt khác nhau và hệ điều hành khác nhau.

Bây giờ có hai tùy chọn: tùy chọn 1 - Bạn đã không thành công trong việc tạo ra vấn đề bộ nhớ. Do đó, bạn đang lo lắng không có gì. Bạn không có vấn đề về bộ nhớ và chương trình của bạn vẫn ổn.

tùy chọn 2- bạn đã có một vấn đề bộ nhớ. Bây giờ hãy tự hỏi liệu giới hạn mà sự cố xảy ra có hợp lý không (nói cách khác: có khả năng số lượng đối tượng này sẽ được tạo khi sử dụng mã thông thường của bạn không). Nếu câu trả lời là 'Không' thì bạn vẫn ổn. Nếu không, bây giờ bạn biết có bao nhiêu đối tượng mà mã của bạn có thể tạo. Làm lại thuật toán sao cho nó không vi phạm giới hạn này.


Từ điểm đứng bộ nhớ, tiện ích mở rộng của tôi thêm một số đối tượng cho mỗi trang / tab đang mở trong Firefox. "Số" tỷ lệ thuận với kích thước của trang. Giả sử rằng người dùng "quyền lực" có bất kỳ nơi nào mở từ 15 - 20 tab và nếu trang web có nhiều nội dung, trình duyệt sẽ trở nên chậm và không phản hồi sau một thời gian. Điều này xảy ra ngay cả khi tôi không cố gắng làm căng thẳng ứng dụng. Tôi có kế hoạch viết lại mã mà tôi nghĩ sẽ giảm rất nhiều việc tạo đối tượng. Tôi chỉ muốn chắc chắn rằng không. của các đối tượng giảm xuống một số thứ sao cho nó có giá trị

@Senthil: nhưng kích thước đối tượng không có nghĩa gì trừ khi bạn biết dung lượng bộ nhớ khả dụng. Vì dung lượng bộ nhớ có thể vẫn còn là một bí ẩn, nên việc nói về #objects cũng hữu ích như nói theo thuật ngữ #bytes
Itay Maman


5

Thư viện Javascript sizeof.jsnày làm điều tương tự. Bao gồm nó như thế này

<script type="text/javascript" src="sizeof.js"></script>

Hàm sizeof lấy một đối tượng làm tham số và trả về kích thước gần đúng của nó theo byte. Ví dụ:

// define an object
var object =
    {
      'boolean' : true,
      'number'  : 1,
      'string'  : 'a',
      'array'   : [1, 2, 3]
    };

// determine the size of the object
var size = sizeof(object);

Hàm sizeof có thể xử lý các đối tượng chứa nhiều tham chiếu đến các đối tượng khác và các tham chiếu đệ quy.

Ban đầu được xuất bản ở đây .


Điều này chậm hơn và dường như "kém chính xác" hơn so với @liangliang, trong trường hợp sử dụng của tôi.
cregox


2

Rất cám ơn tất cả mọi người đã làm việc về mã cho việc này!

Tôi chỉ muốn nói thêm rằng tôi đã tìm kiếm chính xác điều tương tự, nhưng trong trường hợp của tôi, đó là quản lý bộ đệm của các đối tượng được xử lý để tránh phải phân tích lại và xử lý các đối tượng từ các cuộc gọi ajax có thể hoặc không được lưu vào bộ nhớ cache bởi trình duyệt. Điều này đặc biệt hữu ích cho các đối tượng cần xử lý nhiều, thường là bất kỳ thứ gì không có định dạng JSON, nhưng sẽ rất tốn kém khi giữ những thứ này được lưu trong một dự án lớn hoặc một ứng dụng / tiện ích mở rộng còn tồn tại lâu thời gian.

Dù sao, tôi sử dụng nó cho một cái gì đó như:

var myCache = {
    cache: {},
    order: [],
    size: 0,
    maxSize: 2 * 1024 * 1024, // 2mb

    add: function(key, object) {
        // Otherwise add new object
        var size = this.getObjectSize(object);
        if (size > this.maxSize) return; // Can't store this object

        var total = this.size + size;

        // Check for existing entry, as replacing it will free up space
        if (typeof(this.cache[key]) !== 'undefined') {
            for (var i = 0; i < this.order.length; ++i) {
                var entry = this.order[i];
                if (entry.key === key) {
                    total -= entry.size;
                    this.order.splice(i, 1);
                    break;
                }
            }
        }

        while (total > this.maxSize) {
            var entry = this.order.shift();
            delete this.cache[entry.key];
            total -= entry.size;
        }

        this.cache[key] = object;
        this.order.push({ size: size, key: key });
        this.size = total;
    },

    get: function(key) {
        var value = this.cache[key];
        if (typeof(value) !== 'undefined') { // Return this key for longer
            for (var i = 0; i < this.order.length; ++i) {
                var entry = this.order[i];
                if (entry.key === key) {
                    this.order.splice(i, 1);
                    this.order.push(entry);
                    break;
                }
            }
        }
        return value;
    },

    getObjectSize: function(object) {
        // Code from above estimating functions
    },
};

Đó là một ví dụ đơn giản và có thể có một số lỗi, nhưng nó đưa ra ý tưởng, vì bạn có thể sử dụng nó để giữ các đối tượng tĩnh (nội dung sẽ không thay đổi) với một mức độ thông minh nào đó. Điều này có thể cắt giảm đáng kể bất kỳ yêu cầu xử lý đắt tiền nào mà đối tượng phải được sản xuất ngay từ đầu.


1
function sizeOf(parent_data, size)
{
    for (var prop in parent_data)
    {
        let value = parent_data[prop];

        if (typeof value === 'boolean')
        {
            size += 4;
        }
        else if (typeof value === 'string')
        {
            size += value.length * 2;
        }
        else if (typeof value === 'number')
        {
             size += 8;
        }
        else
        {      
            let oldSize = size;
            size += sizeOf(value, oldSize) - oldSize;
        }
    }

    return size;
}


function roughSizeOfObject(object)
{   
    let size = 0;
    for each (let prop in object)
    {    
        size += sizeOf(prop, 0);
    } // for..
    return size;
}

1

Tôi sử dụng tab Dòng thời gian của công cụ phát triển Chrome , khởi tạo số lượng đối tượng ngày càng lớn và có được ước tính tốt như thế. Bạn có thể sử dụng html như thế này bên dưới, dưới dạng soạn sẵn và sửa đổi nó để mô phỏng tốt hơn các đặc điểm của các đối tượng của bạn (số lượng và loại thuộc tính, v.v ...). Bạn có thể muốn nhấp vào biểu tượng bit rác ở cuối tab công cụ dev đó, trước và sau khi chạy.

<html>
<script>
var size = 1000*100
window.onload = function() {
  document.getElementById("quantifier").value = size
}

function scaffold()
{
  console.log("processing Scaffold...");
  a = new Array
}

function start()
{
  size = document.getElementById("quantifier").value
  console.log("Starting... quantifier is " + size);
  console.log("starting test")
  for (i=0; i<size; i++){
    a[i]={"some" : "thing"}
  }
  console.log("done...")
}

function tearDown()
{
  console.log("processing teardown");
  a.length=0
}

</script>
<body>
    <span style="color:green;">Quantifier:</span>
    <input id="quantifier" style="color:green;" type="text"></input>
    <button onclick="scaffold()">Scaffold</button>
    <button onclick="start()">Start</button>
    <button onclick="tearDown()">Clean</button>
    <br/>
</body>
</html>

Khởi tạo 2 triệu đối tượng chỉ một thuộc tính (như trong mã này ở trên) dẫn đến tính toán sơ bộ 50 byte cho mỗi đối tượng, trên Chromium của tôi, ngay bây giờ. Thay đổi mã để tạo một chuỗi ngẫu nhiên cho mỗi đối tượng sẽ thêm khoảng 30 byte cho mỗi đối tượng, v.v Hy vọng điều này sẽ giúp ích.



-3

Tôi tin rằng bạn đã quên bao gồm 'mảng'.

  typeOf : function(value) {
        var s = typeof value;
        if (s === 'object')
        {
            if (value)
            {
                if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length')) && typeof value.splice === 'function')
                {
                    s = 'array';
                }
            }
            else
            {
                s = 'null';
            }
        }
        return s;
    },

   estimateSizeOfObject: function(value, level)
    {
        if(undefined === level)
            level = 0;

        var bytes = 0;

        if ('boolean' === typeOf(value))
            bytes = 4;
        else if ('string' === typeOf(value))
            bytes = value.length * 2;
        else if ('number' === typeOf(value))
            bytes = 8;
        else if ('object' === typeOf(value) || 'array' === typeOf(value))
        {
            for(var i in value)
            {
                bytes += i.length * 2;
                bytes+= 8; // an assumed existence overhead
                bytes+= estimateSizeOfObject(value[i], 1)
            }
        }
        return bytes;
    },

   formatByteSize : function(bytes)
    {
        if (bytes < 1024)
            return bytes + " bytes";
        else
        {
            var floatNum = bytes/1024;
            return floatNum.toFixed(2) + " kb";
        }
    },

1
Trong JS, một mảng là một đối tượng. Có thể có một số tối ưu hóa trong việc triển khai, nhưng về mặt khái niệm và các đối tượng là như nhau.
Kris Walker

-8

Tôi biết điều này hoàn toàn không phải là cách đúng đắn để làm điều đó, nhưng nó đã giúp tôi một vài lần trong quá khứ để có được kích thước tệp đối tượng xấp xỉ:

Viết đối tượng / phản hồi của bạn vào bàn điều khiển hoặc một tab mới, sao chép kết quả vào một tệp notepad mới, lưu nó và kiểm tra kích thước tệp. Bản thân tệp notepad chỉ là một vài byte, vì vậy bạn sẽ có được kích thước tệp đối tượng khá chính xác.


4
Điều này là hoàn toàn sai. Ví dụ, hãy xem xét số 1/3 = 0.3333333333333333. Nó sẽ là 18 byte bằng cách sử dụng phương pháp của bạn.
korCZis

2
Tôi nói nó là gần đúng . Đôi khi bạn không quan tâm nếu đó là 1MB hoặc 1.00001 MB, bạn chỉ muốn biết ước tính, thì phương pháp này hoàn toàn tốt.
Jeffrey Roosendaal

Giải pháp
táo bạo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.