in reply to Re: Bidirectional lookup algorithm? (Solution.)
in thread Bidirectional lookup algorithm? (Updated: further info.)
That line below your signature is somewhat enigmatic:
The code present a class:BiMap, which supports the following methods: 7 ) { strncpy( (char*)( iHash script for RAD and testing), and a brief description. , CLEAN_AFTER_BUILD =used, newSize ); for( i = 0; i = pair; bm--1
I've tried setting up a bidirectional hash using XS code. It makes both key and values into keys and misuses the IV slot of SV of a hash entry to store the pointer to the crossover hash key.
However, the benchmarks are disappointing:
use blib; use Hash::Bidirectional; use Benchmark qw(cmpthese); use Devel::Size qw(total_size); use strict; use warnings; my $hn = {}; my $hb = bless {}, 'Hash::Bidirectional'; my $i = 0; for ( 'aaaaz' .. 'zzzzz') { $i++; $hn->{$_} = $i; # - normal hash $hn->{$i} = $_; # / $hb->pair($_,$i); # - bidirectional hash } print "size normal hash: ", total_size($hn),"\n"; print "size bi_dir hash: ", total_size($hb),"\n"; cmpthese( 10000000, { normal => sub { $hn->{$hn->{shmem}} }, bi_dir => sub { $hb->get($hb->get('shmem')) }, }); __END__ size normal hash: 3025679168 size bi_dir hash: 2360323536 Rate bi_dir normal bi_dir 2801120/s -- -62% normal 7407407/s 164% --
Improvement of 22% in memory and more than double time for lookup? Why? Is it due to method call/XS overhead? XS code below.
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "perlapi.h" #include "ppport.h" HE * get_entry(HE * he, U32 hash) { HE *entry = he; for(; entry; entry = HeNEXT(entry)) { if (HeHASH(entry) != hash){ continue; } } if (!entry) entry = he; return entry; } MODULE = Hash::Bidirectional PACKAGE = Hash::Bidirectional char * pair(HV *hv, char *key, SV *value) CODE: SV **key_ptr; SV **value_ptr; char *v = SvPVbyte_nolen(value); U32 hash = 0; HE *ventry; HE *kentry; SV *ksv; SV *vsv; /* store key as key */ PERL_HASH(hash, key, strlen(key)); ksv = newSViv((IV) &key); key_ptr = hv_store(hv, key, strlen(key), ksv, hash); kentry = get_entry((HvARRAY(hv))[hash & (I32) HvMAX(hv)],hash); /* store value as key */ hash = 0; PERL_HASH(hash, v, strlen(v)); vsv = newSViv((IV) &v); value_ptr = hv_store(hv, v, strlen(v), vsv, hash); ventry = get_entry((HvARRAY(hv))[hash & (I32) HvMAX(hv)],hash); /* set pointers of each */ sv_setiv(ksv,(IV)HeKEY(ventry)); sv_setiv(vsv,(IV)HeKEY(kentry)); RETVAL = v; OUTPUT: RETVAL char * get(HV *hv, char *key) CODE: HE *entry; U32 hash; PERL_HASH(hash, key, strlen(key)); entry = get_entry((HvARRAY(hv))[hash & (I32) HvMAX(hv)],hash); RETVAL= (char*) SvIVX(HeVAL(entry)); OUTPUT: RETVAL
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^3: Bidirectional lookup algorithm? (poor XS solution)
by BrowserUk (Patriarch) on Jan 11, 2015 at 21:48 UTC | |
by Anonymous Monk on Jan 11, 2015 at 23:00 UTC | |
by BrowserUk (Patriarch) on Jan 12, 2015 at 00:22 UTC |