How to get size of an object

조회 수: 811(최근 30일)
Dmitry Borovoy
Dmitry Borovoy 2011년 8월 31일
답변: Matt Raum 2020년 12월 4일
There is function 'whos' that shows variables and their sizes, but for objects it shows just size of the pointer (about 112 bytes). How to get real size of the object?

채택된 답변

Dmitry Borovoy
Dmitry Borovoy 2011년 8월 31일
편집: Adam 2018년 12월 12일
Do you mean something like this:
function GetSize(this)
props = properties(this);
totSize = 0;
for ii=1:length(props)
currentProperty = getfield(this, char(props(ii)));
s = whos('currentProperty');
totSize = totSize + s.bytes;
end
fprintf(1, '%d bytes\n', totSize);
end
  댓글 수: 4
Lucas García
Lucas García 2011년 9월 1일
Nicely done!

댓글을 달려면 로그인하십시오.

추가 답변(6개)

Lucas García
Lucas García 2011년 8월 31일
Unfortunately, there is no way to check the amount of memory that is being occupied by class objects, since MATLAB is storing references to C++ objects. As you say, whos is representing the size of the pointer to the created object, which will be 60 bytes (in 32-bit) or 112 bytes (in 64-bit).
However, you can create a function in your class and calculate the real memory of the object by manually querying for the memory of each of the properties in the class, like you do with whos for a matrix.
  댓글 수: 2
Andrew Janke
Andrew Janke 2019년 3월 5일
> Unfortunately, there is no way to check the amount of memory that is being occupied by class objects, since MATLAB is storing references to C++ objects.
I'm confused by this: aren't Matlab user-defined objects (things defined with a classdef or an old-style @myclass directory) essentially structs with special behaviors? Their properties all contain Matlab arrays, just like struct fields, not C++ objects. (Except in Matlab's internals, but seems true for structs and cells as well, so I don't see why objects are special.) Why couldn't the default behavior of whos' size-counting be the equivalent of doing sizeof(builtin('struct', obj)) on objects?
This behavior seems to have changed as of some version before R2018b, too. When I create a classdef object, whos reports what looks to be the total size of the primitive Matlab arrays in its object graph, which is what I would expect if whos was now doing the equivalent of builtin('struct', obj) on objects.
classdef MyClass
properties
a
b
end
methods
function this = MyClass(a, b)
this.a = a;
this.b = b;
end
end
end
>> version
ans =
'9.5.0.944444 (R2018b)'
>> m = MyClass(zeros(1, 10^6), ones(1, 10^6));
>> whos
Name Size Bytes Class Attributes
ans 1x21 42 char
m 1x1 16000000 MyClass

댓글을 달려면 로그인하십시오.


Rick van Bijnen
Rick van Bijnen 2019년 5월 23일
편집: Rick van Bijnen 2019년 5월 23일
I extended the code of Dmitry and Mario, such that it now also treats nested objects properly, and it pretty-prints the result. You can also put a size treshold, to only show significantly large fields.
Example output:
>> getMemSize(GPS, 1024^2, 'GPS')
[GPS]
usedgridpoints : 3 Mb
phi : 24 Mb
Vtrapx : 24 Mb
Vtrapy : 24 Mb
Vtrapz : 24 Mb
FLaplacian : 24 Mb
FUdd : 24 Mb
FFTshift_rphase : 24 Mb
FFTshift_kphase : 24 Mb
[BdGbasis3Dsymm]
BasisStates : 8 Gb [!]
PhiBuffer : 24 Mb
L : 76 Mb
SourceIndices : 16 Mb
TargetIndices : 16 Mb
TOTAL : 9 Gb [!]
Code:
function [ bytes ] = getMemSize( variable, sizelimit, name, indent )
if nargin < 2
sizelimit = -1;
end
if nargin < 3
name = 'variable';
end
if nargin < 4
indent = '';
end
strsize = 30;
props = properties(variable);
if size(props, 1) < 1
bytes = whos(varname(variable));
bytes = bytes.bytes;
if bytes > sizelimit
if bytes < 1024
fprintf('%s%s: %i\n', indent, pad(name, strsize - length(indent)), bytes);
elseif bytes < 2^20
fprintf('%s%s: %i Kb\n', indent, pad(name, strsize - length(indent)), round(bytes / 2^10));
elseif bytes < 2^30
fprintf('%s%s: %i Mb\n', indent, pad(name, strsize - length(indent)), round(bytes / 2^20));
else
fprintf('%s%s: %i Gb [!]\n', indent, pad(name, strsize - length(indent)), round(bytes / 2^30));
end
end
else
fprintf('\n%s[%s] \n\n', indent, name);
bytes = 0;
for ii=1:length(props)
currentProperty = getfield(variable, char(props(ii)));
pp = props(ii);
bytes = bytes + getMemSize(currentProperty, sizelimit, pp{1}, [indent, ' ']);
end
if length(indent) == 0
fprintf('\n');
name = 'TOTAL';
if bytes < 1024
fprintf('%s%s: %i\n', indent, pad(name, strsize - length(indent)), bytes);
elseif bytes < 2^20
fprintf('%s%s: %i Kb\n', indent, pad(name, strsize - length(indent)), round(bytes / 2^10));
elseif bytes < 2^30
fprintf('%s%s: %i Mb\n', indent, pad(name, strsize - length(indent)), round(bytes / 2^20));
else
fprintf('%s%s: %i Gb [!]\n', indent, pad(name, strsize - length(indent)), round(bytes / 2^30));
end
end
end
end

Mario Reutter
Mario Reutter 2017년 12월 13일
편집: Mario Reutter 2017년 12월 13일
I extended the answer of @Dmitry Borovoy such that the function works with variables, structs, and objects:
function [ bytes ] = getSize( variable )
props = properties(variable);
if size(props, 1) < 1, bytes = whos(varname(variable)); bytes = bytes.bytes;
else %code of Dmitry
bytes = 0;
for ii=1:length(props)
currentProperty = getfield(variable, char(props(ii)));
s = whos(varname(currentProperty));
bytes = bytes + s.bytes;
end
end
end
We also need this helper function to achieve clean code. If you don't like it, you can just replace "varname(" and the following ")" with an apostrophe: ' .
function [ name ] = varname( ~ )
name = inputname(1);
end

Todd Fallesen
Todd Fallesen 2020년 2월 11일
size_var = getVarSize(variable)
function size_var = getVarSize(var)
name = getVarName(var);
size = whos(name);
size_var = size.bytes;
end
function out = getVarName(var)
out = inputname(1);
end

SK
SK 2020년 6월 10일
편집: SK 2020년 6월 10일
The problem with all the suggested solutions is that the matlab properties() function will not return the names of private properties. So while these suggested snippets of code will run to completion, the number they output at the end will not include the size of those private properties.
There appears to be no way to get the deep size of objects reliably other than converting the object recursively to a struct first (using struct()) and then using the code suggested by the posters above. Even if one used the meta class to get the private property names, getfield() will refuse to give the value of a private property and will throw an error.
One clunky solution would be to have a memsize function implemented inside every class. I don't see any other way. It's a mystery why Matlab doesn't provide such a function - something like memsize(classobj).
In addition, all the solutions above need to be modified to take into account (possibly nested) arrays of structs/objects and cell arrays.
  댓글 수: 2
Carsten Ridder
Carsten Ridder 2020년 10월 8일
"Why exactly do you need to know how much memory the object uses? What would you do with this information?"
In order to choose between two different solutions to the same coding problem, the memore requirements is one of the things to consider.
I have to choose one of these solutions - the data content is exactly identical:
1) an array of a userdefined class @measpoint (whos: 43416 bytes, SAVE to disk: 3.4 MB)
2) two MATLAB-tables (whos: 59359818 and 5949040 bytes, SAVE to disk: 873 KB and 196 KB)
Other things to consider is performance like speed and coding simplicity.
Any suggestions?

댓글을 달려면 로그인하십시오.


Matt Raum
Matt Raum 2020년 12월 4일
I run into this issue when trying to determine the memory footprint of objects derived from the handle base class.
I usually use the approach shown in the objbytes2() function, below. It calls getByteStreamFromArray(). I love that function.
It returns a larger size than objbytes1(). I think this is because it accounts for structural metadata and also for any hidden properties.
% Byte counting functions
varbytes = @(x)getfield(whos('x'),'bytes');
objbytes1 = @(x)sum(cellfun(@(p)varbytes(x.(p)),properties(x)));
objbytes2 = @(x)numel(getByteStreamFromArray(x));
% Sample application
x = figure;
varbytes(x)
objbytes1(x)
objbytes2(x)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by