Is there a "signature" for objects instances of subclasses of handle?

1 次查看(过去 30 天)
Dear all,
obj1 = MyClass() ;
n = 1e6 ;
obj2 = obj1 ;
tic ; for k = 1 : n, isequal( obj2, obj1 ) ; end, toc
% -> Elapsed time is 2.107606 seconds.
obj3 = MyClass() ;
tic ; for k = 1 : n, isequal( obj3, obj1 ) ; end, toc
% -> Elapsed time is 68.857936 seconds.
If objects had an accessible signature (e.g. unique unint64) or any equivalent information/mechanism, even the first loop would not take more than a few milliseconds, hence my question.
Thanks,
Cedric
NOTES
  • I didn't find any equivalent information in objects' metaclass structs.
  • ...

回答(1 个)

Shruti Sapre
Shruti Sapre 2015-9-3
Hi Cedric,
I understand that you want to be able to compare two objects are equivalent (if they reference the same instance). I was unable to find a “signature” for the object, but it could be possible to implement this. Since “isequal” is slow for your class, you could maybe have a counter in your class that increments itself when an object is created, and compare the counter when determining if the two instances are the same. You could even have your own “isequal” function which does this.
classdef MyClass < handle
properties
counter
end
methods
function obj=MyClass(obj)
persistent c;
if isempty(c)
c=0;
else
c=c+1;
end
obj.counter=c;
end
function display(obj)
disp(obj.counter);
end
function res=isequal(obj1,obj2)
if obj1.counter==obj2.counter
res=true;
else
res=false;
end
end
end
end
I’m not sure if this would be faster, but it is an alternative approach.
Hope this helps!
-Shruti
  1 个评论
Cedric
Cedric 2015-9-3
编辑:Cedric 2015-9-3
Hi Shruti,
I though about a few alternatives (persistent instance counter, string ID, etc), and I ended up implementing a cascaded approach which uses first string IDs and ISEQUAL if string IDs don't allow differentiating two instances (which should not happen in my context). The reason is that I am not sure how the solution based on a persistent variable behaves in a PARFOR loop. I don't think that there is a lock or atomicity or anything that would prevent two instances from interfering between the moment c (in your example) is incremented and the moment its value is saved in the counter property (?)
I performed some basic tests that show my previous point. The "basic" version doesn't overload ISEQUAL (but is otherwise similar to the persistent version), the "persistent" version is yours, and the "string" version which is based on string comparison. Here is the result:
Basic - eq:2.40s, neq:15.00s
Persistent - eq:1.05s, neq:1.07s
String - eq:1.96s, neq:2.04s
where "eq" means "when two objects are the same instance" and "neq" is the opposite. This shows that ISEQUAL is slow when instances are different. I used the following code (also attached):
clear ; clc ;
bas1 = ClassBasic() ; bas2 = bas1 ; bas3 = ClassBasic() ;
per1 = ClassPersistent() ; per2 = per1 ; per3 = ClassPersistent() ;
str1 = ClassString( 'ID1' ) ; str2 = str1 ; str3 = ClassString( 'ID2' ) ;
n = 1e6 ;
% - Test basic ISEQUAL.
tic ;
for k = 1 : n
isequal( bas1, bas2 ) ;
end
t_bas_eq = toc ;
tic ;
for k = 1 : n
isequal( bas1, bas3 ) ;
end
t_bas_neq = toc ;
% - Test persistent ISEQUAL.
tic ;
for k = 1 : n
isequal( per1, per2 ) ;
end
t_per_eq = toc ;
tic ;
for k = 1 : n
isequal( per1, per3 ) ;
end
t_per_neq = toc ;
% - Test string ISEQUAL.
tic ;
for k = 1 : n
isequal( str1, str2 ) ;
end
t_str_eq = toc ;
tic ;
for k = 1 : n
isequal( str1, str3 ) ;
end
t_str_neq = toc ;
% - Verbose
fprintf( 'Basic - eq:%.2fs, neq:%.2fs\n', t_bas_eq, t_bas_neq ) ;
fprintf( 'Persistent - eq:%.2fs, neq:%.2fs\n', t_per_eq, t_per_neq ) ;
fprintf( 'String - eq:%.2fs, neq:%.2fs\n', t_str_eq, t_str_neq ) ;
And
classdef ClassBasic < handle
properties
instanceId
end
methods
function obj = ClassBasic()
persistent instanceCounter ;
if isempty( instanceCounter )
instanceCounter = 0 ;
else
instanceCounter = instanceCounter + 1 ;
end
obj.instanceId = instanceCounter ;
end
function display( obj )
disp( obj.instanceId ) ;
end
function tf = isequal__DISABLED( obj, obj2 )
if obj.instanceId == obj2.instanceId
tf = true ;
else
tf = false ;
end
end
end
end
classdef ClassPersistent < handle
properties
instanceId
end
methods
function obj = ClassPersistent()
persistent instanceCounter ;
if isempty( instanceCounter )
instanceCounter = 0 ;
else
instanceCounter = instanceCounter + 1 ;
end
obj.instanceId = instanceCounter ;
end
function display( obj )
disp( obj.instanceId ) ;
end
function tf = isequal( obj, obj2 )
if obj.instanceId == obj2.instanceId
tf = true ;
else
tf = false ;
end
end
end
end
classdef ClassString < handle
properties
stringId
end
methods
function obj = ClassString( stringId )
obj.stringId = stringId ;
end
function display( obj )
disp( obj.stringId ) ;
end
function tf = isequal( obj, obj2 )
tf = strcmp( obj.stringId, obj2.stringId ) ;
end
end
end

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Software Development Tools 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by