Beispiel #1
0
static VALUE avl_tree_rsize( VALUE self )
{
  avl_tree_r *t;
  long size;

  Data_Get_Struct( self, avl_tree_r, t );

  size = avl_tree_size( t->root );
  return INT2FIX( size );
}
Beispiel #2
0
int main(int argc, char **argv)
{
	struct option long_options[] = {
		// These options don't set a flag
		{"help",                      no_argument,       NULL, 'h'},
		{"duration",                  required_argument, NULL, 'd'},
		{"initial-size",              required_argument, NULL, 'i'},
		{"thread-num",                required_argument, NULL, 't'},
		{"range",                     required_argument, NULL, 'r'},
		{"seed",                      required_argument, NULL, 'S'},
		{"update-rate",               required_argument, NULL, 'u'},
		{"elasticity",                required_argument, NULL, 'x'},
		{NULL, 0, NULL, 0}
	};
	
	avl_intset_t *set;
	int i, j, c, size, tree_size;
	val_t last = 0; 
	val_t val = 0;
	unsigned long reads, effreads, updates, effupds, aborts, aborts_locked_read, aborts_locked_write,
	aborts_validate_read, aborts_validate_write, aborts_validate_commit,
	aborts_invalid_memory, aborts_double_write, max_retries, failures_because_contention;
	thread_data_t *data;
	maintenance_thread_data_t *maintenance_data;
	pthread_t *threads;
	pthread_t *maintenance_threads;
	pthread_attr_t attr;
	barrier_t barrier;
	struct timeval start, end;
	struct timespec timeout;
	int duration = DEFAULT_DURATION;
	int initial = DEFAULT_INITIAL;
	int nb_threads = DEFAULT_NB_THREADS;
	int nb_maintenance_threads = DEFAULT_NB_MAINTENANCE_THREADS;
	long range = DEFAULT_RANGE;
	int seed = DEFAULT_SEED;
	int update = DEFAULT_UPDATE;
	int unit_tx = DEFAULT_ELASTICITY;
	int alternate = DEFAULT_ALTERNATE;
	int effective = DEFAULT_EFFECTIVE;
	sigset_t block_set;
	
	while(1) {
		i = 0;
		c = getopt_long(argc, argv, "hAf:d:i:t:r:S:u:x:"
										, long_options, &i);
		
		if(c == -1)
			break;
		
		if(c == 0 && long_options[i].flag == 0)
			c = long_options[i].val;
		
		switch(c) {
				case 0:
					break;
				case 'h':
					printf("intset -- STM stress test "
								 "(avltree)\n"
								 "\n"
								 "Usage:\n"
								 "  intset [options...]\n"
								 "\n"
								 "Options:\n"
								 "  -h, --help\n"
								 "        Print this message\n"
								 "  -A, --Alternate\n"
								 "        Consecutive insert/remove target the same value\n"
								 "  -f, --effective <int>\n"
								 "        update txs must effectively write (0=trial, 1=effective, default=" XSTR(DEFAULT_EFFECTIVE) ")\n"
								 "  -d, --duration <int>\n"
								 "        Test duration in milliseconds (0=infinite, default=" XSTR(DEFAULT_DURATION) ")\n"
								 "  -i, --initial-size <int>\n"
								 "        Number of elements to insert before test (default=" XSTR(DEFAULT_INITIAL) ")\n"
								 "  -t, --thread-num <int>\n"
								 "        Number of threads (default=" XSTR(DEFAULT_NB_THREADS) ")\n"
								 "  -r, --range <int>\n"
								 "        Range of integer values inserted in set (default=" XSTR(DEFAULT_RANGE) ")\n"
								 "  -S, --seed <int>\n"
								 "        RNG seed (0=time-based, default=" XSTR(DEFAULT_SEED) ")\n"
								 "  -u, --update-rate <int>\n"
								 "        Percentage of update transactions (default=" XSTR(DEFAULT_UPDATE) ")\n"
								 "  -x, --elasticity (default=4)\n"
								 "        Use elastic transactions\n"
								 "        0 = non-protected,\n"
								 "        1 = normal transaction,\n"
								 "        2 = read elastic-tx,\n"
								 "        3 = read/add elastic-tx,\n"
								 "        4 = read/add/rem elastic-tx,\n"
								 "        5 = fraser lock-free\n"
								 );
					exit(0);
				case 'A':
					alternate = 1;
					break;
				case 'f':
					effective = atoi(optarg);
					break;
				case 'd':
					duration = atoi(optarg);
					break;
				case 'i':
					initial = atoi(optarg);
					break;
				case 't':
					nb_threads = atoi(optarg);
					break;
				case 'r':
					range = atol(optarg);
					break;
				case 'S':
					seed = atoi(optarg);
					break;
				case 'u':
					update = atoi(optarg);
					break;
				case 'x':
					unit_tx = atoi(optarg);
					break;
				case '?':
					printf("Use -h or --help for help\n");
					exit(0);
				default:
					exit(1);
		}
	}
	
	assert(duration >= 0);
	assert(initial >= 0);
	assert(nb_threads > 0);
	assert(range > 0 && range >= initial);
	assert(update >= 0 && update <= 100);
	
	printf("Set type     : avltree\n");
	printf("Duration     : %d\n", duration);
	printf("Initial size : %u\n", initial);
	printf("Nb threads   : %d\n", nb_threads);
	printf("Nb mt threads: %d\n", nb_maintenance_threads);
	printf("Value range  : %ld\n", range);
	printf("Seed         : %d\n", seed);
	printf("Update rate  : %d\n", update);
	printf("Elasticity   : %d\n", unit_tx);
	printf("Alternate    : %d\n", alternate);
	printf("Efffective   : %d\n", effective);
	printf("Type sizes   : int=%d/long=%d/ptr=%d/word=%d\n",
				 (int)sizeof(int),
				 (int)sizeof(long),
				 (int)sizeof(void *),
				 (int)sizeof(uintptr_t));
	
	timeout.tv_sec = duration / 1000;
	timeout.tv_nsec = (duration % 1000) * 1000000;
	
	if ((data = (thread_data_t *)malloc(nb_threads * sizeof(thread_data_t))) == NULL) {
		perror("malloc");
		exit(1);
	}
	if ((threads = (pthread_t *)malloc(nb_threads * sizeof(pthread_t))) == NULL) {
		perror("malloc");
		exit(1);
	}


	if ((maintenance_data = (maintenance_thread_data_t *)malloc(nb_maintenance_threads * sizeof(maintenance_thread_data_t))) == NULL) {
		perror("malloc");
		exit(1);
	}
	if ((maintenance_threads = (pthread_t *)malloc(nb_maintenance_threads * sizeof(pthread_t))) == NULL) {
		perror("malloc");
		exit(1);
	}


	
	if (seed == 0)
		srand((int)time(0));
	else
		srand(seed);
	
	//levelmax = floor_log_2((unsigned int) initial);

	//set = avl_set_new();
	set = avl_set_new_alloc(0, nb_threads);
	//set->stop = &stop;
	//#endif
	stop = 0;
	
	global_seed = rand();
#ifdef TLS
	rng_seed = &global_seed;
#else /* ! TLS */
	if (pthread_key_create(&rng_seed_key, NULL) != 0) {
		fprintf(stderr, "Error creating thread local\n");
		exit(1);
	}
	pthread_setspecific(rng_seed_key, &global_seed);
#endif /* ! TLS */
	
	// Init STM 
	printf("Initializing STM\n");
	
	TM_STARTUP();
	
	// Populate set 
	printf("Adding %d entries to set\n", initial);
	i = 0;
	
	while (i < initial) {
		val = rand_range_re(&global_seed, range);
		//printf("Adding %d\n", val);
		if (avl_add(set, val, 0, 0) > 0) {
		  //printf("Added %d\n", val);
		  //print_avltree(set);

			last = val;
			i++;
		}
	}
	size = avl_set_size(set);
	tree_size = avl_tree_size(set);
	printf("Set size     : %d\n", size);
	printf("Tree size     : %d\n", tree_size);
	//printf("Level max    : %d\n", levelmax);
	
	// Access set from all threads 
	barrier_init(&barrier, nb_threads + nb_maintenance_threads + 1);
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
	for (i = 0; i < nb_threads; i++) {
		printf("Creating thread %d\n", i);
		data[i].id = i;
		data[i].first = last;
		data[i].range = range;
		data[i].update = update;
		data[i].unit_tx = unit_tx;
		data[i].alternate = alternate;
		data[i].effective = effective;
		data[i].nb_modifications = 0;
		data[i].nb_add = 0;
		data[i].nb_added = 0;
		data[i].nb_remove = 0;
		data[i].nb_removed = 0;
		data[i].nb_contains = 0;
		data[i].nb_found = 0;
		data[i].nb_aborts = 0;
		data[i].nb_aborts_locked_read = 0;
		data[i].nb_aborts_locked_write = 0;
		data[i].nb_aborts_validate_read = 0;
		data[i].nb_aborts_validate_write = 0;
		data[i].nb_aborts_validate_commit = 0;
		data[i].nb_aborts_invalid_memory = 0;
		data[i].nb_aborts_double_write = 0;
		data[i].max_retries = 0;
		data[i].seed = rand();
		data[i].set = set;
		data[i].barrier = &barrier;
		data[i].failures_because_contention = 0;
		if (pthread_create(&threads[i], &attr, test, (void *)(&data[i])) != 0) {
			fprintf(stderr, "Error creating thread\n");
			exit(1);
		}
	}


	for (i = 0; i < nb_maintenance_threads; i++) {
	        maintenance_data[i].nb_maint = nb_maintenance_threads;
		maintenance_data[i].id = i;
		maintenance_data[i].nb_removed = 0;
		maintenance_data[i].nb_rotated = 0;
		maintenance_data[i].nb_suc_rotated = 0;
		maintenance_data[i].nb_propagated = 0;
		maintenance_data[i].nb_suc_propagated = 0;
		maintenance_data[i].nb_aborts = 0;
		maintenance_data[i].nb_aborts_locked_read = 0;
		maintenance_data[i].nb_aborts_locked_write = 0;
		maintenance_data[i].nb_aborts_validate_read = 0;
		maintenance_data[i].nb_aborts_validate_write = 0;
		maintenance_data[i].nb_aborts_validate_commit = 0;
		maintenance_data[i].nb_aborts_invalid_memory = 0;
		maintenance_data[i].nb_aborts_double_write = 0;
		maintenance_data[i].max_retries = 0;
		maintenance_data[i].t_data = data;
		maintenance_data[i].nb_threads = nb_threads;

		maintenance_data[i].set = set;
		maintenance_data[i].barrier = &barrier;

		if ((maintenance_data[i].t_nb_trans = (unsigned long *)malloc(nb_threads * sizeof(unsigned long))) == NULL) {
		  perror("malloc");
		  exit(1);
		}
		for(j = 0; j < nb_threads; j++) {
		  maintenance_data[i].t_nb_trans[j] = 0;
		}
		if ((maintenance_data[i].t_nb_trans_old = (unsigned long *)malloc(nb_threads * sizeof(unsigned long))) == NULL) {
		  perror("malloc");
		  exit(1);
		}
		for(j = 0; j < nb_threads; j++) {
		  maintenance_data[i].t_nb_trans_old[j] = 0;
		}

		printf("Creating maintenance thread %d\n", i);
		if (pthread_create(&maintenance_threads[i], &attr, test_maintenance, (void *)(&maintenance_data[i])) != 0) {
			fprintf(stderr, "Error creating thread\n");
			exit(1);
		}
	}

	pthread_attr_destroy(&attr);


	
	// Catch some signals 
	if (signal(SIGHUP, catcher) == SIG_ERR ||
			//signal(SIGINT, catcher) == SIG_ERR ||
			signal(SIGTERM, catcher) == SIG_ERR) {
		perror("signal");
		exit(1);
	}
	
	// Start threads 
	barrier_cross(&barrier);
	
	printf("STARTING...\n");
	gettimeofday(&start, NULL);
	if (duration > 0) {
		nanosleep(&timeout, NULL);
	} else {
		sigemptyset(&block_set);
		sigsuspend(&block_set);
	}
	
#ifdef ICC
	stop = 1;
#else	
	AO_store_full(&stop, 1);
#endif /* ICC */
	
	gettimeofday(&end, NULL);
	printf("STOPPING...\n");
	
	// Wait for thread completion 
	for (i = 0; i < nb_threads; i++) {
		if (pthread_join(threads[i], NULL) != 0) {
			fprintf(stderr, "Error waiting for thread completion\n");
			exit(1);
		}
	}


	// Wait for maintenance thread completion 
	for (i = 0; i < nb_maintenance_threads; i++) {
		if (pthread_join(maintenance_threads[i], NULL) != 0) {
			fprintf(stderr, "Error waiting for maintenance thread completion\n");
			exit(1);
		}
	}


	
	duration = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
	aborts = 0;
	aborts_locked_read = 0;
	aborts_locked_write = 0;
	aborts_validate_read = 0;
	aborts_validate_write = 0;
	aborts_validate_commit = 0;
	aborts_invalid_memory = 0;
	aborts_double_write = 0;
	failures_because_contention = 0;
	reads = 0;
	effreads = 0;
	updates = 0;
	effupds = 0;
	max_retries = 0;
	for (i = 0; i < nb_threads; i++) {
		printf("Thread %d\n", i);
		printf("  #add        : %lu\n", data[i].nb_add);
		printf("    #added    : %lu\n", data[i].nb_added);
		printf("  #remove     : %lu\n", data[i].nb_remove);
		printf("    #removed  : %lu\n", data[i].nb_removed);
		printf("  #contains   : %lu\n", data[i].nb_contains);
		printf("  #found      : %lu\n", data[i].nb_found);
		printf("  #aborts     : %lu\n", data[i].nb_aborts);
		printf("    #lock-r   : %lu\n", data[i].nb_aborts_locked_read);
		printf("    #lock-w   : %lu\n", data[i].nb_aborts_locked_write);
		printf("    #val-r    : %lu\n", data[i].nb_aborts_validate_read);
		printf("    #val-w    : %lu\n", data[i].nb_aborts_validate_write);
		printf("    #val-c    : %lu\n", data[i].nb_aborts_validate_commit);
		printf("    #inv-mem  : %lu\n", data[i].nb_aborts_invalid_memory);
		printf("    #dup-w    : %lu\n", data[i].nb_aborts_double_write);
		printf("    #failures : %lu\n", data[i].failures_because_contention);
		printf("  Max retries : %lu\n", data[i].max_retries);

		printf("  #set read trans reads: %lu\n", data[i].set_read_reads);
		printf("  #set write trans reads: %lu\n", data[i].set_write_reads);
		printf("  #set write trans writes: %lu\n", data[i].set_write_writes);
		printf("  #set trans reads: %lu\n", data[i].set_reads);
		printf("  #set trans writes: %lu\n", data[i].set_writes);
		printf("  set max reads: %lu\n", data[i].set_max_reads);
		printf("  set max writes: %lu\n", data[i].set_max_writes);

		printf("  #read trans reads: %lu\n", data[i].read_reads);
		printf("  #write trans reads: %lu\n", data[i].write_reads);
		printf("  #write trans writes: %lu\n", data[i].write_writes);
		printf("  #trans reads: %lu\n", data[i].reads);
		printf("  #trans writes: %lu\n", data[i].writes);
		printf("  max reads: %lu\n", data[i].max_reads);
		printf("  max writes: %lu\n", data[i].max_writes);
		aborts += data[i].nb_aborts;
		aborts_locked_read += data[i].nb_aborts_locked_read;
		aborts_locked_write += data[i].nb_aborts_locked_write;
		aborts_validate_read += data[i].nb_aborts_validate_read;
		aborts_validate_write += data[i].nb_aborts_validate_write;
		aborts_validate_commit += data[i].nb_aborts_validate_commit;
		aborts_invalid_memory += data[i].nb_aborts_invalid_memory;
		aborts_double_write += data[i].nb_aborts_double_write;
		failures_because_contention += data[i].failures_because_contention;
		reads += data[i].nb_contains;
		effreads += data[i].nb_contains + 
		(data[i].nb_add - data[i].nb_added) + 
		(data[i].nb_remove - data[i].nb_removed); 
		updates += (data[i].nb_add + data[i].nb_remove);
		effupds += data[i].nb_removed + data[i].nb_added; 
		size += data[i].nb_added - data[i].nb_removed;
		if (max_retries < data[i].max_retries)
			max_retries = data[i].max_retries;
	}


	for (i = 0; i < nb_maintenance_threads; i++) {
		printf("Maintenance thread %d\n", i);
		printf("  #removed %lu\n", set->nb_removed);
		printf("  #rotated %lu\n", set->nb_rotated);
		printf("  #rotated sucs %lu\n", set->nb_suc_rotated);
		printf("  #propogated %lu\n", set->nb_propogated);
		printf("  #propogated sucs %lu\n", set->nb_suc_propogated);
		printf("  #aborts     : %lu\n", maintenance_data[i].nb_aborts);
		printf("    #lock-r   : %lu\n", maintenance_data[i].nb_aborts_locked_read);
		printf("    #lock-w   : %lu\n", maintenance_data[i].nb_aborts_locked_write);
		printf("    #val-r    : %lu\n", maintenance_data[i].nb_aborts_validate_read);
		printf("    #val-w    : %lu\n", maintenance_data[i].nb_aborts_validate_write);
		printf("    #val-c    : %lu\n", maintenance_data[i].nb_aborts_validate_commit);
		printf("    #inv-mem  : %lu\n", maintenance_data[i].nb_aborts_invalid_memory);
		printf("    #dup-w    : %lu\n", maintenance_data[i].nb_aborts_double_write);
		//printf("    #failures : %lu\n", maintenance_data[i].failures_because_contention);
		printf("  Max retries : %lu\n", maintenance_data[i].max_retries);
	}


	printf("Set size      : %d (expected: %d)\n", avl_set_size(set), size);
	printf("Tree size      : %d\n", avl_tree_size(set));
	printf("Duration      : %d (ms)\n", duration);
	printf("#txs          : %lu (%f / s)\n", reads + updates, (reads + updates) * 1000.0 / duration);
	
	printf("#read txs     : ");
	if (effective) {
		printf("%lu (%f / s)\n", effreads, effreads * 1000.0 / duration);
		printf("  #contains   : %lu (%f / s)\n", reads, reads * 1000.0 / duration);
	} else printf("%lu (%f / s)\n", reads, reads * 1000.0 / duration);
	
	printf("#eff. upd rate: %f \n", 100.0 * effupds / (effupds + effreads));
	
	printf("#update txs   : ");
	if (effective) {
		printf("%lu (%f / s)\n", effupds, effupds * 1000.0 / duration);
		printf("  #upd trials : %lu (%f / s)\n", updates, updates * 1000.0 / 
					 duration);
	} else printf("%lu (%f / s)\n", updates, updates * 1000.0 / duration);
	
	printf("#aborts       : %lu (%f / s)\n", aborts, aborts * 1000.0 / duration);
	printf("  #lock-r     : %lu (%f / s)\n", aborts_locked_read, aborts_locked_read * 1000.0 / duration);
	printf("  #lock-w     : %lu (%f / s)\n", aborts_locked_write, aborts_locked_write * 1000.0 / duration);
	printf("  #val-r      : %lu (%f / s)\n", aborts_validate_read, aborts_validate_read * 1000.0 / duration);
	printf("  #val-w      : %lu (%f / s)\n", aborts_validate_write, aborts_validate_write * 1000.0 / duration);
	printf("  #val-c      : %lu (%f / s)\n", aborts_validate_commit, aborts_validate_commit * 1000.0 / duration);
	printf("  #inv-mem    : %lu (%f / s)\n", aborts_invalid_memory, aborts_invalid_memory * 1000.0 / duration);
	printf("  #dup-w      : %lu (%f / s)\n", aborts_double_write, aborts_double_write * 1000.0 / duration);
	printf("  #failures   : %lu\n",  failures_because_contention);
	printf("Max retries   : %lu\n", max_retries);
	

	//print_avltree(set);
	// Delete set 
        avl_set_delete(set);
	
	// Cleanup STM 
	TM_SHUTDOWN();
	
#ifndef TLS
	pthread_key_delete(rng_seed_key);
#endif /* ! TLS */
	
	free(threads);
	free(data);

	free(maintenance_threads);
	free(maintenance_data);
	
	return 0;
}