How to get size of an object
조회 수: 567 (최근 30일)
이전 댓글 표시
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?
댓글 수: 0
채택된 답변
추가 답변 (7개)
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
Lucas García
2011년 8월 31일
Also, if you are able to have the same elements of the object in one of the classic MATLAB data types, you will have a pretty good "estimate" of the amount of memory that your object takes:
>> warning off 'MATLAB:structOnObject'
>> s = builtin('struct', obj);
>> w = whos('s');
>> memObj = w.bytes
>> warning on 'MATLAB:structOnObject'
Andrew Janke
2019년 3월 5일
편집: per isakson
2019년 3월 11일
> 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
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
댓글 수: 0
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
댓글 수: 0
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
댓글 수: 0
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
Steven Lord
2020년 6월 10일
Asking the question "How much memory does this variable use?" may seem simple, but it's not.
A = ones(10000);
B = A;
How much actual memory does B use? Is it around 10000*10000*8 (8 bytes/element for real full double)? Maybe not.
A(1) = 2;
How much actual memory does B use now?
Why exactly do you need to know how much memory the object uses? What would you do with this information? I can think of a couple potential answers to those questions, but I'm curious what your specific use case is.
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
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)
댓글 수: 0
Ivan Garcia
2023년 1월 3일
편집: Ivan Garcia
2023년 1월 3일
A quick way of doing this is saving the var in a mat file. This is if you want a ballpark idea if the object is lightweight or not. This should not be used for a precise variable size measurement.
save('var1.mat', 'var1');
Then check the file size in the OS, e.g.,:
>> !ls -alg
total 2699
drwxr-xr-x 2 users 4 Jan 3 14:47 .
drwxr-xr-x 12 users 12 Jan 3 14:42 ..
-rw-r--r-- 1 users 1358542 Jan 3 13:29 var1.mat
댓글 수: 2
Andrew Janke
2023년 1월 3일
I'm not sure I'd recommend that. There's overhead in the MAT-file structure itself, or in some cases it may be using duplication/de-duplication or data compression, and some Matlab data structures (e.g. especially cellstrs and maybe strings) have significantly different MAT-file representations. The size of a MAT-file serialization of a Matlab value/array can vary a lot from its in-memory representation.
Ivan Garcia
2023년 1월 3일
At least for my case, I needed to know if an object was lightweight or not. And the above answered the question (I got 1 MB from the variable). I clarified that other approaches should be used for precise measurement. Thanks
참고 항목
카테고리
Help Center 및 File Exchange에서 Construct and Work with Object Arrays에 대해 자세히 알아보기
제품
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!