/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ /******************************************************************************* S P O R T M O D E L _____ ____/_____\____ /__o____o____o__\ __ \_______________/ (@@)/ /\_____|_____/\ x~[]~ ~~~~~~~~~~~/~~~~~~~|~~~~~~~\~~~~~~~~/\~~~~~~~~~ Advanced Technology Garbage Collector Copyright (c) 1997 Netscape Communications, Inc. All rights reserved. Author: Warren Harris *******************************************************************************/ #include "plhash.h" #include "dynahash.h" #include "openhash.h" #include "prlog.h" #include #include #include #define ITERATIONS 10000 /******************************************************************************/ #define HASH_ALLOC 1 static PLHashNumber HashFunction(const void *key) { return (PLHashNumber)key; } static PRIntn HashKeyComparator(const void *v1, const void *v2) { return (int)v1 == (int)v2; } static PRIntn HashValueComparator(const void *v1, const void *v2) { #ifdef HASH_ALLOC return *(PRUword*)v1 == *(PRUword*)v2; #else return (PRUword)v1 == (PRUword)v2; #endif } /******************************************************************************/ static void HashTableAdd(PLHashTable* ht, PRUword i) { void* elem; void* value; #ifdef HASH_ALLOC value = malloc(sizeof(PRUword)); *(PRUword*)value = i; #else value = (void*)i; #endif elem = PL_HashTableAdd(ht, (const void*)i, value); PR_ASSERT(elem != NULL); } static void HashTableLookup(PLHashTable* ht, PRUword i) { void* value; PRUword v; value = PL_HashTableLookup(ht, (const void*)i); #ifdef HASH_ALLOC v = *(PRUword*)value; #else v = (PRUword)value; #endif PR_ASSERT(v == i); } static void HashTableDelete(PLHashTable* ht, PRUword i) { PRBool wasFound; #ifdef HASH_ALLOC PLHashEntry* entry = *PL_HashTableRawLookup(ht, i, (const void*)i); free(entry->value); #endif wasFound = PL_HashTableRemove(ht, (const void*)i); PR_ASSERT(wasFound); } static void TestHashTable(int initialSize) { PRUword i; clock_t t1, t2; PLHashTable* ht; ht = PL_NewHashTable(initialSize, HashFunction, HashKeyComparator, HashValueComparator, NULL, NULL); PR_ASSERT(ht); fprintf(stdout, "prhash\t%d", initialSize); t1 = clock(); for (i = 0; i < ITERATIONS; i++) { HashTableAdd(ht, i); } t2 = clock(); fprintf(stdout, "\t%ldms", (t2 - t1) * 1000 / CLOCKS_PER_SEC); t1 = clock(); for (i = 0; i < ITERATIONS; i++) { HashTableLookup(ht, i); } t2 = clock(); fprintf(stdout, "\t%ldms", (t2 - t1) * 1000 / CLOCKS_PER_SEC); t1 = clock(); for (i = 0; i < ITERATIONS; i++) { HashTableDelete(ht, i); } t2 = clock(); fprintf(stdout, "\t%ldms\n", (t2 - t1) * 1000 / CLOCKS_PER_SEC); PL_HashTableDestroy(ht); } /******************************************************************************/ typedef struct MyHashElement { PLDynahashElement hashElement; /* must be first */ PRUint32 key; PRUint32 value; } MyHashElement; static PRUint32 Dynahash_HashKey(void* context, MyHashElement* x) { #ifdef XP_MAC #pragma unused(context) #endif return x->key; } static PRBool Dynahash_Equals(void* context, MyHashElement* x, MyHashElement* y) { #ifdef XP_MAC #pragma unused(context) #endif return (PRBool)(x->key == y->key); } static void Dynahash_Destroy(void* context, MyHashElement* x) { #ifdef XP_MAC #pragma unused(context) #endif free(x); } /******************************************************************************/ static void DynahashAdd(PLDynahash* dh, PRUword i) { PRStatus status; MyHashElement* oldElem; MyHashElement* elem; elem = (MyHashElement*)malloc(sizeof(MyHashElement)); PR_ASSERT(elem != NULL); elem->hashElement.next = NULL; elem->key = i; elem->value = i; status = PL_DynahashAdd(dh, (PLDynahashElement*)elem, PR_FALSE, (PLDynahashElement**)&oldElem); PR_ASSERT(status == PR_SUCCESS); free(oldElem); } static void DynahashLookup(PLDynahash* dh, PRUword i) { MyHashElement elem; MyHashElement* found; PRBool wasFound; elem.hashElement.next = NULL; elem.key = i; found = (MyHashElement*)PL_DynahashLookup(dh, (PLDynahashElement*)&elem); PR_ASSERT(found); wasFound = (PRBool)(found->value == i); PR_ASSERT(wasFound); } static void DynahashDelete(PLDynahash* dh, PRUword i) { MyHashElement elem; MyHashElement* found; PRBool wasFound = PR_FALSE; elem.hashElement.next = NULL; elem.key = i; found = (MyHashElement*)PL_DynahashRemove(dh, (PLDynahashElement*)&elem); PR_ASSERT(found); wasFound = (PRBool)(found->value == i); PR_ASSERT(wasFound); free(found); } static void TestDynahash(int initialSize) { PRUword i; clock_t t1, t2; PLDynahash* dh; dh = PL_NewDynahash(initialSize, (PLHashFun)Dynahash_HashKey, (PLEqualFun)Dynahash_Equals, (PLDestroyFun)Dynahash_Destroy, NULL); PR_ASSERT(dh); fprintf(stdout, "dyna\t%d", initialSize); t1 = clock(); for (i = 0; i < ITERATIONS; i++) { DynahashAdd(dh, i); } t2 = clock(); fprintf(stdout, "\t%ldms", (t2 - t1) * 1000 / CLOCKS_PER_SEC); t1 = clock(); for (i = 0; i < ITERATIONS; i++) { DynahashLookup(dh, i); } t2 = clock(); fprintf(stdout, "\t%ldms", (t2 - t1) * 1000 / CLOCKS_PER_SEC); t1 = clock(); for (i = 0; i < ITERATIONS; i++) { DynahashDelete(dh, i); } t2 = clock(); fprintf(stdout, "\t%ldms\n", (t2 - t1) * 1000 / CLOCKS_PER_SEC); PL_DynahashDestroy(dh); } /******************************************************************************/ static void Openhash_Destroy(void* context, PLOpenhashElement* elem) { #ifdef XP_MAC #pragma unused(context) #endif #ifdef HASH_ALLOC free(elem->value); #endif } /******************************************************************************/ static void OpenhashAdd(PLOpenhash* dh, PRUword i) { #ifdef HASH_ALLOC void* elem = malloc(sizeof(PRUword)); PR_ASSERT(elem != NULL); *(PRUword*)elem = i; #else void* elem = (void*)i; #endif PL_OpenhashAdd(dh, i, elem); } static void OpenhashLookup(PLOpenhash* dh, PRUword i) { void* elem = PL_OpenhashLookup(dh, i); #ifdef HASH_ALLOC PR_ASSERT(elem); PR_ASSERT(*(PRUword*)elem == i); #else PR_ASSERT((PRUword)elem == i); #endif } static void TestOpenhash(int initialSize) { PRUword i; clock_t t1, t2; PLOpenhash* dh; dh = PL_NewOpenhash(initialSize, (PLOpenhashHashFun)NULL, (PLOpenhashEqualFun)NULL, (PLOpenhashDestroyFun)Openhash_Destroy, NULL); PR_ASSERT(dh); fprintf(stdout, "open\t%d", initialSize); t1 = clock(); for (i = 0; i < ITERATIONS; i++) { OpenhashAdd(dh, i); } t2 = clock(); fprintf(stdout, "\t%ldms", (t2 - t1) * 1000 / CLOCKS_PER_SEC); t1 = clock(); for (i = 0; i < ITERATIONS; i++) { OpenhashLookup(dh, i); } t2 = clock(); fprintf(stdout, "\t%ldms\n", (t2 - t1) * 1000 / CLOCKS_PER_SEC); PL_OpenhashDestroy(dh); } /******************************************************************************/ int main(void) { #if 0 PRBool success = PL_DynahashTest(); fprintf(stdout, "DynahashTest => %s\n", success ? "true" : "false"); #endif fprintf(stdout, "SportModel: Hash table comparison tests\n"); fprintf(stdout, "\tsize\tadd\tlookup\tremove\n"); TestHashTable(1024 * 8 - 8); TestHashTable(1024 - 8); TestHashTable(8); TestDynahash(1024 * 8 - 8); TestDynahash(1024 - 8); TestDynahash(8); TestOpenhash(1024 * 1024); TestOpenhash(1024 * 256); TestOpenhash(1024 * 128); return 0; } /******************************************************************************/