image thumbnail
from gcoll: a pedestrian garbage collector and workspace cleaner by us
garbage-collects workspace variables into a structure and optionally deletes those floating variable

sout=gcoll(varargin)
%     gcoll
%     gcoll  vpat1 -ws -opt1 vpat2 ... -opt2 ...
% s = gcoll;
% s = gcoll('vpat1 -ws -opt1 vpat2 ... -opt2 ...');
% s = gcoll('vpat1 ...','-ws -opt1 ...','vpat2 -opt2 ...','...');
%
% garbage-collects workspace variables into
% output-structure <s> of the form:
%	sout.varname1 = contents_of_var1
%	sout.varnameN = contents_of_varN
%
% vpat:	pattern to select var			[def: all]
%	see:	help whos
% -ws :	workspace id
%	-base					[def]
%	-caller
% -opt:	option flag (can be concatenated)
%   -k	keep    clear var EXCEPT those selected
%   -x	clear!  var in ws AFTER collection	[def: keep var]
%   -q	do NOT  display progress		[def: show processing]
%
% examples
% % use base variables
%	clear all;
%	a=rand([128 64 3]);
%	bb=1;
%	ccc='foo';
%	v=gcoll
% %	collect>   1:    a  C:double  B:196608  S:128x64x3
% %	collect>   2:   bb  C:double  B:     8  S:1x1
% %	collect>   3:  ccc  C:char    B:     6  S:1x3
% %	garbage collected --------------------------------
% %	nr items:  3
% %	nr bytes:  196622
% %	v =	a: [128x64x3 double]
% %		bb: 1
% %		ccc: 'foo'
%	v=gcoll('c* -x')
% %	collect.clear>   1:  ccc  C:char  B:6  S:1x3
% %	garbage collected --------------------------
% %	nr items:  1
% %	nr bytes:  6
% %	v =	ccc: 'foo'
% %--------------------------------------------------------------
% % call from within a function <foo.m>
% %	function foo(varargin)
% %		x=rand(1024);
% %		m=gcoll('-caller');
% % run-time
% %	foo(1,2,3)
% %	collect>   1:  varargin  C:cell    B:    204  S:1x3
% %	collect>   2:         x  C:double  B:8388608  S:1024x1024
% %	garbage collected ---------------------------------------
% %	nr items:  2
% %	nr bytes:  8388812
% %	m =	varargin: {[1]  [2]  [3]}
% %		x: [1024x1024 double]

% created:
%	us	12-Jan-2001
% modified:
%	us	01-Oct-2003 17:55:17	/ TMW

function	sout=gcoll(varargin)
% check input
		s=get_collector;
	if	nargout
		sout=s;
	end
% parse command line(s)
		[mod,ws,flg]=get_com(varargin{:});
% create a valid <whos> command
		com=get_mod(mod);
% evaluate
		v=evalin(ws,com);
% prepare collection and output
		nb=0;
		sl=12;
		vl=size(v,1);
	if	vl
% compute dynamic formatting
		vl=ceil(log10(vl+1))+2;
		c=struct2cell(v);
		nl=cellfun('length',c(1,:));
		nl=max(nl);
		cl=cellfun('length',c(4,:));
		cl=max(cl);
		bl=max([1 c{3,:}]);
		bl=ceil(log10(bl)+1)-1;
		fmt1=sprintf('%%%dd:  %%%d.%ds  C:%%-%d.%ds  B:%%%dd  S:%%s',...
			vl,nl,nl,cl,cl,bl);
% collect GARBAGE
	for	i=1:size(v,1);
		vn=v(i).name;
		nb=nb+v(i).bytes;
		ns=sprintf('%dx',v(i).size);
		var=evalin(ws,vn);
		com=sprintf('s.%s=var;',vn);
		eval(com);
		txt=sprintf(['collect> ' fmt1],...
			i,vn,v(i).class,v(i).bytes,ns(1:end-1));
	if	flg.k
		txt=strrep(txt,'collect>','collect.keep>');
	end
	if	flg.x
		txt=strrep(txt,'collect>','collect.clear>');
		evalin(ws,['clear ' vn]);
	end
	if	flg.q
		txt=[];
	end
		disp(txt);
		sl=max(sl,length(txt));
	end
	end
% recover vars to keep
	if	flg.k
		evalin(ws,'clear variables');
	if	~isempty(s)
		fn=fieldnames(s);
% first field is collector's ID!
	for	i=2:length(fn)
		assignin(ws,fn{i},s.(fn{i}));
	end
	end
	end

% ... and show results
	if	~flg.q
		str='garbage collected ';
		sl=max(12,sl-length(str));
		str=[str repmat('-',1,sl) '\n'];
		str=[str 'nr items:  %d\n'];
		str=[str 'nr bytes:  %d'];
		disp(sprintf(str,size(v,1),nb));
	end
	if	nargout
		sout=s;
	end
		return;
%--------------------------------------------------------------------------------
function	s=get_collector
% create an almost unique struct identifier
		r=rand('state');
		n=rand;
		rand('state',r);
		rand;
		c=fix(clock);
		fn=sprintf('%4.4d',c(1));
		fn=[fn sprintf('%2.2d',c(2:end))];
		fn=[fn sprintf('_%4.4d',fix(1000*n))];
		s.(['g_' fn])=['ID ' datestr(c)];
%--------------------------------------------------------------------------------
function	com=get_mod(mod)

		tmpl=',;/+-=';
% create args for <whos>
	if	isempty(mod)
		com='whos';
		return;
	else
		com='whos(';
	end
		ix=ismember(mod,tmpl);
		mod(ix)=' ';
		suff=mod;
	while	~isempty(suff)
		[var,suff]=strtok(suff);
		com=sprintf('%s''%s'',',com,var);
	end
		com(end)=')';
		return;
%--------------------------------------------------------------------------------
function	[mod,ws,flg]=get_com(varargin)

% options
		key={
%		option		alt proc		def proc
%---------------------------------------------------------------------
		'-base'		'ws=''base'';'		'ws=''base'';'
		'-caller'	'ws=''caller'';'	'ws=''base'';'
		'-file'		'flg.e=1;'		'flg.e=0;'
		'global'	'flg.e=2;'		';'
		'-k'		'flg.k=1;'		'flg.k=0;'
		'-q'		'flg.q=1;'		'flg.q=0;'
		'-x'		'flg.x=1;'		'flg.x=0;'
		};

% def parameters
		flg=[];
		mod='';
		com='';
% process command line argument(s)
	if	nargin
	for	i=1:nargin
	if	ischar(varargin{i})
		com=[com char(varargin{i}) ' '];
	end
	end
		com=strread(com,'%s');
	end
% recover ws/option flags
	for	i=1:size(key,1)
		eval(key{i,3});			% def proc mode
		ix=strmatch(key{i,1},com,'exact');
	if	~isempty(ix)
		com(ix,:)='';
		eval(key{i,2});			% alt proc mode
	end
	end

	switch	flg.e
	case	1
		error('gcoll cannot work on files');
	case	2
		error('gcoll cannot collect <globals>');
	end

		com=char(com);
	if	~isempty(com)
		com=[com repmat(' ',size(com,1),1)];
		com=reshape(com.',[],1).';
	end
		mod=deblank(com);
		return;
%--------------------------------------------------------------------------------

Contact us at files@mathworks.com