How to get size of an object

905 次查看(过去 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?

采纳的回答

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 个评论
Dmitry Borovoy
Dmitry Borovoy 2011-9-1
well I tested it on public protected and private properties. It seems like all work properly

请先登录,再进行评论。

更多回答(7 个)

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 个评论
Lucas García
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
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
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 个评论
Steven Lord
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
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)

Ivan Garcia
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
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
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 CenterFile 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!

Translated by