rbmatlab 0.10.01
|
00001 function [varargout] = filecache_function(funcptr, varargin) 00002 %function [varargout] = filecache_function(funcptr, varargin) 00003 % function used for file-caching other function calls. 00004 % 00005 % If an expensive function 00006 % 00007 % @code 00008 % [E, F] = myfunction(A,B,C) 00009 % @endcode 00010 % 00011 % is called frequently during a program run, a filecaching can be 00012 % used, i.e. one calls the function instead as 00013 % 00014 % @code 00015 % [E, F] = filecache_function(@myfunction,A,B,C); 00016 % @endcode 00017 % 00018 % If the function result exists in the cache, this is loaded, otherwise the 00019 % function is called, the result saved in the cache and the result returned. 00020 % 00021 % Parameters: 00022 % funcptr: is the pointer to a function whose calls are to be cached. 00023 % varargin: is parameter list of the cached function call 00024 % 00025 % Return values: 00026 % varargout: return values of the cached function call 00027 % 00028 % - The cache-directory is assumed to be in 'RBMATLABTEMP/cache' 00029 % - The cache-directory can be cleared with the function filecache_clear() 00030 00031 % Bernard Haasdonk 22.5.2007 00032 00033 if nargout==0 00034 error('filecaching only works for functions with return values!'); 00035 end; 00036 00037 funcname = func2str(funcptr); 00038 00039 % determining of a 'hash-code' from the function-arguments: 00040 tmpfn = fullfile(filecache_path,'tmparg.mat'); 00041 saveargs = varargin; 00042 for i=1:length(saveargs) 00043 if isobject(varargin{i}) 00044 warning('off', 'MATLAB:structOnObject'); 00045 saveargs{i} = struct(varargin{i}); 00046 warning('on', 'MATLAB:structOnObject'); 00047 end 00048 end 00049 00050 save(tmpfn,'saveargs'); 00051 fid = fopen(tmpfn,'r'); 00052 bin = fread(fid); 00053 % cut of header, which contains date, i.e. first 116 bytes 00054 bin = bin(117:end); 00055 fclose(fid); 00056 uintbin = uint32(bin); 00057 % simple arithmetics for identifying arguments 00058 key = mod(sum(uintbin.*uint32(1:length(uintbin))'),1e9); 00059 keystr = num2str(key); 00060 %keyboard; 00061 %key = sum() 00062 00063 resultfn = fullfile(filecache_path,... 00064 [funcname,keystr,'.mat']); 00065 multval_cache = fullfile(filecache_path,... 00066 [funcname,'mv.mat']); 00067 00068 is_cached = 0; 00069 hash_found = 0; 00070 funcstr = strtrim(evalc('disp(funcptr)')); 00071 00072 if exist(resultfn,'file'); 00073 loaded = load(resultfn); 00074 hash_found = 1; 00075 elseif exist(multval_cache,'file') 00076 tmp = load(multval_cache); 00077 tmp_key_pos = find(tmp.keylist==key,1); 00078 if ~isempty(tmp_key_pos) 00079 tmp_key_ind = tmp.map_key2ind(tmp_key_pos); 00080 tmp_file_ind = tmp.map_key2file(tmp_key_pos); 00081 storefile = fullfile(filecache_path,... 00082 [funcname,'mv',num2str(tmp_file_ind),'.mat']); 00083 if exist(storefile,'file') 00084 tmp = load(storefile); 00085 loaded = tmp.cache(tmp_key_ind); 00086 hash_found = 1; 00087 else 00088 error(['Could not find file ',storefile,... 00089 ', which is specified in multivalue cache list.']); 00090 end 00091 end 00092 end 00093 00094 if hash_found 00095 % isequal does not work for handles 00096 % if isequal(tmp.saveargs,saveargs) 00097 if isequal_ignore_handles(loaded.saveargs,saveargs) 00098 varargout = loaded.varargout; 00099 is_cached = 1; 00100 disp(['call of ',funcstr,', successfully read from cache, key=',keystr]); 00101 % keyboard; 00102 else 00103 % the key-computation formula must be updated in this case... 00104 disp(['arguments in cached file and current call do not',... 00105 'correspond!!']); 00106 disp('please change key-function in file_cache_function!'); 00107 disp('recomputation is started and cache-file replaced.'); 00108 %keyboard; 00109 end 00110 end 00111 00112 00113 if ~is_cached 00114 % call function 00115 disp('result not found in cache'); 00116 [varargout{1:nargout}] = funcptr(varargin{:}); 00117 % save(resultfn,'varargin'); 00118 00119 siz=whos('varargout'); 00120 % if size is less than 100kb, store in multi-value cache. 00121 if(siz.bytes < 1024*100) 00122 if exist(multval_cache,'file') 00123 meta=load(multval_cache); 00124 max_file_ind = meta.map_key2file(end); 00125 max_key_ind = meta.map_key2ind(end)+1; 00126 last_size = meta.last_size; 00127 % if store file size exceeds 10MB, create a new one 00128 if (last_size + siz.bytes > 1024*10000) 00129 max_file_ind = max_file_ind + 1; 00130 max_key_ind = 1; 00131 end 00132 else 00133 meta.keylist = []; 00134 meta.map_key2file = []; 00135 meta.map_key2ind = []; 00136 max_file_ind = 1; 00137 max_key_ind = 1; 00138 end 00139 storefile = fullfile(filecache_path,... 00140 [funcname,'mv',num2str(max_file_ind),'.mat']); 00141 if exist(storefile, 'file') 00142 load(storefile); 00143 end 00144 cache(max_key_ind).saveargs = saveargs; 00145 cache(max_key_ind).varargout = varargout; 00146 00147 tmp_size = whos('cache'); 00148 last_size = tmp_size.bytes; 00149 keylist = [meta.keylist, key]; 00150 map_key2file = [meta.map_key2file, max_file_ind]; 00151 map_key2ind = [meta.map_key2ind, max_key_ind]; 00152 00153 save(multval_cache, 'last_size', 'keylist', 'map_key2file', 'map_key2ind'); 00154 save(storefile, 'cache'); 00155 00156 else 00157 save(resultfn,'saveargs','varargout'); 00158 end 00159 disp(['call of ',funcstr,', now computed and cached, key=',keystr]); 00160 end 00161