Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r83779 - in trunk/tools/build/v2/engine: . modules
From: steven_at_[hidden]
Date: 2013-04-06 16:55:26


Author: steven_watanabe
Date: 2013-04-06 16:55:25 EDT (Sat, 06 Apr 2013)
New Revision: 83779
URL: http://svn.boost.org/trac/boost/changeset/83779

Log:
Reduce property-set memory usage.
Text files modified:
   trunk/tools/build/v2/engine/builtins.h | 2
   trunk/tools/build/v2/engine/jam.c | 1
   trunk/tools/build/v2/engine/modules/property-set.c | 212 +++++++++++++++++++++++++++------------
   3 files changed, 149 insertions(+), 66 deletions(-)

Modified: trunk/tools/build/v2/engine/builtins.h
==============================================================================
--- trunk/tools/build/v2/engine/builtins.h (original)
+++ trunk/tools/build/v2/engine/builtins.h 2013-04-06 16:55:25 EDT (Sat, 06 Apr 2013)
@@ -21,6 +21,8 @@
 void init_sequence();
 void init_order();
 
+void property_set_done();
+
 LIST *builtin_calc( FRAME * frame, int flags );
 LIST *builtin_depends( FRAME * frame, int flags );
 LIST *builtin_rebuilds( FRAME * frame, int flags );

Modified: trunk/tools/build/v2/engine/jam.c
==============================================================================
--- trunk/tools/build/v2/engine/jam.c (original)
+++ trunk/tools/build/v2/engine/jam.c 2013-04-06 16:55:25 EDT (Sat, 06 Apr 2013)
@@ -573,6 +573,7 @@
     clear_targets_to_update();
 
     /* Widely scattered cleanup. */
+ property_set_done();
     file_done();
     rules_done();
     timestamp_done();

Modified: trunk/tools/build/v2/engine/modules/property-set.c
==============================================================================
--- trunk/tools/build/v2/engine/modules/property-set.c (original)
+++ trunk/tools/build/v2/engine/modules/property-set.c 2013-04-06 16:55:25 EDT (Sat, 06 Apr 2013)
@@ -1,101 +1,181 @@
-/* Copyright Vladimir Prus 2003. Distributed under the Boost */
-/* Software License, Version 1.0. (See accompanying */
-/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+/*
+ * Copyright 2013 Steven Watanabe
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
 
-#include "../compile.h"
-#include "../lists.h"
-#include "../native.h"
 #include "../object.h"
-#include "../strings.h"
-#include "../timestamp.h"
+#include "../lists.h"
+#include "../modules.h"
+#include "../rules.h"
 #include "../variable.h"
+#include "../native.h"
+#include "../compile.h"
+#include "../mem.h"
 
-#include <string.h>
-
+struct ps_map_entry
+{
+ struct ps_map_entry * next;
+ LIST * key;
+ OBJECT * value;
+};
 
-LIST * get_grist( char const * const f )
+struct ps_map
 {
- char const * const end = strchr( f, '>' );
- string s[ 1 ];
- LIST * result;
+ struct ps_map_entry * * table;
+ size_t table_size;
+ size_t num_elems;
+};
 
- string_new( s );
+static unsigned list_hash(LIST * key)
+{
+ unsigned int hash = 0;
+ LISTITER iter = list_begin( key ), end = list_end( key );
+ for ( ; iter != end; ++iter )
+ {
+ hash = hash * 2147059363 + object_hash( list_item( iter ) );
+ }
+ return hash;
+}
 
- string_append_range( s, f, end + 1 );
- result = list_new( object_new( s->value ) );
+static int list_equal( LIST * lhs, LIST * rhs )
+{
+ LISTITER lhs_iter, lhs_end, rhs_iter;
+ if ( list_length( lhs ) != list_length( rhs ) )
+ {
+ return 0;
+ }
+ lhs_iter = list_begin( lhs );
+ lhs_end = list_end( lhs );
+ rhs_iter = list_begin( rhs );
+ for ( ; lhs_iter != lhs_end; ++lhs_iter, ++rhs_iter )
+ {
+ if ( ! object_equal( list_item( lhs_iter ), list_item( rhs_iter ) ) )
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
 
- string_free( s );
- return result;
+static void ps_map_init( struct ps_map * map )
+{
+ size_t i;
+ map->table_size = 2;
+ map->num_elems = 0;
+ map->table = BJAM_MALLOC( map->table_size * sizeof( struct ps_map_entry * ) );
+ for ( i = 0; i < map->table_size; ++i )
+ {
+ map->table[ i ] = NULL;
+ }
 }
 
+static void ps_map_destroy( struct ps_map * map )
+{
+ size_t i;
+ for ( i = 0; i < map->table_size; ++i )
+ {
+ struct ps_map_entry * pos;
+ for ( pos = map->table[ i ]; pos; )
+ {
+ struct ps_map_entry * tmp = pos->next;
+ BJAM_FREE( pos );
+ pos = tmp;
+ }
+ }
+ BJAM_FREE( map->table );
+}
 
-/*
-rule create ( raw-properties * )
+static void ps_map_rehash( struct ps_map * map )
 {
- raw-properties = [ sequence.unique
- [ sequence.insertion-sort $(raw-properties) ] ] ;
+ struct ps_map old = *map;
+ size_t i;
+ map->table = BJAM_MALLOC( map->table_size * 2 * sizeof( struct ps_map_entry * ) );
+ map->table_size *= 2;
+ for ( i = 0; i < map->table_size; ++i )
+ {
+ map->table[ i ] = NULL;
+ }
+ for ( i = 0; i < old.table_size; ++i )
+ {
+ struct ps_map_entry * pos;
+ for ( pos = old.table[ i ]; pos; )
+ {
+ struct ps_map_entry * tmp = pos->next;
+
+ unsigned hash_val = list_hash( pos->key );
+ unsigned bucket = hash_val % map->table_size;
+ pos->next = map->table[ bucket ];
+ map->table[ bucket ] = pos;
 
- local key = $(raw-properties:J=-:E=) ;
+ pos = tmp;
+ }
+ }
+ BJAM_FREE( old.table );
+}
 
- if ! $(.ps.$(key))
+static struct ps_map_entry * ps_map_insert(struct ps_map * map, LIST * key)
+{
+ unsigned hash_val = list_hash( key );
+ unsigned bucket = hash_val % map->table_size;
+ struct ps_map_entry * pos;
+ for ( pos = map->table[bucket]; pos ; pos = pos->next )
     {
- .ps.$(key) = [ new property-set $(raw-properties) ] ;
+ if ( list_equal( pos->key, key ) )
+ return pos;
     }
- return $(.ps.$(key)) ;
+
+ if ( map->num_elems >= map->table_size )
+ {
+ ps_map_rehash( map );
+ bucket = hash_val % map->table_size;
+ }
+ pos = BJAM_MALLOC( sizeof( struct ps_map_entry ) );
+ pos->next = map->table[bucket];
+ pos->key = key;
+ pos->value = 0;
+ map->table[bucket] = pos;
+ ++map->num_elems;
+ return pos;
 }
-*/
+
+static struct ps_map all_property_sets;
 
 LIST * property_set_create( FRAME * frame, int flags )
 {
     LIST * properties = lol_get( frame->args, 0 );
- LIST * sorted = L0;
- LIST * unique;
- LIST * val;
- string var[ 1 ];
- OBJECT * name;
- LISTITER iter;
- LISTITER end;
-
- sorted = list_sort( properties );
- unique = list_unique( sorted );
-
- string_new( var );
- string_append( var, ".ps." );
-
- iter = list_begin( unique );
- end = list_end( unique );
- for ( ; iter != end; iter = list_next( iter ) )
- {
- string_append( var, object_str( list_item( iter ) ) );
- string_push_back( var, '-' );
- }
- name = object_new( var->value );
- val = var_get( frame->module, name );
- if ( list_empty( val ) )
+ LIST * sorted = list_sort( properties );
+ LIST * unique = list_unique( sorted );
+ struct ps_map_entry * pos = ps_map_insert( &all_property_sets, unique );
+ list_free( sorted );
+ if ( pos->value )
+ {
+ list_free( unique );
+ return list_new( object_copy( pos->value ) );
+ }
+ else
     {
         OBJECT * const rulename = object_new( "new" );
- val = call_rule( rulename, frame, list_append( list_new( object_new(
+ LIST * val = call_rule( rulename, frame, list_append( list_new( object_new(
             "property-set" ) ), unique ), 0 );
         /* The 'unique' variable is freed in 'call_rule'. */
         object_free( rulename );
- var_set( frame->module, name, list_copy( val ), VAR_SET );
- }
- else
- {
- list_free( unique );
- val = list_copy( val );
+ pos->value = list_front( val );
+ pos->key = var_get( bindmodule( pos->value ), object_new( "self.raw" ) );
+ return val;
     }
- object_free( name );
- string_free( var );
- list_free( sorted );
-
- return val;
 }
 
 
 void init_property_set()
 {
     char const * args[] = { "raw-properties", "*", 0 };
- declare_native_rule( "property-set", "create", args, property_set_create, 1
- );
+ declare_native_rule( "property-set", "create", args, property_set_create, 1 );
+ ps_map_init( &all_property_sets );
+}
+
+void property_set_done()
+{
+ ps_map_destroy( &all_property_sets );
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk