Header imageAller au contenu principal

Hashtbl cache with LRU expiration

A skeleton of a cache based on Hashtbl with LRU expiration

type data_t = Real of float array | Cplx of Complex.t array
type cached_t = Room_t | Room_f | Smoothed | Wrapped | Unwrapped | GRD | Eq_minphase_t | Eq_minphase_f
    | Deconv1_t | Deconv1_f | Residue1_wrapped | Residue1_unwrapped | Residue1_GRD | Eq_allpass_t
    | Deconv2_t | Deconv2_f

let timestamp_t = float
let sweep_interval = 600.
let last_sweep = ref 0.

let src_serial = ref 0
let sid () = !src_serial
let sincr () = incr src_serial

let hcache = Hashtbl.create 16


let h_find (cache_id: cached_t) params =
    Hashtbl.find hcache (cache_id, sid (), params)

let h_expire kh =
    let h_make_expire_list h =
        (*  1. construct a hashtbl with cache_id as sole elt of the keys, value being a list
            of timestamps  *)
        let h_list = Hashtbl.create 16 in
        let build_len_list hlist k v =
            let cache_id, src_id, params = k in
            let ts, _ = v in
            let cid_list = try
                Hashtbl.find hlist cache_id
            with Not_found -> ( Hashtbl.add hlist cache_id []; [] ) in
            Hashtbl.replace hlist cache_id (ts :: cid_list)
        in
        Hashtbl.iter (build_len_list h_list) h ;
        (*  2. iter the h_list about lists lengths, thresholds  *)
        let h_list_over = Hashtbl.create 16 in
        let thresholds_len_list hlist k v =
            let thresh = 5 in
            let ts_list = List.sort Pervasives.compare v in
            let llen = List.length ts_list in 
            if  llen > thresh then (
                Hashtbl.add hlist k (BatList.take (llen-thresh) ts_list)
            )
        in
        Hashtbl.iter (thresholds_len_list h_list_over) h_list ;
        (*  should looks like cache_id as key, a timestamp (list) as value  *)
        h_list_over
    in
    let expire k v =
        let cache_id, src_id, params = k in
        let ts, data = v in
        let expire_h = h_make_expire_list kh in
        let exp_list = try Hashtbl.find expire_h cache_id with Not_found -> [] in
        try
            if (List.exists (fun x -> x = ts) exp_list) then (Hashtbl.remove kh k)
        with Not_found -> ()
    in Hashtbl.iter expire kh

let h_add cache_id params (data: data_t) =
    let ts = Unix.gettimeofday () in
    if ts > (!last_sweep +. sweep_interval) then (h_expire hcache ; last_sweep := ts) ;
    Hashtbl.add hcache (cache_id, sid (), params) (ts, data)


let () =

    h_add Room_t (25., 45., 14000., 20000.) (Real [|1.;2.;3.;4.;5.|]) ;
    let mydata = h_find Room_t (25., 45., 14000., 20000.) in ()