programing

JavaScript 개체의 크기를 가져오려면 어떻게 해야 합니까?

javaba 2022. 10. 26. 21:26
반응형

JavaScript 개체의 크기를 가져오려면 어떻게 해야 합니까?

JavaScript 객체가 차지하는 크기를 알고 싶습니다.

다음 기능을 수행합니다.

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

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

'I'm '를 인스턴스화합니다.student:

var stud = new Student();

그런 걸 할 수 있게

stud.firstName = "new Firstname";

alert(stud.firstName);

stud.marks.maxMarks = 200;

기타.

이제 ㅇㅇ, ㅇㅇ.stud오브젝트는 메모리에서 일정 크기를 차지합니다.여기에는 약간의 데이터와 더 많은 개체가 있습니다.

용량을 확인하려면 어떻게 요?stud체가가 점유 ?? ????랄까...sizeof()JavaScript? 한 알수 정말 것 요.sizeof(stud).

몇 달 동안 인터넷을 검색했는데 찾을 수가 없었어요. (몇 군데 포럼에서 물어봤지만 답변이 없었어요.)

나는 원래의 답변에 코드를 다시 반영했다.재귀와 추정된 존재 오버헤드를 제거했습니다.

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;
}

Google Chrome Hip Profiler를 사용하면 객체 메모리 사용을 검사할 수 있습니다.

추적에서 객체를 찾을 수 있어야 하는데, 이는 까다로울 수 있습니다.개체를 Window global에 고정하면 "Containment" 목록 모드에서 쉽게 찾을 수 있습니다.

첨부된 스크린샷에서 윈도우에 "testObj"라는 오브젝트를 만들었습니다.그런 다음 (녹음을 한 후) 프로파일러에 위치하면 객체의 전체 크기 및 객체의 모든 것이 "유지 크기"로 표시됩니다.

메모리 고장에 대한 자세한 정보

크롬 프로파일러

위 스크린샷에서 개체는 보존 크기 60을 표시합니다.여기서 단위는 바이트인 것 같습니다.

나는 단지 비슷한 문제를 해결하기 위해 이 글을 썼다.이것은 당신이 찾고 있는 것, 즉 인터프리터가 오브젝트를 저장하는 방법을 고려하지 않습니다.

그러나 V8을 사용하는 경우 멋진 프로토타이핑 및 숨겨진 클래스가 오버헤드의 대부분을 차지하므로 근사치를 얻을 수 있습니다.

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 );
}

서버에서 클라이언트로 전송될 가능성이 있는 매우 큰 오브젝트에 플래그를 붙이기 위해 이 플래그를 사용하는 경우가 있습니다.메모리 풋프린트를 나타내지 않습니다.보내거나 보관하는 데 드는 대략적인 비용만 얻을 수 있습니다.

또한 느린데, 개발 전용입니다.하지만 한 줄의 코드로 대략적인 답을 얻는 것은 나에게 도움이 되었다.

roughObjSize = JSON.stringify(bigObject).length;

다음은 이 문제에 대한 조금 더 간단한 해결 방법입니다.

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);

개체 크기를 가져오는 NPM 모듈이 있습니다. 이 모듈을 사용하여 설치할 수 있습니다.npm 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));

이것은 진부한 방법이지만, 다른 번호로 두 번 시도해보니 일관성이 있는 것 같습니다.

여러분이 할 수 있는 일은 여러분이 원하는 종류의 100만 개에서 200만 개 정도의 엄청난 수의 객체를 할당하는 것입니다.가비지 컬렉터가 개체를 해제하지 않도록 어레이에 개체를 배치합니다(배열로 인해 메모리 오버헤드가 약간 증가하지만 이 문제는 발생하지 않기를 바랍니다.게다가 개체가 메모리에 있는 것을 염려할 경우에는 개체를 어딘가에 저장합니다).할당 전후에 경고를 추가하고 각 경고에서 Firefox 프로세스가 사용하는 메모리 양을 확인합니다.테스트에서 페이지를 열기 전에 새로운 Firefox 인스턴스가 있는지 확인하십시오.페이지를 열고 "before" 경보가 표시된 후 메모리 사용량을 기록합니다.경고를 닫고 메모리가 할당될 때까지 기다립니다.오래된 메모리에서 새 메모리를 뺀 후 할당량으로 나눕니다.예를 들어:

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');

컴퓨터에서 시도해보니 "before" 경보가 표시되었을 때 프로세스 메모리가 48352K였습니다.할당 후 Firefox의 메모리는 440236K였습니다.200만 개의 할당에 대해서는, 이것은 각 오브젝트에 대해서 약 200 바이트입니다.

100만개의 할당으로 다시 시도해보니 오브젝트당 196바이트(어레이에 200만개의 추가 데이터가 사용되었을 것입니다)로 비슷합니다.

자, 여기 도움이 될 만한 해킹 방법이 있습니다.JavaScript는 "size of" 메서드를 제공하지 않습니다. 각 JavaScript 구현이 다르기 때문입니다.예를 들어 Google Chrome에서는 동일한 페이지가 각 개체에 대해 약 66바이트를 사용합니다(최소한 태스크 관리자에서 판단).

같은 문제를 안고 있다.구글에서 검색한 결과 stackoverflow 커뮤니티와 이 솔루션을 공유하고 싶습니다.

중요:

Github https://gist.github.com/zensh/4975495에서 Yan Ching이 공유한 기능을 사용했습니다.

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);

당신은 그것에 대해 어떻게 생각하세요?

코멘트를 하지 못해 죄송하고, 저는 그냥 tomwrong부터 일을 계속합니다.이 확장 버전에서는 개체를 두 번 이상 카운트하지 않으므로 무한 루프가 발생하지 않습니다.게다가, 나는 물건의 열쇠도 대략 세어야 한다고 생각한다.

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);

메모리 감소 노력이 실제로 메모리 감소에 도움이 되는지 알고 싶다.

이 코멘트를 팔로우 하면, 다음과 같이 할 필요가 있습니다.메모리 문제 발생 시도 - 이러한 모든 개체를 생성하고 문제(브라우저 크래시, 브라우저 프리즈 또는 메모리 부족 오류)가 발생할 때까지 상한을 크게 늘리는 코드를 작성합니다.이상적으로는 다른 브라우저와 다른 운영체제를 사용하여 이 실험을 반복해야 합니다.

이제 두 가지 옵션이 있습니다.옵션 1 - 메모리 문제를 생성하지 못했습니다.그래서 당신은 아무 걱정도 안 하고 있지 않습니다.메모리 문제도 없고 프로그램도 정상입니다.

옵션 2 - 메모리 문제가 발생하였습니다.이제 문제가 발생한 제한이 타당한지 자문해 보십시오(즉, 코드를 정상적으로 사용할 때 이 양의 개체가 생성될 가능성이 높습니다).만약 '아니오'라고 대답한다면 당신은 괜찮습니다.그렇지 않으면 코드가 생성할 수 있는 개체 수를 알 수 있습니다.이 제한을 위반하지 않도록 알고리즘을 변경합니다.

라이브러리 【Javascript】sizeof.js같은 일을 합니다. 넣으세요.

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

size of 함수는 객체를 매개 변수로 사용하여 대략적인 크기를 바이트 단위로 반환합니다.예를 들어 다음과 같습니다.

// 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);

함수의 크기는 다른 객체에 대한 여러 참조 및 재귀 참조를 포함하는 객체를 처리할 수 있습니다.

원래 여기에 출판되어 있습니다.

Firefox 확장의 메모리 사용량이 주된 관심사라면 Mozilla 개발자에게 확인해 볼 것을 권장합니다.

Mozilla는 Wiki에서 메모리 누수를 분석하는 도구 목록을 제공합니다.

크롬 현상 도구에는 이러한 기능이 있습니다.저는 이 기사가 매우 유용하다고 느꼈고, 당신이 원하는 대로 바로 할 수 있습니다: https://developers.google.com/chrome-developer-tools/docs/heap-profiling

코드 작업을 해 주신 모든 분들께 감사드립니다!

같은 것을 찾고 있다는 것을 덧붙이고 싶었을 뿐이지만, 제 경우 브라우저에 의해 캐시되었을 수도 있고 아닐 수도 있는 Ajax 호출에서 객체를 재파싱 및 처리할 필요가 없도록 처리되는 객체의 캐시를 관리하기 위한 것입니다.이것은 특히 많은 처리를 필요로 하는 오브젝트(보통 JSON 형식이 아닌 오브젝트)에 도움이 되지만, 이러한 오브젝트를 대규모 프로젝트나 장시간 실행 상태로 두는 어플리케이션/확장에 캐시하는 것은 비용이 많이 들 수 있습니다.

어쨌든, 저는 이것을 다음과 같은 용도로 사용합니다.

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
    },
};

이것은 단순한 예이며 오류가 있을 수 있지만, 어느 정도의 지능으로 정적 객체(콘텐츠는 변경되지 않음)를 유지하는 데 사용할 수 있기 때문에 아이디어를 얻을 수 있습니다.이를 통해 애초에 오브젝트를 생산해야 했던 모든 고가의 처리 요건을 대폭 줄일 수 있습니다.

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;
}

Chrome 개발 툴의 타임라인 탭을 사용하여 점점 더 많은 오브젝트를 인스턴스화하여 좋은 견적을 얻을 수 있습니다.다음과 같은 html을 보일러 플레이트로 사용하여 오브젝트의 특성(속성의 수 및 유형 등)을 보다 효과적으로 시뮬레이션할 수 있도록 수정할 수 있습니다.실행 전후에 해당 개발 도구 탭의 맨 아래에 있는 휴지통 비트 아이콘을 클릭할 수 있습니다.

<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>

(위의 코드와 같이) 각각 1개의 속성으로 이루어진 200만개의 오브젝트를 인스턴스화하면 현재 내 Chromium에서 오브젝트당 50바이트의 대략적인 계산이 이루어집니다.코드를 변경하여 오브젝트당 임의의 문자열을 생성하면 오브젝트당 약 30바이트가 추가됩니다.이게 도움이 됐으면 좋겠다.

오브젝트의 aprox. size를 프로그램적으로 체크할 필요가 있는 경우는 오브젝트 사이즈에 사용할 수 있었던 라이브러리 http://code.stephenmorley.org/javascript/finding-the-memory-usage-of-objects/도 체크할 수 있습니다.

그렇지 않으면 Chrome/Firefox 힙 프로파일러를 사용할 것을 권장합니다.

위 답변에 문제가 있었습니다.ArrayBuffer문서를 확인한 결과 ArrayBuffer에는byteLength필요한 것을 정확하게 알려주는 자산입니다.

function sizeOf(data)
{
    if (typeof(data) === 'object')
    {
        if (data instanceof ArrayBuffer)
        {
            return data.byteLength;
        }
        // other objects goes here
    }
    // non-object cases goes here
}

console.log(sizeOf(new ArrayBuffer(15))); // 15

레퍼런스:

승인된 답변은 와 함께 동작하지 않습니다.Set,WeakMap기타 반복할 수 있는 오브젝트.(다른 답변에서 설명한 object-sizeof 패키지에서도 같은 문제가 있습니다).

여기 내 해결책이 있습니다.

export function roughSizeOfObject(object) {
  const objectList = [];
  const stack = [object];
  const bytes = [0];
  while (stack.length) {
    const value = stack.pop();
    if (value == null) bytes[0] += 4;
    else if (typeof value === 'boolean') bytes[0] += 4;
    else if (typeof value === 'string') bytes[0] += value.length * 2;
    else if (typeof value === 'number') bytes[0] += 8;
    else if (typeof value === 'object' && objectList.indexOf(value) === -1) {
      objectList.push(value);
      if (typeof value.byteLength === 'number') bytes[0] += value.byteLength;
      else if (value[Symbol.iterator]) {
        // eslint-disable-next-line no-restricted-syntax
        for (const v of value) stack.push(v);
      } else {
        Object.keys(value).forEach(k => { 
           bytes[0] += k.length * 2; stack.push(value[k]);
        });
      }
    }
  }
  return bytes[0];
}

또, 키 스토리지와 동작하는 키 수 등, 그 외의 사소한 개선도 포함되어 있습니다.ArrayBuffer.

@Dan의 이미 컴팩트한 솔루션을 기반으로 자체 기능 버전을 소개합니다.콘텍스트를 희생하고 가능한 한 콤팩트하게 하고 싶은 사용자에게는 변수 이름이 한 글자로 축소됩니다.

const ns = {};
ns.sizeof = function(v) {
  let f = ns.sizeof, //this needs to match the name of the function itself, since arguments.callee.name is defunct
    o = {
      "undefined": () => 0,
      "boolean": () => 4,
      "number": () => 8,
      "string": i => 2 * i.length,
      "object": i => !i ? 0 : Object
        .keys(i)
        .reduce((t, k) => f(k) + f(i[k]) + t, 0)
    };
  return o[typeof v](v);
};

ns.undef;
ns.bool = true;
ns.num = 1;
ns.string = "Hello";
ns.obj = {
  first_name: 'John',
  last_name: 'Doe',
  born: new Date(1980, 1, 1),
  favorite_foods: ['Pizza', 'Salad', 'Indian', 'Sushi'],
  can_juggle: true
};

console.log(ns.sizeof(ns.undef));
console.log(ns.sizeof(ns.bool));
console.log(ns.sizeof(ns.num));
console.log(ns.sizeof(ns.string));
console.log(ns.sizeof(ns.obj));
console.log(ns.sizeof(ns.obj.favorite_foods));

크롬으로 헤드 스냅샷을 만들고 개체의 크기를 모니터링합니다.

여기에 이미지 설명 입력

나는 당신이 'array'를 넣는 것을 잊었다고 생각한다.

  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";
        }
    },

이것이 올바른 방법이 아니라는 것을 알지만, 과거에도 몇 번인가 오브젝트 파일 사이즈를 얻는 데 도움이 되었습니다.

오브젝트/응답 내용을 콘솔 또는 새 탭에 기록하고 결과를 새 메모장 파일에 복사하여 저장한 후 파일 크기를 확인합니다.메모장 파일 자체는 몇 바이트에 불과하기 때문에 꽤 정확한 객체 파일 크기를 얻을 수 있습니다.

언급URL : https://stackoverflow.com/questions/1248302/how-to-get-the-size-of-a-javascript-object

반응형