Move bench directory to https://github.com/P-p-H-d/c-stl-comparison
since it is better to have the comparison centralized in one place.
This commit is contained in:
1 parent
26cec1591a
commit
f7580e7ce9
50 files changed
-10481
No files matched your search
-512
@@ -1,512 +0,0 @@
|
|||||||
# Copyright (c) 2017-2024, Patrick Pelissier
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions are met:
|
|
||||||
# + Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# + Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
|
||||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
CC=cc -std=c11
|
|
||||||
CXX=c++ -std=c++11
|
|
||||||
CFLAGS=-O2 -march=native -Wall
|
|
||||||
XCFLAGS=
|
|
||||||
CPPFLAGS=-I..
|
|
||||||
N=4
|
|
||||||
BENCH_DEF=
|
|
||||||
RM=rm -rf
|
|
||||||
|
|
||||||
.PHONY: all pgo container queue mempool string plain bench-mlib bench-mlib-mempool bench-stl bench-qt bench-glib bench-klib bench-libdynamic bench-sparsepp bench-collectionc bench-tommyds bench-flathashmap bench-emilib bench-emhash bench-hopscotchmap bench-mlib-thread bench-liblfds bench-concurrentqueue bench-boost bench-mempool bench-string bench-plain bench-rigtorp-mpmc-queue bench-cmc
|
|
||||||
|
|
||||||
all: container queue mempool string plain
|
|
||||||
|
|
||||||
pgo:
|
|
||||||
$(MAKE) all XCFLAGS="-fprofile-generate=pgo"
|
|
||||||
$(MAKE) all XCFLAGS="-fprofile-use=pgo"
|
|
||||||
|
|
||||||
#########################################################################
|
|
||||||
|
|
||||||
container: bench-mlib bench-mlib-mempool bench-stl bench-qt bench-glib bench-klib bench-libdynamic bench-cmc bench-sparsepp bench-densehashmap bench-collectionc bench-tommyds bench-flathashmap bench-emilib bench-emhash bench-hopscotchmap bench-uthash bench-qlibc bench-libsrt bench-nedtries bench-rigtorp-hashmap bench-ctl bench-stc bench-pottery bench-CC
|
|
||||||
@echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
|
||||||
|
|
||||||
queue: bench-mlib-thread bench-liblfds bench-concurrentqueue bench-boost bench-rigtorp-mpmc-queue
|
|
||||||
@echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
|
||||||
|
|
||||||
mempool: bench-mempool
|
|
||||||
@echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
|
||||||
|
|
||||||
string: bench-string
|
|
||||||
@echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
|
||||||
|
|
||||||
plain: bench-plain
|
|
||||||
@echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#########################################################################
|
|
||||||
|
|
||||||
|
|
||||||
bench-mlib:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -pthread bench-mlib.c common.c -o bench-mlib.exe
|
|
||||||
@./bench-mlib.exe 10
|
|
||||||
@./bench-mlib.exe 11
|
|
||||||
@./bench-mlib.exe 20
|
|
||||||
@./bench-mlib.exe 30
|
|
||||||
@./bench-mlib.exe 31
|
|
||||||
@./bench-mlib.exe 40
|
|
||||||
@./bench-mlib.exe 41
|
|
||||||
@./bench-mlib.exe 42
|
|
||||||
@./bench-mlib.exe 46
|
|
||||||
@./bench-mlib.exe 47
|
|
||||||
@./bench-mlib.exe 43
|
|
||||||
@./bench-mlib.exe 50
|
|
||||||
@./bench-mlib.exe 51
|
|
||||||
|
|
||||||
bench-mlib-mempool:
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) bench-mlib.c common.c -DUSE_MEMPOOL -pthread -o bench-mlib-mempool.exe
|
|
||||||
@./bench-mlib-mempool.exe 10
|
|
||||||
@./bench-mlib-mempool.exe 11
|
|
||||||
@./bench-mlib-mempool.exe 20
|
|
||||||
@./bench-mlib-mempool.exe 30
|
|
||||||
@./bench-mlib-mempool.exe 31
|
|
||||||
@./bench-mlib-mempool.exe 40
|
|
||||||
@./bench-mlib-mempool.exe 41
|
|
||||||
@./bench-mlib-mempool.exe 42
|
|
||||||
@./bench-mlib-mempool.exe 46
|
|
||||||
@./bench-mlib-mempool.exe 47
|
|
||||||
@./bench-mlib-mempool.exe 43
|
|
||||||
@./bench-mlib-mempool.exe 50
|
|
||||||
@./bench-mlib-mempool.exe 51
|
|
||||||
|
|
||||||
bench-mlib-thread:
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) bench-mlib.c common.c -DMULTI_THREAD_MEASURE -pthread -o bench-mlib-thread.exe
|
|
||||||
@./bench-mlib-thread.exe 60
|
|
||||||
@./bench-mlib-thread.exe 61
|
|
||||||
@./bench-mlib-thread.exe 62
|
|
||||||
@./bench-mlib-thread.exe 63
|
|
||||||
@./bench-mlib-thread.exe 64
|
|
||||||
@./bench-mlib-thread.exe 65
|
|
||||||
@./bench-mlib-thread.exe 66
|
|
||||||
|
|
||||||
bench-stl:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) bench-stl.cpp common.c -o bench-stl.exe
|
|
||||||
@./bench-stl.exe 10
|
|
||||||
@./bench-stl.exe 20
|
|
||||||
@./bench-stl.exe 30
|
|
||||||
@./bench-stl.exe 40
|
|
||||||
@./bench-stl.exe 41
|
|
||||||
@./bench-stl.exe 42
|
|
||||||
@./bench-stl.exe 46
|
|
||||||
@./bench-stl.exe 43
|
|
||||||
@./bench-stl.exe 50
|
|
||||||
@./bench-stl.exe 51
|
|
||||||
|
|
||||||
# QT shall point to the the directory containing the file .pc are stored
|
|
||||||
bench-qt:
|
|
||||||
@if test -n "$${QT}" ; then $(MAKE) bench-qt0 ; else echo "Nothing to be done for QT." ; fi
|
|
||||||
bench-qt0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -fPIC bench-qt.cpp common.c -o bench-qt.exe `PKG_CONFIG_PATH="$${QT}" pkg-config --libs --cflags Qt5Core`
|
|
||||||
@./bench-qt.exe 10
|
|
||||||
@./bench-qt.exe 20
|
|
||||||
@./bench-qt.exe 30
|
|
||||||
@./bench-qt.exe 40
|
|
||||||
@./bench-qt.exe 41
|
|
||||||
@./bench-qt.exe 42
|
|
||||||
@./bench-qt.exe 50
|
|
||||||
|
|
||||||
# GLIB shall point to the the directory containing the file .pc are stored
|
|
||||||
bench-glib:
|
|
||||||
@if test -n "$${GLIB}" ; then $(MAKE) bench-glib0 ; else echo "Nothing to be done for GLIB." ; fi
|
|
||||||
bench-glib0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) bench-glib.c common.c -o bench-glib.exe `PKG_CONFIG_PATH="$${GLIB}" pkg-config --libs --cflags glib-2.0`
|
|
||||||
@./bench-glib.exe 10
|
|
||||||
@./bench-glib.exe 20
|
|
||||||
@./bench-glib.exe 30
|
|
||||||
@./bench-glib.exe 40
|
|
||||||
@./bench-glib.exe 41
|
|
||||||
@./bench-glib.exe 50
|
|
||||||
|
|
||||||
# KLIB shall point to the directory where the headers are
|
|
||||||
bench-klib:
|
|
||||||
@if test -n "$${KLIB}" ; then $(MAKE) bench-klib0 ; else echo "Nothing to be done for KLIB." ; fi
|
|
||||||
|
|
||||||
bench-klib0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I $${KLIB} bench-klib.c common.c -o bench-klib.exe
|
|
||||||
@./bench-klib.exe 10
|
|
||||||
@./bench-klib.exe 20
|
|
||||||
@./bench-klib.exe 30
|
|
||||||
@./bench-klib.exe 40
|
|
||||||
@./bench-klib.exe 41
|
|
||||||
@./bench-klib.exe 50
|
|
||||||
|
|
||||||
# CMC shall point to the directory where the CMC main header is
|
|
||||||
bench-cmc:
|
|
||||||
@if test -n "$${CMC}" ; then $(MAKE) bench-cmc0 ; else echo "Nothing to be done for CMC." ; fi
|
|
||||||
|
|
||||||
bench-cmc0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I $${CMC} bench-cmc.c common.c -o bench-cmc.exe
|
|
||||||
@./bench-cmc.exe 20
|
|
||||||
@./bench-cmc.exe 30
|
|
||||||
@./bench-cmc.exe 40
|
|
||||||
|
|
||||||
# LIBDYNAMIC shall point to the the source directory where the source is built
|
|
||||||
bench-libdynamic:
|
|
||||||
@if test -n "$${LIBDYNAMIC}" ; then $(MAKE) bench-libdynamic0 ; else echo "Nothing to be done for LIBDYNAMIC." ; fi
|
|
||||||
|
|
||||||
bench-libdynamic0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) bench-libdynamic.c common.c -o bench-libdynamic.exe -I$${LIBDYNAMIC}/src $${LIBDYNAMIC}/.libs/libdynamic.a
|
|
||||||
@./bench-libdynamic.exe 20
|
|
||||||
@./bench-libdynamic.exe 40
|
|
||||||
@./bench-libdynamic.exe 41
|
|
||||||
|
|
||||||
# SPARSEPP shall point to the directory where the headers are
|
|
||||||
bench-sparsepp:
|
|
||||||
@if test -n "$${SPARSEPP}" ; then $(MAKE) bench-sparsepp0 ; else echo "Nothing to be done for SPARSEPP." ; fi
|
|
||||||
|
|
||||||
bench-sparsepp0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${SPARSEPP}" -I "$${SPARSEPP}/.." bench-sparsepp.cpp common.c -o bench-sparsepp.exe
|
|
||||||
@./bench-sparsepp.exe 41
|
|
||||||
@./bench-sparsepp.exe 42
|
|
||||||
@./bench-sparsepp.exe 43
|
|
||||||
|
|
||||||
# DENSEHASHMAP shall point to the directory where the src are
|
|
||||||
bench-densehashmap:
|
|
||||||
@if test -n "$${DENSEHASHMAP}" ; then $(MAKE) bench-densehashmap0 ; else echo "Nothing to be done Google DENSEHASHMAP." ; fi
|
|
||||||
|
|
||||||
bench-densehashmap0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${DENSEHASHMAP}" -I "$${DENSEHASHMAP}/.." bench-densehashmap.cpp common.c -o bench-densehashmap.exe
|
|
||||||
@./bench-densehashmap.exe 41
|
|
||||||
@./bench-densehashmap.exe 42
|
|
||||||
@./bench-densehashmap.exe 43
|
|
||||||
|
|
||||||
# COLLECTIONC shall point to the directory where it is installed
|
|
||||||
bench-collectionc:
|
|
||||||
@if test -n "$${COLLECTIONC}" ; then $(MAKE) bench-collectionc0 ; else echo "Nothing to be done for COLLECTIONC." ; fi
|
|
||||||
|
|
||||||
bench-collectionc0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${COLLECTIONC}/include/collectc" bench-collectionc.c common.c "$${COLLECTIONC}/lib/libcollectc.a" -o bench-collectionc.exe
|
|
||||||
@./bench-collectionc.exe 10
|
|
||||||
@./bench-collectionc.exe 20
|
|
||||||
@./bench-collectionc.exe 30
|
|
||||||
@./bench-collectionc.exe 40
|
|
||||||
@./bench-collectionc.exe 41
|
|
||||||
@./bench-collectionc.exe 50
|
|
||||||
|
|
||||||
# TOMMYDS shall point to the source directory.
|
|
||||||
bench-tommyds:
|
|
||||||
@if test -n "$${TOMMYDS}" ; then $(MAKE) bench-tommyds0 ; else echo "Nothing to be done for TOMMYDS." ; fi
|
|
||||||
|
|
||||||
bench-tommyds0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${TOMMYDS}" bench-tommyds.c $${TOMMYDS}/tommyds/tommyarray.c $${TOMMYDS}/tommyds/tommylist.c $${TOMMYDS}/tommyds/tommytree.c $${TOMMYDS}/tommyds/tommyhashlin.c common.c -o bench-tommyds.exe
|
|
||||||
@./bench-tommyds.exe 10
|
|
||||||
@./bench-tommyds.exe 20
|
|
||||||
@./bench-tommyds.exe 30
|
|
||||||
@./bench-tommyds.exe 40
|
|
||||||
@./bench-tommyds.exe 41
|
|
||||||
|
|
||||||
# FLATHASHMAP shall point to the directory where the headers are
|
|
||||||
bench-flathashmap:
|
|
||||||
@if test -n "$${FLATHASHMAP}" ; then $(MAKE) bench-flathashmap0 ; else echo "Nothing to be done for FLATHASHMAP." ; fi
|
|
||||||
|
|
||||||
bench-flathashmap0:
|
|
||||||
$(CXX) -std=c++14 $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${FLATHASHMAP}" bench-flathashmap.cpp common.c -o bench-flathashmap.exe
|
|
||||||
@./bench-flathashmap.exe 41
|
|
||||||
@./bench-flathashmap.exe 42
|
|
||||||
@./bench-flathashmap.exe 46
|
|
||||||
@./bench-flathashmap.exe 43
|
|
||||||
|
|
||||||
# EMILIB shall point to the directory where the headers are
|
|
||||||
bench-emilib:
|
|
||||||
@if test -n "$${EMILIB}" ; then $(MAKE) bench-emilib0 ; else echo "Nothing to be done for EMILIB." ; fi
|
|
||||||
|
|
||||||
bench-emilib0:
|
|
||||||
$(CXX) -std=c++14 $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${EMILIB}" bench-emilib.cpp common.c -o bench-emilib.exe
|
|
||||||
@./bench-emilib.exe 41
|
|
||||||
@./bench-emilib.exe 42
|
|
||||||
@./bench-emilib.exe 46
|
|
||||||
@./bench-emilib.exe 43
|
|
||||||
|
|
||||||
# EMHASh shall point to the directory where the headers are
|
|
||||||
bench-emhash:
|
|
||||||
@if test -n "$${EMHASH}" ; then $(MAKE) bench-emhash0 ; else echo "Nothing to be done for EMHASH." ; fi
|
|
||||||
|
|
||||||
bench-emhash0:
|
|
||||||
$(CXX) -std=c++14 $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${EMHASH}" bench-emhash.cpp common.c -o bench-emhash.exe
|
|
||||||
@./bench-emhash.exe 41
|
|
||||||
@./bench-emhash.exe 42
|
|
||||||
@./bench-emhash.exe 46
|
|
||||||
@./bench-emhash.exe 43
|
|
||||||
|
|
||||||
# HOPSCOTCHMAP shall point to the directory where the source are
|
|
||||||
bench-hopscotchmap:
|
|
||||||
@if test -n "$${HOPSCOTCHMAP}" ; then $(MAKE) bench-hopscotchmap0 ; else echo "Nothing to be done for HOPSCOTCHMAP." ; fi
|
|
||||||
|
|
||||||
bench-hopscotchmap0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${HOPSCOTCHMAP}/include/tsl" bench-hopscotchmap.cpp common.c -o bench-hopscotchmap.exe
|
|
||||||
@./bench-hopscotchmap.exe 41
|
|
||||||
@./bench-hopscotchmap.exe 42
|
|
||||||
@./bench-hopscotchmap.exe 43
|
|
||||||
|
|
||||||
# UTHASH shall point to the directory where the source are
|
|
||||||
bench-uthash:
|
|
||||||
@if test -n "$${UTHASH}" ; then $(MAKE) bench-uthash0 ; else echo "Nothing to be done for UTHASH." ; fi
|
|
||||||
|
|
||||||
bench-uthash0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${UTHASH}" bench-uthash.c common.c -o bench-uthash.exe
|
|
||||||
@./bench-uthash.exe 10
|
|
||||||
@./bench-uthash.exe 20
|
|
||||||
@./bench-uthash.exe 40
|
|
||||||
@./bench-uthash.exe 41
|
|
||||||
@./bench-uthash.exe 50
|
|
||||||
|
|
||||||
# QLIBC shall point to the directory where the library is installed.
|
|
||||||
bench-qlibc:
|
|
||||||
@if test -n "$${QLIBC}" ; then $(MAKE) bench-qlibc0 ; else echo "Nothing to be done for QLIBC." ; fi
|
|
||||||
|
|
||||||
bench-qlibc0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${QLIBC}/include" -L "$${QLIBC}/lib" -lqlibc -pthread bench-qlibc.c common.c -o bench-qlibc.exe
|
|
||||||
@LD_LIBRARY_PATH="$${QLIBC}/lib:$${LD_LIBRARY_PATH}" ./bench-qlibc.exe 10
|
|
||||||
@LD_LIBRARY_PATH="$${QLIBC}/lib:$${LD_LIBRARY_PATH}" ./bench-qlibc.exe 20
|
|
||||||
@LD_LIBRARY_PATH="$${QLIBC}/lib:$${LD_LIBRARY_PATH}" ./bench-qlibc.exe 30
|
|
||||||
|
|
||||||
# LIBSRT shall point to the directory where it is installed
|
|
||||||
bench-libsrt:
|
|
||||||
@if test -n "$${LIBSRT}" ; then $(MAKE) bench-libsrt0 ; else echo "Nothing to be done for LIBSRT." ; fi
|
|
||||||
|
|
||||||
bench-libsrt0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${LIBSRT}/src" bench-libsrt.c common.c -o bench-libsrt.exe $${LIBSRT}/src/.libs/libsrt.a
|
|
||||||
@./bench-libsrt.exe 20
|
|
||||||
@./bench-libsrt.exe 50
|
|
||||||
|
|
||||||
|
|
||||||
# LIBLFDS shall point to the directory where the bin/build/inc/obj/src directories are
|
|
||||||
# The library shall be built.
|
|
||||||
bench-liblfds:
|
|
||||||
@if test -n "$${LIBLFDS}" ; then $(MAKE) bench-liblfds0 ; else echo "Nothing to be done for LIBLFDS." ; fi
|
|
||||||
bench-liblfds0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${LIBLFDS}/inc" -Wno-unknown-pragmas bench-liblfds.c common.c -DMULTI_THREAD_MEASURE -o bench-liblfds.exe $${LIBLFDS}/bin/liblfds711.a -lpthread
|
|
||||||
@LD_LIBRARY_PATH="$${LIBLFDS}/bin:$${LD_LIBRARY_PATH}" ./bench-liblfds.exe 60
|
|
||||||
|
|
||||||
|
|
||||||
# CONCURRENTQUEUE shall point to the directory where the bin/build/inc/obj/src directories are
|
|
||||||
# The library shall be built.
|
|
||||||
bench-concurrentqueue:
|
|
||||||
@if test -n "$${CONCURRENTQUEUE}" ; then $(MAKE) bench-concurrentqueue0 ; else echo "Nothing to be done for CONCURRENTQUEUE." ; fi
|
|
||||||
bench-concurrentqueue0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${CONCURRENTQUEUE}/" bench-concurrentqueue.cpp common.c -DMULTI_THREAD_MEASURE -o bench-concurrentqueue.exe -lpthread
|
|
||||||
@./bench-concurrentqueue.exe 60
|
|
||||||
|
|
||||||
|
|
||||||
# XXHASH shall point to the source directory of xxhash
|
|
||||||
# The library shall be built.
|
|
||||||
bench-xxhash:
|
|
||||||
@if test -n "$${XXHASH}" ; then $(MAKE) bench-xxhash0 ; else echo "Nothing to be done for XXHASH." ; fi
|
|
||||||
bench-xxhash0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${XXHASH}/" bench-xxhash.c common.c "$${XXHASH}/libxxhash.a" -o bench-xxhash.exe
|
|
||||||
@./bench-xxhash.exe 70
|
|
||||||
|
|
||||||
# BOOST shall point to the header location.
|
|
||||||
bench-boost:
|
|
||||||
@if test -n "$${BOOST}" ; then $(MAKE) bench-boost0 ; else echo "Nothing to be done for BOOST." ; fi
|
|
||||||
bench-boost0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${BOOST}" bench-boost.cpp common.c -DMULTI_THREAD_MEASURE -o bench-boost-thread.exe -lpthread
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${BOOST}" bench-boost.cpp common.c -o bench-boost.exe -lpthread
|
|
||||||
@./bench-boost.exe 42
|
|
||||||
@./bench-boost.exe 41
|
|
||||||
@./bench-boost-thread.exe 60
|
|
||||||
|
|
||||||
# NEDTRIES shall point to the header location.
|
|
||||||
bench-nedtries:
|
|
||||||
@if test -n "$${NEDTRIES}" ; then $(MAKE) bench-nedtries0 ; else echo "Nothing to be done for NEDTRIES." ; fi
|
|
||||||
bench-nedtries0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${NEDTRIES}" bench-nedtries.c common.c -o bench-nedtries.exe
|
|
||||||
@./bench-nedtries.exe 40
|
|
||||||
@./bench-nedtries.exe 45
|
|
||||||
|
|
||||||
# RIGTORP_HASHMAP shall point to the directory where the headers are
|
|
||||||
bench-rigtorp-hashmap:
|
|
||||||
@if test -n "$${RIGTORP_HASHMAP}" ; then $(MAKE) bench-rigtorp-hashmap0 ; else echo "Nothing to be done for RIGTORP_HASHMAP." ; fi
|
|
||||||
|
|
||||||
bench-rigtorp-hashmap0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${RIGTORP_HASHMAP}/include" bench-rigtorp-hashmap.cpp common.c -o bench-rigtorp-hashmap.exe
|
|
||||||
@./bench-rigtorp-hashmap.exe 42
|
|
||||||
@./bench-rigtorp-hashmap.exe 41
|
|
||||||
@./bench-rigtorp-hashmap.exe 43
|
|
||||||
|
|
||||||
# RIGTORP_MPMC_QUEUE shall point to the directory where the headers are
|
|
||||||
bench-rigtorp-mpmc-queue:
|
|
||||||
@if test -n "$${RIGTORP_MPMC_QUEUE}" ; then $(MAKE) bench-rigtorp-mpmc-queue0 ; else echo "Nothing to be done for RIGTORP_MPMC_QUEUE." ; fi
|
|
||||||
bench-rigtorp-mpmc-queue0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${RIGTORP_MPMC_QUEUE}" bench-rigtorp-mpmcqueue.cpp common.c -DMULTI_THREAD_MEASURE -o bench-mpmcqueue.exe -lpthread
|
|
||||||
@./bench-mpmcqueue.exe 60
|
|
||||||
|
|
||||||
# CTL shall point to the source directory (not where the headers are)
|
|
||||||
bench-ctl:
|
|
||||||
@if test -n "$${CTL}" ; then $(MAKE) bench-ctl0 ; else echo "Nothing to be done for CTL." ; fi
|
|
||||||
|
|
||||||
bench-ctl0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I $${CTL} bench-ctl.c common.c -o bench-ctl.exe
|
|
||||||
@./bench-ctl.exe 10
|
|
||||||
@./bench-ctl.exe 20
|
|
||||||
@./bench-ctl.exe 30
|
|
||||||
@./bench-ctl.exe 40
|
|
||||||
@./bench-ctl.exe 50
|
|
||||||
|
|
||||||
# STC shall point to the source directory (not where the headers are)
|
|
||||||
bench-stc:
|
|
||||||
@if test -n "$${STC}" ; then $(MAKE) bench-stc0 ; else echo "Nothing to be done for STC." ; fi
|
|
||||||
|
|
||||||
bench-stc0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I $${STC}/include bench-stc.c common.c -o bench-stc.exe
|
|
||||||
@./bench-stc.exe 10
|
|
||||||
@./bench-stc.exe 20
|
|
||||||
@./bench-stc.exe 30
|
|
||||||
@./bench-stc.exe 40
|
|
||||||
@./bench-stc.exe 41
|
|
||||||
@./bench-stc.exe 50
|
|
||||||
|
|
||||||
# POTTERY shall point to the source directory (not where the headers are)
|
|
||||||
bench-pottery:
|
|
||||||
@if test -n "$${POTTERY}" ; then $(MAKE) bench-pottery0 ; else echo "Nothing to be done for POTTERY." ; fi
|
|
||||||
|
|
||||||
bench-pottery0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -DPOTTERY_AVAILABLE=1 -I $${POTTERY}/include bench-pottery.c common.c -o bench-pottery.exe
|
|
||||||
@./bench-pottery.exe 10
|
|
||||||
@./bench-pottery.exe 20
|
|
||||||
@./bench-pottery.exe 30
|
|
||||||
@./bench-pottery.exe 40
|
|
||||||
@./bench-pottery.exe 41
|
|
||||||
@./bench-pottery.exe 50
|
|
||||||
|
|
||||||
# CCLIB shall point to the source directory of CC (where the headers are)
|
|
||||||
bench-CC:
|
|
||||||
@if test -n "$${CCLIB}" ; then $(MAKE) bench-CC0 ; else echo "Nothing to be done for CC." ; fi
|
|
||||||
|
|
||||||
bench-CC0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I $${CCLIB}/ bench-CC.c common.c -o bench-CC.exe
|
|
||||||
@./bench-CC.exe 10
|
|
||||||
@./bench-CC.exe 20
|
|
||||||
@./bench-CC.exe 40
|
|
||||||
@./bench-CC.exe 41
|
|
||||||
|
|
||||||
# VERSTABLE shall point to the source directory of VERSTABLE (where the headers are)
|
|
||||||
bench-verstable:
|
|
||||||
@if test -n "$${VERSTABLE}" ; then $(MAKE) bench-verstable0 ; else echo "Nothing to be done for VERSTABLE." ; fi
|
|
||||||
|
|
||||||
bench-verstable0:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I $${VERSTABLE}/ bench-verstable.c common.c -o bench-verstable.exe
|
|
||||||
@./bench-verstable.exe 40
|
|
||||||
@./bench-verstable.exe 41
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
bench-mlib-json: bench-mlib
|
|
||||||
@./bench-mlib.exe 110
|
|
||||||
@./bench-mlib.exe 111
|
|
||||||
@./bench-mlib.exe 112
|
|
||||||
|
|
||||||
bench-rapidjson:
|
|
||||||
@if test -n "$${RAPIDJSON}" ; then $(MAKE) bench-rapidjson0 ; else echo "Nothing to be done for RAPIDJSON." ; fi
|
|
||||||
bench-rapidjson0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -I "$${RAPIDJSON}/" bench-rapidjson.cpp common.c -o bench-rapidjson.exe
|
|
||||||
@./bench-rapidjson.exe 110
|
|
||||||
@./bench-rapidjson.exe 111
|
|
||||||
@./bench-rapidjson.exe 112
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
bench-plain:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) bench-plain-c.c -o bench-plain-c.exe
|
|
||||||
@./bench-plain-c.exe
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
bench-mempool:
|
|
||||||
@if test -n "$${BOOST}" ; then if test -n "$${GLIB}" ; then make bench-mempool0 BENCH_DEF="-DUSE_BOOST -DUSE_GLIB `pkg-config --libs --cflags glib-2.0` -lboost_system" ; else make bench-mempool0 BENCH_DEF="-DUSE_BOOST -lboost_system" ; fi ; else if test -n "$${GLIB}" ; then make bench-mempool0 BENCH_DEF="-DUSE_GLIB `pkg-config --libs --cflags glib-2.0`" ; else make bench-mempool0 ; fi ; fi
|
|
||||||
bench-mempool0:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) pool.cc $(BENCH_DEF) -o bench-mempool.exe
|
|
||||||
@./bench-mempool.exe
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
bench-maxdict:
|
|
||||||
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) max-dict.c -o bench-max-dict.exe
|
|
||||||
@./bench-max-dict.exe
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
# BSTRLIB shall point to the BSTRLIB sources
|
|
||||||
# LIBSRT shall point to the LIBSRT sources
|
|
||||||
bench-string:
|
|
||||||
@if test -n "$${BSTRLIB}" ; then $(MAKE) bench-string-step1 BENCH_DEF="-DBENCH_CAN_USE_BSTRLIB -I ${BSTRLIB} $${BSTRLIB}/obj/bstrlib.o $${BSTRLIB}/obj/bstraux.o $${BSTRLIB}/obj/bstrwrap.o" ; else $(MAKE) bench-string-step1 ; fi
|
|
||||||
|
|
||||||
bench-string-step1:
|
|
||||||
@if test -n "$${LIBSRT}" ; then $(MAKE) bench-string-step2 BENCH_DEF="$(BENCH_DEF) -DBENCH_CAN_USE_LIBSRT -I$${LIBSRT}/src $${LIBSRT}/src/.libs/libsrt.a" ; else $(MAKE) bench-string-step2 BENCH_DEF="$(BENCH_DEF)"; fi
|
|
||||||
|
|
||||||
#NOTE: Need to build by hand sds.o since it is not build by default and sds.c is not compatible with C++
|
|
||||||
bench-string-step2:
|
|
||||||
@if test -n "$${SDS}" ; then $(MAKE) bench-string-step4 BENCH_DEF="$(BENCH_DEF) -fpermissive -DBENCH_CAN_USE_SDS -I$${SDS}/ $${SDS}/sds.o" ; else $(MAKE) bench-string-step4 BENCH_DEF="$(BENCH_DEF)"; fi
|
|
||||||
|
|
||||||
bench-string-step4:
|
|
||||||
@if test -n "$${GLIB}" ; then $(MAKE) bench-string-step5 BENCH_DEF="$(BENCH_DEF) -DBENCH_CAN_USE_GLIB $$(pkg-config --cflags --libs glib-2.0)" ; else $(MAKE) bench-string-step5 BENCH_DEF="$(BENCH_DEF)"; fi
|
|
||||||
|
|
||||||
bench-string-step5:
|
|
||||||
@if test -n "$${POTTERY}" ; then $(MAKE) bench-string-step6 BENCH_DEF="$(BENCH_DEF) -DBENCH_CAN_USE_POTTERY -I$${POTTERY}/include -I$${POTTERY}/util/ $${POTTERY}/util/pottery/string/string.c" ; else $(MAKE) bench-string-step6 BENCH_DEF="$(BENCH_DEF)"; fi
|
|
||||||
|
|
||||||
bench-string-step6:
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -DBENCH_CAN_USE_STL -DBENCH_CAN_USE_MSTARLIB bench-string.cpp common.c $(BENCH_DEF) -o bench-string.exe
|
|
||||||
$(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -DBENCH_CAN_USE_STL -DBENCH_CAN_USE_MSTARLIB bench-string-2.cpp common.c $(BENCH_DEF) -o bench-string-2.exe
|
|
||||||
@./bench-string.exe
|
|
||||||
@./bench-string-2.exe 2000000 0
|
|
||||||
@./bench-string-2.exe 2000000 1
|
|
||||||
@./bench-string-2.exe 2000000 2
|
|
||||||
@./bench-string-2.exe 2000000 4
|
|
||||||
@./bench-string-2.exe 2000000 5
|
|
||||||
|
|
||||||
bench-string-pgo:
|
|
||||||
$(MAKE) bench-string XCFLAGS="-fprofile-generate=pgo"
|
|
||||||
$(MAKE) bench-string XCFLAGS="-fprofile-use=pgo"
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
bench-find-sort:
|
|
||||||
g++ bench-find-sort.cpp -O2 -march=native -std=c++11 -I.. -g common.c -o bench-find-sort.exe
|
|
||||||
./bench-find-sort.exe 10000000
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o bench-*.exe
|
|
||||||
$(RM) bench-*.s *~ massif.out.*
|
|
||||||
$(RM) plot-*.dat
|
|
||||||
$(RM) pgo
|
|
||||||
$(RM) tmp-serial.*
|
|
||||||
cd nucleotide && $(MAKE) clean
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
massif-do: all
|
|
||||||
@valgrind --tool=massif ./bench-mlib.exe $(N)
|
|
||||||
@valgrind --tool=massif ./bench-mlib-mempool.exe $(N)
|
|
||||||
@valgrind --tool=massif ./bench-stl.exe $(N)
|
|
||||||
@valgrind --tool=massif ./bench-qt.exe $(N)
|
|
||||||
@valgrind --tool=massif ./bench-glib.exe $(N)
|
|
||||||
@test -f ./bench-klib.exe && valgrind --tool=massif ./bench-klib.exe $(N)
|
|
||||||
@test -f ./bench-libdynamic.exe && valgrind --tool=massif ./bench-libdynamic.exe $(N)
|
|
||||||
|
|
||||||
massif-visu:
|
|
||||||
test -f massif.out.* || $(MAKE) massif-do
|
|
||||||
for i in massif.out.* ; do ms_print $$i|head -30 ; done
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include "cc.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
vec( unsigned int ) a1, a2;
|
|
||||||
init(&a1);
|
|
||||||
init(&a2);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
push(&a1, rand_get() );
|
|
||||||
push(&a2, rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += *get(&a1, i ) * *get(&a2, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
cleanup(&a1);
|
|
||||||
cleanup(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_list(size_t n)
|
|
||||||
{
|
|
||||||
list( unsigned int ) a1, a2;
|
|
||||||
init(&a1);
|
|
||||||
init(&a2);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
push(&a1, rand_get() );
|
|
||||||
push(&a2, rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned *it1 = first( &a1 ), *it2 = first( &a2 ); it1 != end( &a1 ); it1 = next( &a1, it1 ), it2 = next(&a2, it2) ) {
|
|
||||||
s += *it1 * *it2;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
cleanup(&a1);
|
|
||||||
cleanup(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
map( unsigned long, unsigned long ) dict;
|
|
||||||
init(&dict);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long value = rand_get();
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
insert(&dict, key, value);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
const unsigned long *val = get(&dict, key);
|
|
||||||
if (val != NULL)
|
|
||||||
s += *val;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
cleanup(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
typedef struct {
|
|
||||||
char a[256];
|
|
||||||
} char_array_t;
|
|
||||||
static inline void char_init (char_array_t *a) { a->a[0] = 0; }
|
|
||||||
static inline void char_set (char_array_t *a, const char_array_t b) { strcpy(a->a, b.a); }
|
|
||||||
static inline bool char_equal_p (const char_array_t *a, const char_array_t *b) { return strcmp(a->a,b->a)==0; }
|
|
||||||
static inline bool char_cmp (const char_array_t *a, const char_array_t *b) { return strcmp(a->a,b->a); }
|
|
||||||
static inline void char_clear (char_array_t *a) { (void)a; }
|
|
||||||
static inline size_t char_hash(const char_array_t *a) {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = a->a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
#define CC_DTOR char_array_t, { char_clear(&val); }
|
|
||||||
#define CC_CMPR char_array_t, { return char_cmp(&val_1, &val_2); }
|
|
||||||
#define CC_HASH char_array_t, { return char_hash(&val); }
|
|
||||||
#include "cc.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
map( char_array_t, char_array_t) dict;
|
|
||||||
init(&dict);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
insert(&dict, s1, s2);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
const char_array_t *val = get(&dict, s1);
|
|
||||||
if (val != NULL)
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
cleanup(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("CC", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "m-thread.h"
|
|
||||||
|
|
||||||
#include <boost/unordered/unordered_flat_map.hpp>
|
|
||||||
#include <boost/lockfree/queue.hpp>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
boost::unordered_flat_map<unsigned long, unsigned long> dict;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
boost::unordered_flat_map<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2_linear(size_t n)
|
|
||||||
{
|
|
||||||
boost::unordered_flat_map<unsigned long, unsigned long> dict;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[i] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
boost::unordered_flat_map<unsigned long, unsigned long>::iterator it = dict.find(i);
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::size_t hash_value(const char_array_s &k) {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
boost::unordered_flat_map<char_array_s, char_array_s> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
boost::unordered_flat_map<char_array_s, char_array_s>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static void
|
|
||||||
test_dict_str(size_t n)
|
|
||||||
{
|
|
||||||
boost::unordered_flat_map<string, string> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
string s2 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
boost::unordered_flat_map<string, string>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
boost::lockfree::queue<unsigned int, boost::lockfree::capacity<4*64>> g_buff;
|
|
||||||
boost::lockfree::queue<unsigned long long, boost::lockfree::capacity<4*64>> g_final;
|
|
||||||
|
|
||||||
static void final(void *arg)
|
|
||||||
{
|
|
||||||
size_t *p_n = (size_t*) arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
unsigned long long j, s = 0;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
while (!g_final.pop(j));
|
|
||||||
s += j;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void conso(void *arg)
|
|
||||||
{
|
|
||||||
unsigned int j;
|
|
||||||
size_t *p_n = (size_t*)arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
unsigned long long s = 0;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
while (!g_buff.pop(j));
|
|
||||||
s += j;
|
|
||||||
}
|
|
||||||
while (!g_final.push(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void prod(void *arg)
|
|
||||||
{
|
|
||||||
size_t *p_n = (size_t*)arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
size_t r = n;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
while (!g_buff.push(r));
|
|
||||||
r = r * 31421U + 6927U;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_queue(size_t n)
|
|
||||||
{
|
|
||||||
const int cpu_count = get_cpu_count();
|
|
||||||
const int prod_count = cpu_count/2;
|
|
||||||
const int conso_count = cpu_count - prod_count;
|
|
||||||
if (cpu_count < 2) {
|
|
||||||
fprintf(stderr, "WARNING: Can not measure Buffer performance.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rand_get();
|
|
||||||
// Create thread
|
|
||||||
m_thread_t idx_p[prod_count];
|
|
||||||
m_thread_t idx_c[conso_count];
|
|
||||||
m_thread_t idx_final;
|
|
||||||
for(int i = 0; i < prod_count; i++) {
|
|
||||||
m_thread_create (idx_p[i], prod, &n);
|
|
||||||
}
|
|
||||||
for(int i = 0; i < conso_count; i++) {
|
|
||||||
m_thread_create (idx_c[i], conso, &n);
|
|
||||||
}
|
|
||||||
size_t n2 = conso_count;
|
|
||||||
m_thread_create(idx_final, final, &n2);
|
|
||||||
|
|
||||||
// Wait for jobs to be done.
|
|
||||||
for(int i = 0; i < prod_count; i++) {
|
|
||||||
m_thread_join(idx_p[i]);
|
|
||||||
}
|
|
||||||
for(int i = 0; i < conso_count; i++) {
|
|
||||||
m_thread_join(idx_c[i]);
|
|
||||||
}
|
|
||||||
m_thread_join(idx_final);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42, "dict", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 43, "DictStr", 1000000, 0, test_dict_str, 0},
|
|
||||||
{ 46, "DictLinear", 1000000, 0, test_dict2_linear, 0},
|
|
||||||
{ 60, "Queue MPMC", 1000000, 0, test_queue, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("BOOST", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,204 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "macro_collections.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
// CMC list are dynamic array
|
|
||||||
#define MY_LIST_PARAMS (list_uint, list_uint_s, , , unsigned int)
|
|
||||||
C_MACRO_COLLECTIONS_EXTENDED(CMC, LIST, MY_LIST_PARAMS, (STR))
|
|
||||||
|
|
||||||
struct list_uint_s_fval list_fval = { .cmp = NULL,
|
|
||||||
.cpy = NULL,
|
|
||||||
.str = NULL,
|
|
||||||
.free = NULL,
|
|
||||||
.hash = NULL,
|
|
||||||
.pri = NULL };
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
struct list_uint_s *a1 = list_uint_new(1, &list_fval);
|
|
||||||
struct list_uint_s *a2 = list_uint_new(1, &list_fval);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
list_uint_push_back(a1, rand_get() );
|
|
||||||
list_uint_push_back(a2, rand_get() );
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += list_uint_get(a1, i ) * list_uint_get(a2, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
list_uint_free(a1);
|
|
||||||
list_uint_free(a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define my_cmp(a,b) ( (a) < (b) ? -1 : (a) > (b) )
|
|
||||||
|
|
||||||
#define MY_TMAP_PARAMS (tree_ulong, tree_ulong_s, , unsigned long, bool)
|
|
||||||
C_MACRO_COLLECTIONS_EXTENDED(CMC, TREEMAP, MY_TMAP_PARAMS, (STR))
|
|
||||||
|
|
||||||
int cmp_ulong(unsigned long a, unsigned long b) { return my_cmp(a,b); }
|
|
||||||
|
|
||||||
struct tree_ulong_s_fkey tree_fkey = { .cmp = cmp_ulong,
|
|
||||||
.cpy = NULL,
|
|
||||||
.str = NULL,
|
|
||||||
.free = NULL,
|
|
||||||
.hash = NULL,
|
|
||||||
.pri = NULL };
|
|
||||||
|
|
||||||
struct tree_ulong_s_fval tree_fval = { .cmp = NULL,
|
|
||||||
.cpy = NULL,
|
|
||||||
.str = NULL,
|
|
||||||
.free = NULL,
|
|
||||||
.hash = NULL,
|
|
||||||
.pri = NULL };
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
struct tree_ulong_s *tree;
|
|
||||||
tree = tree_ulong_new(&tree_fkey, &tree_fval);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long j = rand_get();
|
|
||||||
tree_ulong_insert(tree, j, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long j = rand_get();
|
|
||||||
if (tree_ulong_get_ref(tree, j) != 0)
|
|
||||||
s+= j;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
tree_ulong_free(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
#define hash_func(a) kh_int64_hash_func(a)
|
|
||||||
size_t hash_ulong(unsigned long a)
|
|
||||||
{
|
|
||||||
return ( (a) >> 33 ) ^ (a) ^ ((a) << 11);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MY_DICT_PARAMS (hmap, hmap_s, , unsigned long, unsigned long)
|
|
||||||
C_MACRO_COLLECTIONS_EXTENDED(CMC, HASHMAP, MY_DICT_PARAMS, (STR))
|
|
||||||
|
|
||||||
struct hmap_s_fkey hmap_fkey = { .cmp = cmp_ulong,
|
|
||||||
.cpy = NULL,
|
|
||||||
.str = NULL,
|
|
||||||
.free = NULL,
|
|
||||||
.hash = hash_ulong,
|
|
||||||
.pri = NULL };
|
|
||||||
|
|
||||||
struct hmap_s_fval hmap_fval = { .cmp = NULL,
|
|
||||||
.cpy = NULL,
|
|
||||||
.str = NULL,
|
|
||||||
.free = NULL,
|
|
||||||
.hash = NULL,
|
|
||||||
.pri = NULL };
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
struct hmap_s *dict = hmap_new(16, 0.7, &hmap_fkey, &hmap_fval);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
hmap_insert(dict, rand_get(), rand_get());
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long *val = hmap_get_ref(dict, rand_get());
|
|
||||||
if (val != 0)
|
|
||||||
s += *val;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
hmap_free(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#if 0 // Not working issue in using not integer types
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char a[256];
|
|
||||||
} char_array_t;
|
|
||||||
static inline int char_cmp (const char_array_t a, const char_array_t b) { return strcmp(a.a,b.a); }
|
|
||||||
static inline size_t char_hash(const char_array_t a) {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = a.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MY_DICTB_PARAMS (bhmap, bhmap_s, , char_array_t, char_array_t)
|
|
||||||
C_MACRO_COLLECTIONS_EXTENDED(CMC, HASHMAP, MY_DICT_PARAMS, (STR))
|
|
||||||
|
|
||||||
struct bhmap_s_fkey bhmap_fkey = { .cmp = char_cmp,
|
|
||||||
.cpy = NULL,
|
|
||||||
.str = NULL,
|
|
||||||
.free = NULL,
|
|
||||||
.hash = char_hash,
|
|
||||||
.pri = NULL };
|
|
||||||
|
|
||||||
struct bhmap_s_fval bhmap_fval = { .cmp = NULL,
|
|
||||||
.cpy = NULL,
|
|
||||||
.str = NULL,
|
|
||||||
.free = NULL,
|
|
||||||
.hash = NULL,
|
|
||||||
.pri = NULL };
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
struct bhmap_s *dict = bhmap_new(16, 0.7, &bhmap_fkey, &bhmap_fval);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
bhmap_insert(dict, s1, s2);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get() );
|
|
||||||
char_array_t *val = bhmap_get_ref(dict, s1);
|
|
||||||
if (val != 0)
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
bhmap_free(dict);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
//{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("CMC", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "array.h"
|
|
||||||
#include "slist.h"
|
|
||||||
#include "treetable.h"
|
|
||||||
#include "hashtable.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
Array *a1, *a2;
|
|
||||||
enum cc_stat stat;
|
|
||||||
|
|
||||||
stat = array_new(&a1);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
stat = array_new(&a2);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
stat = array_add(a1, (void*) (uintptr_t)rand_get() );
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
stat = array_add(a2, (void*) (uintptr_t)rand_get() );
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
void *e, *f;
|
|
||||||
stat = array_get_at(a1, i, &e);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
stat = array_get_at(a2, i, &f);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
s += ((unsigned int)(uintptr_t) e) * ((unsigned int)(uintptr_t) f);
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
array_destroy(a1);
|
|
||||||
array_destroy(a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_list(size_t n)
|
|
||||||
{
|
|
||||||
SList *a1, *a2;
|
|
||||||
enum cc_stat stat;
|
|
||||||
|
|
||||||
stat = slist_new(&a1);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
stat = slist_new(&a2);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
stat = slist_add(a1, (void*) (uintptr_t)rand_get() );
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
stat = slist_add(a2, (void*) (uintptr_t)rand_get() );
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
SListIter iter1, iter2;
|
|
||||||
void *e, *f;
|
|
||||||
slist_iter_init(&iter1, a1);
|
|
||||||
slist_iter_init(&iter2, a2);
|
|
||||||
while (slist_iter_next(&iter1, &e) == CC_OK && slist_iter_next(&iter2, &f) == CC_OK) {
|
|
||||||
s += ((unsigned int)(uintptr_t) e) * ((unsigned int)(uintptr_t) f);
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
slist_destroy(a1);
|
|
||||||
slist_destroy(a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static int compare(const void *a, const void *b)
|
|
||||||
{
|
|
||||||
const uintptr_t pa = (uintptr_t) a;
|
|
||||||
const uintptr_t pb = (uintptr_t) b;
|
|
||||||
return (pa < pb) ? -1 : (pa > pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
TreeTable *tree;
|
|
||||||
enum cc_stat stat;
|
|
||||||
|
|
||||||
stat = treetable_new(compare, &tree);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
void *key = (void*)(uintptr_t) rand_get();
|
|
||||||
stat = treetable_add(tree, key, key);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
void *e;
|
|
||||||
void *key = (void*) (uintptr_t) rand_get();
|
|
||||||
stat = treetable_get(tree, key, &e);
|
|
||||||
if (stat == CC_OK)
|
|
||||||
s += (uintptr_t)e;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
treetable_destroy(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static size_t hash_func (const void *key, int l, uint32_t seed)
|
|
||||||
{
|
|
||||||
const unsigned long pa = (uintptr_t) key;
|
|
||||||
(void)l;
|
|
||||||
return pa ^ seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int equal_func(const void *key1, const void *key2)
|
|
||||||
{
|
|
||||||
const unsigned long pa = (uintptr_t) key1;
|
|
||||||
const unsigned long pb = (uintptr_t) key2;
|
|
||||||
return (pa < pb) ? -1 : pa > pb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
HashTable *dict;
|
|
||||||
enum cc_stat stat;
|
|
||||||
HashTableConf htc;
|
|
||||||
hashtable_conf_init(&htc);
|
|
||||||
htc.hash = hash_func;
|
|
||||||
htc.key_compare = equal_func;
|
|
||||||
stat = hashtable_new_conf(&htc, &dict);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
void *value = (void*)(uintptr_t) rand_get();
|
|
||||||
void *key = (void*)(uintptr_t) rand_get();
|
|
||||||
stat = hashtable_add(dict, key, value );
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
void *key = (void*)(uintptr_t) rand_get();
|
|
||||||
void *r;
|
|
||||||
stat = hashtable_get(dict, key, &r);
|
|
||||||
if (stat == CC_OK)
|
|
||||||
s += (uintptr_t) r;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
hashtable_destroy(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef char char_array_t[256];
|
|
||||||
|
|
||||||
static int char_equal (const void* a, const void * b)
|
|
||||||
{
|
|
||||||
const char_array_t *pa = (const char_array_t *)a;
|
|
||||||
const char_array_t *pb = (const char_array_t *)b;
|
|
||||||
return strcmp(*pa,*pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t char_hash(const void *a, int l, uint32_t seed)
|
|
||||||
{
|
|
||||||
const char_array_t *pa = (const char_array_t *)a;
|
|
||||||
const char *s = *pa;
|
|
||||||
(void)l ;
|
|
||||||
size_t hash = seed;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
HashTable *dict;
|
|
||||||
enum cc_stat stat;
|
|
||||||
HashTableConf htc;
|
|
||||||
hashtable_conf_init(&htc);
|
|
||||||
htc.hash = char_hash;
|
|
||||||
htc.key_compare = char_equal;
|
|
||||||
stat = hashtable_new_conf(&htc, &dict);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
|
|
||||||
char_array_t **tab = malloc (sizeof(char_array_t *)*2*n);
|
|
||||||
if (!tab) abort();
|
|
||||||
size_t cpt = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t *key = malloc (sizeof (char_array_t));
|
|
||||||
char_array_t *value = malloc (sizeof (char_array_t));
|
|
||||||
tab[cpt++] = key;
|
|
||||||
tab[cpt++] = value;
|
|
||||||
sprintf(*key, "%u", rand_get());
|
|
||||||
sprintf(*value, "%u", rand_get());
|
|
||||||
stat = hashtable_add(dict, key, value );
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1;
|
|
||||||
void *r;
|
|
||||||
sprintf(s1, "%u", rand_get());
|
|
||||||
stat = hashtable_get(dict, s1, &r);
|
|
||||||
if (stat == CC_OK)
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
hashtable_destroy(dict);
|
|
||||||
if (cpt != 2*n) abort();
|
|
||||||
for(size_t i = 0; i < 2*n;i++)
|
|
||||||
free(tab[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static int cmp_float(const void * a, const void *b)
|
|
||||||
{
|
|
||||||
const float *const*pa = a, *const*pb = b;
|
|
||||||
return (**pa < **pb) ? -1 : (**pa > **pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
Array *a1;
|
|
||||||
enum cc_stat stat;
|
|
||||||
|
|
||||||
stat = array_new(&a1);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
float *v = malloc(sizeof(float));
|
|
||||||
*v = rand_get();
|
|
||||||
stat = array_add(a1, v );
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
}
|
|
||||||
array_sort(a1, cmp_float);
|
|
||||||
void *e;
|
|
||||||
stat = array_get_at(a1, 0, &e);
|
|
||||||
if (stat != CC_OK) abort();
|
|
||||||
g_result = *(float*)e;
|
|
||||||
array_destroy(a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 50, "Sort",10000000, 0, test_sort, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("CollectionC", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "concurrentqueue.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
moodycamel::ConcurrentQueue<unsigned int> g_buff;
|
|
||||||
moodycamel::ConcurrentQueue<unsigned long long> g_final;
|
|
||||||
|
|
||||||
static void final(void *arg)
|
|
||||||
{
|
|
||||||
size_t *p_n = (size_t*) arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
unsigned long long j, s = 0;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
while (!g_final.try_dequeue(j));
|
|
||||||
s += j;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void conso(void *arg)
|
|
||||||
{
|
|
||||||
unsigned int j;
|
|
||||||
size_t *p_n = (size_t*)arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
unsigned long long s = 0;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
while (!g_buff.try_dequeue(j));
|
|
||||||
s += j;
|
|
||||||
}
|
|
||||||
while (!g_final.try_enqueue(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void prod(void *arg)
|
|
||||||
{
|
|
||||||
size_t *p_n = (size_t*)arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
size_t r = n;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
while (!g_buff.try_enqueue(r));
|
|
||||||
r = r * 31421U + 6927U;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_queue(size_t n)
|
|
||||||
{
|
|
||||||
const int cpu_count = get_cpu_count();
|
|
||||||
const int prod_count = cpu_count/2;
|
|
||||||
const int conso_count = cpu_count - prod_count;
|
|
||||||
if (cpu_count < 2) {
|
|
||||||
fprintf(stderr, "WARNING: Can not measure Buffer performance.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rand_get();
|
|
||||||
// Create thread
|
|
||||||
m_thread_t idx_p[prod_count];
|
|
||||||
m_thread_t idx_c[conso_count];
|
|
||||||
m_thread_t idx_final;
|
|
||||||
for(int i = 0; i < prod_count; i++) {
|
|
||||||
m_thread_create (idx_p[i], prod, &n);
|
|
||||||
}
|
|
||||||
for(int i = 0; i < conso_count; i++) {
|
|
||||||
m_thread_create (idx_c[i], conso, &n);
|
|
||||||
}
|
|
||||||
size_t n2 = conso_count;
|
|
||||||
m_thread_create(idx_final, final, &n2);
|
|
||||||
|
|
||||||
// Wait for jobs to be done.
|
|
||||||
for(int i = 0; i < prod_count; i++) {
|
|
||||||
m_thread_join(idx_p[i]);
|
|
||||||
}
|
|
||||||
for(int i = 0; i < conso_count; i++) {
|
|
||||||
m_thread_join(idx_c[i]);
|
|
||||||
}
|
|
||||||
m_thread_join(idx_final);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 60, "Queue MPMC", 1000000, 0, test_queue, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("CONCURRENT-QUEUE", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "m-core.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
typedef unsigned int uint;
|
|
||||||
typedef unsigned long ulong;
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
#define POD
|
|
||||||
#define T uint
|
|
||||||
#include "ctl/vector.h"
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
vec_uint a1 = vec_uint_init();
|
|
||||||
vec_uint a2 = vec_uint_init();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
vec_uint_push_back(&a1, rand_get() );
|
|
||||||
vec_uint_push_back(&a2, rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += *vec_uint_at(&a1, i ) * *vec_uint_at(&a2, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
vec_uint_free(&a1);
|
|
||||||
vec_uint_free(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define POD
|
|
||||||
#define T uint
|
|
||||||
#include "ctl/forward_list.h"
|
|
||||||
|
|
||||||
static void test_list (size_t n)
|
|
||||||
{
|
|
||||||
slist_uint a1 = slist_uint_init();
|
|
||||||
slist_uint a2 = slist_uint_init();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
slist_uint_push_front(&a1, rand_get());
|
|
||||||
slist_uint_push_front(&a2, rand_get());
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
slist_uint_it it1 = slist_uint_begin(&a1);
|
|
||||||
slist_uint_it it2 = slist_uint_begin(&a2);
|
|
||||||
for( ; !slist_uint_it_done(&it1) ;
|
|
||||||
slist_uint_it_next(&it1), slist_uint_it_next(&it2)) {
|
|
||||||
s += *slist_uint_it_ref(&it1) * *slist_uint_it_ref(&it2);
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
slist_uint_free(&a1);
|
|
||||||
slist_uint_free(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define POD
|
|
||||||
#define T ulong
|
|
||||||
#include "ctl/set.h"
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
int_cmp(ulong *a, ulong *b) {
|
|
||||||
return *a < *b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
set_ulong tree = set_ulong_init (int_cmp);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
set_ulong_insert (&tree, rand_get() );
|
|
||||||
}
|
|
||||||
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long j = rand_get();
|
|
||||||
if (set_ulong_find_node(&tree, j) != NULL)
|
|
||||||
s+= j;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
set_ulong_free(&tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned long key;
|
|
||||||
unsigned long value;
|
|
||||||
} pair_ulong;
|
|
||||||
|
|
||||||
// Use of M*LIB hash function
|
|
||||||
static inline size_t
|
|
||||||
pair_ulong_hash(pair_ulong *a)
|
|
||||||
{
|
|
||||||
return M_HASH_DEFAULT(a->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
pair_ulong_equal(pair_ulong *a, pair_ulong *b)
|
|
||||||
{
|
|
||||||
return a->key == b->key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
pair_ulong_free(pair_ulong *a) {
|
|
||||||
(void) a;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline pair_ulong
|
|
||||||
pair_ulong_copy(pair_ulong *self) {
|
|
||||||
return (pair_ulong) { .key = self->key, .value = self->value };
|
|
||||||
}
|
|
||||||
|
|
||||||
#define T pair_ulong
|
|
||||||
#include <ctl/unordered_map.h>
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
umap_pair_ulong dict = umap_pair_ulong_init(pair_ulong_hash, pair_ulong_equal);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long value = rand_get();
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
umap_pair_ulong_insert(&dict, (pair_ulong) { key, value });
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
umap_pair_ulong_it it = umap_pair_ulong_find(&dict, (pair_ulong) { rand_get() , 0 } );
|
|
||||||
if (!umap_pair_ulong_it_done(&it) )
|
|
||||||
s += it.ref->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
umap_pair_ulong_free(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define POD
|
|
||||||
#define T float
|
|
||||||
#include "ctl/vector.h"
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
vec_float a1 = vec_float_init();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
vec_float_push_back(&a1, rand_get());
|
|
||||||
}
|
|
||||||
vec_float_sort(&a1);
|
|
||||||
g_result = *vec_float_at(&a1, 0);
|
|
||||||
vec_float_free(&a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 50, "Sort", 10000000, 0, test_sort, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("CTL", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <iterator>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <google/dense_hash_map>
|
|
||||||
|
|
||||||
using google::dense_hash_map;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
dense_hash_map<unsigned long, unsigned long> dict;
|
|
||||||
dict.set_empty_key(-1);
|
|
||||||
dict.set_deleted_key(-2);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dense_hash_map<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<char_array_s> {
|
|
||||||
std::size_t operator()(const char_array_s &k) const {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
namespace tr1 {
|
|
||||||
template <> struct hash<char_array_s> {
|
|
||||||
std::size_t operator()(char_array_s k) const {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
dense_hash_map<char_array_s, char_array_s> dict;
|
|
||||||
struct char_array_s empty, del;
|
|
||||||
memset(&empty, 0, sizeof empty); empty.a[1] = 255;
|
|
||||||
memset(&del, 0, sizeof del); del.a[1] = 255;
|
|
||||||
dict.set_empty_key(empty);
|
|
||||||
dict.set_deleted_key(del);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
dense_hash_map<char_array_s, char_array_s>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static void
|
|
||||||
test_dict_str(size_t n)
|
|
||||||
{
|
|
||||||
dense_hash_map<string, string> dict;
|
|
||||||
string empty, del;
|
|
||||||
empty = "";
|
|
||||||
del = "DEL";
|
|
||||||
dict.set_empty_key(empty);
|
|
||||||
dict.set_deleted_key(del);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
string s2 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
dense_hash_map<string, string>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42,"dict", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 43, "DictStr", 1000000, 0, test_dict_str, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("DENSE-HASPMAP", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <iterator>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "hash_table7.hpp"
|
|
||||||
|
|
||||||
using namespace emhash7;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
HashMap<unsigned long, unsigned long> dict;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
HashMap<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2_linear(size_t n)
|
|
||||||
{
|
|
||||||
HashMap<unsigned long, unsigned long> dict;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[i] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
HashMap<unsigned long, unsigned long>::iterator it = dict.find(i);
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<char_array_s> {
|
|
||||||
std::size_t operator()(const char_array_s &k) const {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
HashMap<char_array_s, char_array_s> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
HashMap<char_array_s, char_array_s>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static void
|
|
||||||
test_dict_str(size_t n)
|
|
||||||
{
|
|
||||||
HashMap<string, string> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
string s2 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
HashMap<string, string>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42,"dict", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 43, "DictStr", 1000000, 0, test_dict_str, 0},
|
|
||||||
{ 46, "DictLinear", 1000000, 0, test_dict2_linear, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("EMHASH", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <iterator>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "emilib/hash_map.hpp"
|
|
||||||
|
|
||||||
using namespace emilib;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
HashMap<unsigned long, unsigned long> dict;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
HashMap<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2_linear(size_t n)
|
|
||||||
{
|
|
||||||
HashMap<unsigned long, unsigned long> dict;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[i] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
HashMap<unsigned long, unsigned long>::iterator it = dict.find(i);
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<char_array_s> {
|
|
||||||
std::size_t operator()(const char_array_s &k) const {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
HashMap<char_array_s, char_array_s> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
HashMap<char_array_s, char_array_s>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static void
|
|
||||||
test_dict_str(size_t n)
|
|
||||||
{
|
|
||||||
HashMap<string, string> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
string s2 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
HashMap<string, string>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42,"dict", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 43, "DictStr", 1000000, 0, test_dict_str, 0},
|
|
||||||
{ 46, "DictLinear", 1000000, 0, test_dict2_linear, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("EMILIB", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
// program to find longest contiguous subsequence
|
|
||||||
// based on https://www.geeksforgeeks.org/longest-consecutive-subsequence/
|
|
||||||
#include <iostream>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
// Returns length of the longest contiguous subsequence
|
|
||||||
int cpp_find_longest(int arr[], int n)
|
|
||||||
{
|
|
||||||
unordered_set<int> S;
|
|
||||||
int ans = 0;
|
|
||||||
|
|
||||||
// Hash all the array elements
|
|
||||||
for (int i = 0; i < n; i++)
|
|
||||||
S.insert(arr[i]);
|
|
||||||
|
|
||||||
// check each possible sequence from
|
|
||||||
// the start then update optimal length
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
// if current element is the starting
|
|
||||||
// element of a sequence
|
|
||||||
if (S.find(arr[i] - 1) == S.end()) {
|
|
||||||
// Then check for next elements
|
|
||||||
// in the sequence
|
|
||||||
int j = arr[i] + 1;
|
|
||||||
while (S.find(j) != S.end())
|
|
||||||
j++;
|
|
||||||
|
|
||||||
// update optimal length if
|
|
||||||
// this length is more
|
|
||||||
ans = max(ans, j - arr[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "m-dict.h"
|
|
||||||
|
|
||||||
static inline bool oor_equal_p(int a, unsigned char c) { return a == ((c == 0) ? INT_MIN : INT_MAX); }
|
|
||||||
static inline void oor_set(int *a, unsigned char c) { *a = ((c == 0) ? INT_MIN : INT_MAX); }
|
|
||||||
|
|
||||||
DICT_OASET_DEF(dict_int, int, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)))
|
|
||||||
|
|
||||||
// Returns length of the longest contiguous subsequence
|
|
||||||
int mlib_find_longest(int arr[], int n)
|
|
||||||
{
|
|
||||||
dict_int_t S;
|
|
||||||
int ans = 0;
|
|
||||||
|
|
||||||
dict_int_init(S);
|
|
||||||
|
|
||||||
// Hash all the array elements
|
|
||||||
for (int i = 0; i < n; i++)
|
|
||||||
dict_int_push(S, arr[i]);
|
|
||||||
|
|
||||||
// check each possible sequence from
|
|
||||||
// the start then update optimal length
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
// if current element is the starting
|
|
||||||
// element of a sequence
|
|
||||||
int *p = dict_int_get(S, arr[i]-1);
|
|
||||||
if (p == NULL) {
|
|
||||||
// Then check for next elements
|
|
||||||
// in the sequence
|
|
||||||
int j = arr[i] + 1;
|
|
||||||
while (dict_int_get(S, j) != NULL)
|
|
||||||
j++;
|
|
||||||
|
|
||||||
// update optimal length if
|
|
||||||
// this length is more
|
|
||||||
ans = M_MAX(ans, j - arr[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dict_int_clear(S);
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
int n = argc == 1 ? 10000 : atoi(argv[1]);
|
|
||||||
int *arr = (int*) malloc(n * sizeof(int));
|
|
||||||
for(int i = 0; i < n; i++)
|
|
||||||
arr[i] = rand_get();
|
|
||||||
|
|
||||||
unsigned long long t0 = cputime();
|
|
||||||
cout << "Length of the Longest contiguous subsequence is "
|
|
||||||
<< cpp_find_longest(arr, n) << endl;
|
|
||||||
|
|
||||||
unsigned long long t1 = cputime();
|
|
||||||
|
|
||||||
cout << "Length of the Longest contiguous subsequence is "
|
|
||||||
<< mlib_find_longest(arr, n) << endl;
|
|
||||||
unsigned long long t2 = cputime();
|
|
||||||
|
|
||||||
cout << "Time C++: " << (t1-t0) << " Time M*LIB: " << (t2-t1) << endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
// Need recent gcc
|
|
||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <iterator>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "flat_hash_map.hpp"
|
|
||||||
|
|
||||||
using namespace ska;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
flat_hash_map<unsigned long, unsigned long> dict;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
flat_hash_map<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2_linear(size_t n)
|
|
||||||
{
|
|
||||||
flat_hash_map<unsigned long, unsigned long> dict;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[i] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
flat_hash_map<unsigned long, unsigned long>::iterator it = dict.find(i);
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<char_array_s> {
|
|
||||||
std::size_t operator()(const char_array_s &k) const {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
flat_hash_map<char_array_s, char_array_s> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
flat_hash_map<char_array_s, char_array_s>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static void
|
|
||||||
test_dict_str(size_t n)
|
|
||||||
{
|
|
||||||
flat_hash_map<string, string> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
string s2 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
flat_hash_map<string, string>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42,"dict", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 43, "DictStr", 1000000, 0, test_dict_str, 0},
|
|
||||||
{ 46, "DictLinear", 1000000, 0, test_dict2_linear, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("FLAT-HASPMAP", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
GArray *a1, *a2;
|
|
||||||
a1 = g_array_new (FALSE, FALSE, sizeof (unsigned int));
|
|
||||||
a2 = g_array_new (FALSE, FALSE, sizeof (unsigned int));
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
unsigned int v = rand_get();
|
|
||||||
g_array_append_val(a1, v );
|
|
||||||
v = rand_get();
|
|
||||||
g_array_append_val(a2, v );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += g_array_index(a1, unsigned int, i ) * g_array_index(a2, unsigned int, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
g_array_free(a1, FALSE);
|
|
||||||
g_array_free(a2, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_list (size_t n)
|
|
||||||
{
|
|
||||||
GSList *a1 = NULL, *a2 = NULL;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
a1 = g_slist_prepend (a1, GINT_TO_POINTER (rand_get() ));
|
|
||||||
a2 = g_slist_prepend (a2, GINT_TO_POINTER (rand_get() ));
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(GSList *it1 = a1, *it2 = a2 ; it1 != NULL; it1 = g_slist_next(it1), it2 = g_slist_next(it2) ) {
|
|
||||||
s += GPOINTER_TO_INT(it1->data) * GPOINTER_TO_INT(it2->data);
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
g_slist_free(a1);
|
|
||||||
g_slist_free(a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static int compare(gconstpointer a, gconstpointer b, gpointer user_data)
|
|
||||||
{
|
|
||||||
const unsigned long *pa = a;
|
|
||||||
const unsigned long *pb = b;
|
|
||||||
(void) user_data;
|
|
||||||
return (*pa < *pb) ? -1 : (*pa > *pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
GTree *tree = g_tree_new_full(compare, NULL, free, NULL);
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
// NOTE: unsigned long are not designed to work with GPOINTER_TO_INT according to documentation.
|
|
||||||
unsigned long *p = malloc(sizeof(unsigned long));
|
|
||||||
*p = rand_get();
|
|
||||||
g_tree_insert(tree, p, p);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
unsigned long *p = g_tree_lookup(tree, &key);
|
|
||||||
if (p)
|
|
||||||
s += *p;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
g_tree_destroy(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static guint hash_func (gconstpointer a)
|
|
||||||
{
|
|
||||||
const unsigned long *pa = a;
|
|
||||||
return *pa;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean equal_func(gconstpointer a, gconstpointer b)
|
|
||||||
{
|
|
||||||
const unsigned long *pa = a;
|
|
||||||
const unsigned long *pb = b;
|
|
||||||
return *pa == *pb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
GHashTable *dict = g_hash_table_new_full(hash_func, equal_func, free, free);
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long *key = malloc(sizeof(unsigned long));
|
|
||||||
unsigned long *value = malloc(sizeof(unsigned long));
|
|
||||||
*key = rand_get();
|
|
||||||
*value = rand_get();
|
|
||||||
g_hash_table_insert(dict, key, value );
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
unsigned long *p = g_hash_table_lookup(dict, &key);
|
|
||||||
if (p)
|
|
||||||
s += *p;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
g_hash_table_destroy(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef char char_array_t[256];
|
|
||||||
|
|
||||||
static gboolean char_equal (gconstpointer a, gconstpointer b)
|
|
||||||
{
|
|
||||||
const char_array_t *pa = (const char_array_t *)a;
|
|
||||||
const char_array_t *pb = (const char_array_t *)b;
|
|
||||||
return strcmp(*pa,*pb)==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint char_hash(gconstpointer a)
|
|
||||||
{
|
|
||||||
const char_array_t *pa = (const char_array_t *)a;
|
|
||||||
const char *s = *pa;
|
|
||||||
guint hash = 0;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
GHashTable *dict = g_hash_table_new_full(char_hash, char_equal, free, free);
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t *key = malloc (sizeof (char_array_t));
|
|
||||||
char_array_t *value = malloc (sizeof (char_array_t));
|
|
||||||
sprintf(*key, "%u", rand_get());
|
|
||||||
sprintf(*value, "%u", rand_get());
|
|
||||||
g_hash_table_insert(dict, key, value );
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1;
|
|
||||||
sprintf(s1, "%u", rand_get());
|
|
||||||
char_array_t *p = g_hash_table_lookup(dict, &s1);
|
|
||||||
if (p)
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
g_hash_table_destroy(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static gint cmp_float(gconstpointer a,
|
|
||||||
gconstpointer b)
|
|
||||||
{
|
|
||||||
const float *pa = a, *pb = b;
|
|
||||||
return (*pa < *pb) ? -1 : (*pa > *pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
GArray *a1 = g_array_new (FALSE, FALSE, sizeof (float));
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
float v = rand_get();
|
|
||||||
g_array_append_val(a1, v );
|
|
||||||
}
|
|
||||||
g_array_sort(a1, cmp_float);
|
|
||||||
g_result = g_array_index (a1, float, 0);
|
|
||||||
g_array_free(a1, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 50, "Sort",10000000, 0, test_sort, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("GLIB", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <iterator>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "hopscotch_map.h"
|
|
||||||
|
|
||||||
using namespace tsl;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
tsl::hopscotch_map<unsigned long, unsigned long> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
hopscotch_map<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<char_array_s> {
|
|
||||||
std::size_t operator()(const char_array_s &k) const {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
hopscotch_map<char_array_s, char_array_s> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
hopscotch_map<char_array_s, char_array_s>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static void
|
|
||||||
test_dict_str(size_t n)
|
|
||||||
{
|
|
||||||
hopscotch_map<string, string> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
string s2 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
hopscotch_map<string, string>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42,"dict", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 43, "DictStr", 1000000, 0, test_dict_str, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("HOPSCOTCHMAP", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "kvec.h"
|
|
||||||
#include "klist.h"
|
|
||||||
#include "kbtree.h"
|
|
||||||
#include "khash.h"
|
|
||||||
#include "ksort.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
kvec_t(unsigned int) a1, a2;
|
|
||||||
|
|
||||||
kv_init(a1);
|
|
||||||
kv_init(a2);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
kv_push(unsigned int, a1, rand_get() );
|
|
||||||
kv_push(unsigned int, a2, rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += kv_A(a1, i ) * kv_A(a2, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
kv_destroy(a1);
|
|
||||||
kv_destroy(a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define uint_free(x)
|
|
||||||
KLIST_INIT(list_uint, unsigned int, uint_free)
|
|
||||||
|
|
||||||
static void test_list (size_t n)
|
|
||||||
{
|
|
||||||
klist_t(list_uint) *a1, *a2;
|
|
||||||
a1 = kl_init(list_uint);
|
|
||||||
a2 = kl_init(list_uint);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
*kl_pushp (list_uint, a1) = rand_get();
|
|
||||||
*kl_pushp (list_uint, a2) = rand_get();
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
kliter_t(list_uint) *it1, *it2;
|
|
||||||
for(it1 = kl_begin(a1), it2 = kl_begin(a2);
|
|
||||||
it1 != kl_end(a1);
|
|
||||||
it1 = kl_next(it1), it2 = kl_next(it2)) {
|
|
||||||
s += kl_val(it1) * kl_val(it2);
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
kl_destroy(list_uint, a1);
|
|
||||||
kl_destroy(list_uint, a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define my_cmp(a,b) ( (a) < (b) ? -1 : (a) > (b) )
|
|
||||||
|
|
||||||
KBTREE_INIT(kTree, unsigned long, my_cmp)
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
kbtree_t(kTree) *tree;
|
|
||||||
tree = kb_init(kTree, KB_DEFAULT_SIZE/2);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long j = rand_get();
|
|
||||||
kb_putp(kTree, tree, &j);
|
|
||||||
}
|
|
||||||
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long j = rand_get();
|
|
||||||
if (kb_getp(kTree, tree, &j) != 0)
|
|
||||||
s+= j;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
kb_destroy(kTree, tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define hash_eq(a, b) ((a) == (b))
|
|
||||||
#define hash_func(a) kh_int64_hash_func(a)
|
|
||||||
|
|
||||||
KHASH_INIT(iun, unsigned long, unsigned long, 1, hash_func, hash_eq)
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
khash_t(iun) *dict = kh_init(iun);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
int ret;
|
|
||||||
khiter_t k = kh_put(iun, dict, rand_get(), &ret);
|
|
||||||
kh_value(dict, k) = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
khiter_t k = kh_get(iun, dict, rand_get());
|
|
||||||
if (kh_exist(dict, k))
|
|
||||||
s += kh_value(dict, k);
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
kh_destroy(iun, dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char a[256];
|
|
||||||
} char_array_t;
|
|
||||||
static inline void char_init (char_array_t *a) { a->a[0] = 0; }
|
|
||||||
static inline void char_set (char_array_t *a, const char_array_t b) { strcpy(a->a, b.a); }
|
|
||||||
static inline bool char_equal_p (const char_array_t a, const char_array_t b) { return strcmp(a.a,b.a)==0; }
|
|
||||||
static inline size_t char_hash(const char_array_t a) {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = a.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
KHASH_INIT(iub, char_array_t, char_array_t, 1, char_hash, char_equal_p)
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
khash_t(iub) *dict = kh_init(iub);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
int ret;
|
|
||||||
char_array_t s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
khiter_t k = kh_put(iub, dict, s1, &ret);
|
|
||||||
char_set(&kh_value(dict, k), s2);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
khiter_t k = kh_get(iub, dict, s1);
|
|
||||||
if (kh_exist(dict, k))
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
kh_destroy(iub, dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
// NOTE: Needed for compiling
|
|
||||||
double drand48(void) { return rand_get(); }
|
|
||||||
|
|
||||||
KSORT_INIT_GENERIC(float)
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
kvec_t(float) a1;
|
|
||||||
|
|
||||||
kv_init(a1);
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
kv_push(float, a1, rand_get() );
|
|
||||||
}
|
|
||||||
// NOTE: Is-it the right way to do? Seems very low level!
|
|
||||||
ks_introsort_float(n, & kv_A(a1, 0));
|
|
||||||
g_result = kv_A(a1, 0);
|
|
||||||
kv_destroy(a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 50, "Sort",10000000, 0, test_sort, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("KLIB", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
// Needed due to compilation error in pool.h
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "dynamic.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
vector a1, a2;
|
|
||||||
|
|
||||||
vector_construct(&a1, sizeof(unsigned int));
|
|
||||||
vector_construct(&a2, sizeof(unsigned int));
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
unsigned int v = rand_get();
|
|
||||||
vector_push_back(&a1, &v);
|
|
||||||
v = rand_get();
|
|
||||||
vector_push_back(&a2, &v);
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += *(unsigned int*) vector_at(&a1, i) * *(unsigned int*) vector_at(&a2, i);
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
vector_destruct(&a1, NULL);
|
|
||||||
vector_destruct(&a2, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static size_t hash_func (void *a)
|
|
||||||
{
|
|
||||||
return hash_data(a, sizeof (unsigned long));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int equal_func(void *a, void *b)
|
|
||||||
{
|
|
||||||
const unsigned long *pa = a;
|
|
||||||
if (b == NULL) {
|
|
||||||
return *pa == -1U;
|
|
||||||
}
|
|
||||||
const unsigned long *pb = b;
|
|
||||||
return *pa == *pb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_func(void *a, void *b)
|
|
||||||
{
|
|
||||||
unsigned long *pa = a;
|
|
||||||
if (b == NULL) {
|
|
||||||
*pa = -1U;
|
|
||||||
} else {
|
|
||||||
const unsigned long *pb = b;
|
|
||||||
*pa = *pb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct map_element map_element;
|
|
||||||
struct map_element
|
|
||||||
{
|
|
||||||
unsigned long key;
|
|
||||||
unsigned long value;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
map dict;
|
|
||||||
map_construct(&dict, sizeof(map_element), set_func);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
map_insert(&dict, (map_element[]) {{.key = rand_get(), .value = rand_get()}}, hash_func, set_func, equal_func, NULL);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
map_element *p = map_at(&dict, (map_element[]){{.key = rand_get()}}, hash_func, equal_func);
|
|
||||||
if (p)
|
|
||||||
s += p->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
map_destruct(&dict, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef char char_array_t[256];
|
|
||||||
|
|
||||||
static int char_equal (void *a, void *b)
|
|
||||||
{
|
|
||||||
const char_array_t *pa = (const char_array_t *)a;
|
|
||||||
if (b == NULL)
|
|
||||||
return strcmp(*pa, "") == 0;
|
|
||||||
const char_array_t *pb = (const char_array_t *)b;
|
|
||||||
return strcmp(*pa,*pb)==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t char_hash(void *a)
|
|
||||||
{
|
|
||||||
char_array_t *pa = (char_array_t *)a;
|
|
||||||
return hash_string(*pa);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void char_set(void *a, void *b)
|
|
||||||
{
|
|
||||||
char_array_t *pa = (char_array_t *)a;
|
|
||||||
if (b == NULL) {
|
|
||||||
strcpy(*pa, "");
|
|
||||||
} else {
|
|
||||||
const char_array_t *pb = (const char_array_t *)b;
|
|
||||||
strcpy(*pa,*pb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct big_map_element big_map_element;
|
|
||||||
struct big_map_element
|
|
||||||
{
|
|
||||||
char_array_t key;
|
|
||||||
char_array_t value;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
map dict;
|
|
||||||
map_construct(&dict, sizeof(big_map_element), char_set);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
big_map_element el;
|
|
||||||
sprintf(el.key, "%u", rand_get());
|
|
||||||
sprintf(el.value, "%u", rand_get());
|
|
||||||
map_insert(&dict, &el, char_hash, char_set, char_equal, NULL);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
big_map_element el;
|
|
||||||
sprintf(el.key, "%u", rand_get());
|
|
||||||
big_map_element *p = map_at(&dict, &el, char_hash, char_equal);
|
|
||||||
if (p)
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
map_destruct(&dict, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("LIBDYNAMIC", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "liblfds711.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct lfds711_queue_bmm_state g_buff;
|
|
||||||
struct lfds711_queue_bmm_state g_final;
|
|
||||||
|
|
||||||
static void final(void *arg)
|
|
||||||
{
|
|
||||||
size_t *p_n = arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
unsigned long long j, s = 0;
|
|
||||||
LFDS711_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
|
||||||
for(int i = 0; i < n;i++) {
|
|
||||||
void *p;
|
|
||||||
while (0 == lfds711_queue_bmm_dequeue(&g_final, &p, NULL)) { m_thread_yield(); }
|
|
||||||
j = (uintptr_t)p;
|
|
||||||
s += j;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void conso(void *arg)
|
|
||||||
{
|
|
||||||
unsigned int j;
|
|
||||||
size_t *p_n = arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
unsigned long long s = 0;
|
|
||||||
LFDS711_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
|
||||||
for(int i = 0; i < n;i++) {
|
|
||||||
void *p;
|
|
||||||
while (0 == lfds711_queue_bmm_dequeue(&g_buff, &p, NULL)) { m_thread_yield(); }
|
|
||||||
j = (uintptr_t) p;
|
|
||||||
s += j;
|
|
||||||
}
|
|
||||||
while (0 == lfds711_queue_bmm_enqueue(&g_final, (void*)(uintptr_t)s, NULL)) { m_thread_yield(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
static void prod(void *arg)
|
|
||||||
{
|
|
||||||
size_t *p_n = arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
size_t r = n;
|
|
||||||
LFDS711_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
while (0 == lfds711_queue_bmm_enqueue(&g_buff, (void*)(uintptr_t)r, NULL)) { m_thread_yield(); }
|
|
||||||
r = r * 31421U + 6927U;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_queue(size_t n)
|
|
||||||
{
|
|
||||||
const int cpu_count = get_cpu_count();
|
|
||||||
const int prod_count = cpu_count/2;
|
|
||||||
const int conso_count = cpu_count - prod_count;
|
|
||||||
if (cpu_count < 2) {
|
|
||||||
fprintf(stderr, "WARNING: Can not measure Buffer performance.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rand_get();
|
|
||||||
// Init
|
|
||||||
const size_t size = m_core_roundpow2(64*cpu_count);
|
|
||||||
struct lfds711_queue_bmm_element g_buff_elements[size];
|
|
||||||
struct lfds711_queue_bmm_element g_final_elements[size];
|
|
||||||
lfds711_queue_bmm_init_valid_on_current_logical_core(&g_buff, g_buff_elements,
|
|
||||||
size, NULL);
|
|
||||||
lfds711_queue_bmm_init_valid_on_current_logical_core(&g_final, g_final_elements,
|
|
||||||
size, NULL);
|
|
||||||
|
|
||||||
// Create thread
|
|
||||||
m_thread_t idx_p[prod_count];
|
|
||||||
m_thread_t idx_c[conso_count];
|
|
||||||
m_thread_t idx_final;
|
|
||||||
for(int i = 0; i < prod_count; i++) {
|
|
||||||
m_thread_create (idx_p[i], prod, &n);
|
|
||||||
}
|
|
||||||
for(int i = 0; i < conso_count; i++) {
|
|
||||||
m_thread_create (idx_c[i], conso, &n);
|
|
||||||
}
|
|
||||||
size_t n2 = conso_count;
|
|
||||||
m_thread_create(idx_final, final, &n2);
|
|
||||||
|
|
||||||
// Wait for jobs to be done.
|
|
||||||
for(int i = 0; i < prod_count; i++) {
|
|
||||||
m_thread_join(idx_p[i]);
|
|
||||||
}
|
|
||||||
for(int i = 0; i < conso_count; i++) {
|
|
||||||
m_thread_join(idx_c[i]);
|
|
||||||
}
|
|
||||||
m_thread_join(idx_final);
|
|
||||||
|
|
||||||
// Clear & quit
|
|
||||||
lfds711_queue_bmm_cleanup(&g_final, NULL);
|
|
||||||
lfds711_queue_bmm_cleanup(&g_buff, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 60, "Queue MPMC", 1000000, 0, test_queue, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("LIBLFDS", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "svector.h"
|
|
||||||
#include "smap.h"
|
|
||||||
#include "smset.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
srt_vector *a1 = sv_alloc ( sizeof (unsigned int), 16, NULL);
|
|
||||||
srt_vector *a2 = sv_alloc ( sizeof (unsigned int), 16, NULL);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
unsigned int value = rand_get();
|
|
||||||
sv_push(&a1, &value );
|
|
||||||
value = rand_get();
|
|
||||||
sv_push(&a2, &value );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += *(unsigned int*)sv_at(a1, i ) * *(unsigned int *)sv_at(a2, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
sv_free(&a1);
|
|
||||||
sv_free(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
/* There is no 'unsigned long' key in smset */
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static int cmp_float (const void *a, const void *b)
|
|
||||||
{
|
|
||||||
const float *pa=a;
|
|
||||||
const float *pb = b;
|
|
||||||
return (*pa < *pb) ? -1 : *pa > *pb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
srt_vector *a1 = sv_alloc(sizeof(float), 16, cmp_float);
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
unsigned int value = rand_get();
|
|
||||||
sv_push(&a1, &value );
|
|
||||||
}
|
|
||||||
sv_sort(a1);
|
|
||||||
g_result = *(float*)sv_at(a1, 0);
|
|
||||||
sv_free(&a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 50, "sort", 10000000, 0, test_sort, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("LIBSRT", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
-1086
File diff suppressed because it is too large.
Load diff
@@ -1,99 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "nedtrie.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef struct foo_s {
|
|
||||||
NEDTRIE_ENTRY(foo_s) link;
|
|
||||||
unsigned long key;
|
|
||||||
unsigned long value;
|
|
||||||
} foo_t;
|
|
||||||
typedef struct foo_tree_s foo_tree_t;
|
|
||||||
NEDTRIE_HEAD(foo_tree_s, foo_s);
|
|
||||||
|
|
||||||
static inline size_t fookeyfunct(const foo_t *r)
|
|
||||||
{
|
|
||||||
return r->key;
|
|
||||||
}
|
|
||||||
|
|
||||||
NEDTRIE_GENERATE(static, foo_tree_s, foo_s, link, fookeyfunct, NEDTRIE_NOBBLEZEROS(foo_tree_s))
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
foo_tree_t footree;
|
|
||||||
NEDTRIE_INIT(&footree);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
unsigned long val = rand_get();
|
|
||||||
foo_t * p = malloc(sizeof(foo_t));
|
|
||||||
if (p == NULL) abort();
|
|
||||||
p->key = key;
|
|
||||||
p->value = val;
|
|
||||||
NEDTRIE_INSERT(foo_tree_s, &footree, p);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
foo_t key = { .key = rand_get() };
|
|
||||||
foo_t *p = NEDTRIE_FIND(foo_tree_s, &footree, &key);
|
|
||||||
if (p)
|
|
||||||
s += p->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
foo_t *r, *next;
|
|
||||||
NEDTRIE_FOREACH_SAFE(r, foo_tree_s, &footree, next) {
|
|
||||||
// Remove is needed, otherwise it segfault
|
|
||||||
NEDTRIE_REMOVE(foo_tree_s, &footree, r);
|
|
||||||
free(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_noalloc(size_t n)
|
|
||||||
{
|
|
||||||
foo_tree_t footree;
|
|
||||||
NEDTRIE_INIT(&footree);
|
|
||||||
|
|
||||||
foo_t *tab = malloc(n*sizeof(foo_t));
|
|
||||||
if (tab == NULL) abort();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
unsigned long val = rand_get();
|
|
||||||
tab[i].key = key;
|
|
||||||
tab[i].value = val;
|
|
||||||
NEDTRIE_INSERT(foo_tree_s, &footree, &tab[i]);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
foo_t key = { .key = rand_get() };
|
|
||||||
foo_t *p = NEDTRIE_FIND(foo_tree_s, &footree, &key);
|
|
||||||
if (p)
|
|
||||||
s += p->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
free(tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 45, "dict(noalloc)", 1000000, 0, test_dict_noalloc, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("NEDTRIES", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
// Inspired by: http://stackoverflow.com/questions/3664272/is-stdvector-so-much-slower-than-plain-arrays/3664349#3664349
|
|
||||||
|
|
||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#include "m-array.h"
|
|
||||||
#include "m-list.h"
|
|
||||||
#include "m-rbtree.h"
|
|
||||||
#include "m-dict.h"
|
|
||||||
#include "m-algo.h"
|
|
||||||
#include "m-mempool.h"
|
|
||||||
#include "m-string.h"
|
|
||||||
|
|
||||||
unsigned long g_result;
|
|
||||||
|
|
||||||
static unsigned long long
|
|
||||||
cputime (void)
|
|
||||||
{
|
|
||||||
struct rusage rus;
|
|
||||||
getrusage (0, &rus);
|
|
||||||
return rus.ru_utime.tv_sec * 1000000ULL + rus.ru_utime.tv_usec;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Pixel
|
|
||||||
{
|
|
||||||
unsigned char r, g, b;
|
|
||||||
};
|
|
||||||
|
|
||||||
ARRAY_DEF(array_pixel, struct Pixel, (INIT(M_NOTHING_DEFAULT), INIT_SET(M_MEMCPY_DEFAULT) ))
|
|
||||||
|
|
||||||
void UseMlib(void)
|
|
||||||
{
|
|
||||||
unsigned long long t1 = cputime();
|
|
||||||
|
|
||||||
for(int i = 0; i < 1000; ++i)
|
|
||||||
{
|
|
||||||
int dimension = 999;
|
|
||||||
|
|
||||||
array_pixel_t pixels;
|
|
||||||
array_pixel_init(pixels);
|
|
||||||
array_pixel_reserve(pixels, dimension * dimension);
|
|
||||||
|
|
||||||
for(int i = 0; i < dimension * dimension; ++i)
|
|
||||||
{
|
|
||||||
const struct Pixel p = { 255, 0, 0};
|
|
||||||
array_pixel_push_back (pixels, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
array_pixel_clear(pixels);
|
|
||||||
}
|
|
||||||
unsigned long long t2 = cputime();
|
|
||||||
printf ("M*Lib Array: %Lu us\n", (t2-t1)/1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UseNative(void)
|
|
||||||
{
|
|
||||||
unsigned long long t1 = cputime();
|
|
||||||
|
|
||||||
for(int i = 0; i < 1000; ++i)
|
|
||||||
{
|
|
||||||
int dimension = 999;
|
|
||||||
|
|
||||||
struct Pixel * pixels = malloc(sizeof(struct Pixel) * dimension * dimension);
|
|
||||||
|
|
||||||
for(int i = 0 ; i < dimension * dimension; ++i)
|
|
||||||
{
|
|
||||||
pixels[i].r = 255;
|
|
||||||
pixels[i].g = 0;
|
|
||||||
pixels[i].b = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(pixels);
|
|
||||||
}
|
|
||||||
unsigned long long t2 = cputime();
|
|
||||||
printf ("Native Array: %Lu us\n", (t2-t1)/1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
UseNative();
|
|
||||||
UseMlib();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,269 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define POTTERY_VECTOR_PREFIX vec_uint
|
|
||||||
#define POTTERY_VECTOR_VALUE_TYPE unsigned int
|
|
||||||
#define POTTERY_VECTOR_LIFECYCLE_BY_VALUE 1
|
|
||||||
#include "pottery/vector/pottery_vector_static.t.h"
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
vec_uint_t a1, a2;
|
|
||||||
|
|
||||||
vec_uint_init(&a1);
|
|
||||||
vec_uint_init(&a2);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
vec_uint_insert_last(&a1, rand_get() );
|
|
||||||
vec_uint_insert_last(&a2, rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += *vec_uint_at(&a1, i ) * *vec_uint_at(&a2, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
vec_uint_destroy(&a1);
|
|
||||||
vec_uint_destroy(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef struct foo_s {
|
|
||||||
struct foo_s* next;
|
|
||||||
struct foo_s* previous;
|
|
||||||
int data;
|
|
||||||
} foo_t;
|
|
||||||
|
|
||||||
#define POTTERY_DOUBLY_LINKED_LIST_PREFIX foo_list
|
|
||||||
#define POTTERY_DOUBLY_LINKED_LIST_VALUE_TYPE foo_t
|
|
||||||
#include "pottery/doubly_linked_list/pottery_doubly_linked_list_static.t.h"
|
|
||||||
|
|
||||||
static void test_list(size_t n)
|
|
||||||
{
|
|
||||||
foo_list_t a1, a2;
|
|
||||||
foo_list_init(&a1);
|
|
||||||
foo_list_init(&a2);
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
foo_t *tmp = malloc(sizeof (foo_t));
|
|
||||||
if (tmp == NULL) abort();
|
|
||||||
tmp->data = rand_get();
|
|
||||||
foo_list_link_last(&a1, tmp);
|
|
||||||
|
|
||||||
tmp = malloc(sizeof (foo_t));
|
|
||||||
if (tmp == NULL) abort();
|
|
||||||
tmp->data = rand_get();
|
|
||||||
foo_list_link_last(&a2, tmp);
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(foo_t *it1 = foo_list_first(&a1), *it2 = foo_list_first(&a2) ;
|
|
||||||
foo_list_entry_exists(&a1, it1) ;
|
|
||||||
it1 = foo_list_next(&a1, it1), it2 = foo_list_next(&a2, it2)) {
|
|
||||||
s += it1->data * it2->data;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
for(foo_t *it1 = foo_list_first(&a1);
|
|
||||||
foo_list_entry_exists(&a1, it1) ;
|
|
||||||
) {
|
|
||||||
foo_t *tmp = it1;
|
|
||||||
it1 = foo_list_next(&a1, it1);
|
|
||||||
free(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(foo_t *it1 = foo_list_first(&a2);
|
|
||||||
foo_list_entry_exists(&a2, it1) ;
|
|
||||||
) {
|
|
||||||
foo_t *tmp = it1;
|
|
||||||
it1 = foo_list_next(&a2, it1);
|
|
||||||
free(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
// ERROR: it returns the wrong result.
|
|
||||||
#define POTTERY_TREE_MAP_PREFIX set_ulong
|
|
||||||
#define POTTERY_TREE_MAP_VALUE_TYPE unsigned long
|
|
||||||
#define POTTERY_TREE_MAP_LIFECYCLE_MOVE_BY_VALUE 1
|
|
||||||
#define POTTERY_TREE_MAP_COMPARE_THREE_WAY(a,b) ((a) < (b) ? -1 : (a) > (b))
|
|
||||||
#define POTTERY_TREE_MAP_LIFECYCLE_DESTROY(a) (void) a
|
|
||||||
#include "pottery/tree_map/pottery_tree_map_static.t.h"
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
set_ulong_t tree;
|
|
||||||
set_ulong_init(&tree);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
set_ulong_insert(&tree, rand_get() );
|
|
||||||
}
|
|
||||||
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long j = rand_get();
|
|
||||||
if (set_ulong_find(&tree, &j ) != NULL)
|
|
||||||
s += j;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
set_ulong_destroy(&tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#include "m-core.h" // For M_HASH_DEFAULT
|
|
||||||
typedef struct bar_s {
|
|
||||||
unsigned long key;
|
|
||||||
unsigned long value;
|
|
||||||
} bar_t;
|
|
||||||
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_PREFIX map_ulong
|
|
||||||
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_VALUE_TYPE bar_t
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_KEY_TYPE unsigned long
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_REF_KEY(v) v->key
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_KEY_HASH(x) M_HASH_DEFAULT(x)
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_KEY_EQUAL(x, y) x == y
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_LIFECYCLE_MOVE(p,q) memcpy(p, q, sizeof (bar_t))
|
|
||||||
|
|
||||||
#include "pottery/open_hash_map/pottery_open_hash_map_static.t.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
map_ulong_t dict;
|
|
||||||
map_ulong_init(&dict);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long value = rand_get();
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
bar_t * kyle = pottery_null;
|
|
||||||
map_ulong_emplace_key(&dict, key, &kyle, pottery_null);
|
|
||||||
kyle->key = key;
|
|
||||||
kyle->value = value;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
bar_t *kyle = map_ulong_find(&dict, rand_get());
|
|
||||||
if (kyle != NULL)
|
|
||||||
s += kyle->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
map_ulong_destroy(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char a[256];
|
|
||||||
} char_array_t;
|
|
||||||
static inline void char_init (char_array_t *a) { a->a[0] = 0; }
|
|
||||||
static inline void char_set (char_array_t *a, const char_array_t b) { strcpy(a->a, b.a); }
|
|
||||||
static inline bool char_equal_p (const char_array_t a, const char_array_t b) { return strcmp(a.a,b.a)==0; }
|
|
||||||
static inline void char_clear (char_array_t *a) { (void)a; }
|
|
||||||
static inline size_t char_hash(const char_array_t *a) {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = a->a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct bars_s {
|
|
||||||
char_array_t key;
|
|
||||||
char_array_t value;
|
|
||||||
} bars_t;
|
|
||||||
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_PREFIX map_achar
|
|
||||||
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_VALUE_TYPE bars_t
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_KEY_TYPE char_array_t
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_REF_KEY(v) v->key
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_KEY_HASH(x) char_hash(&x)
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_KEY_EQUAL(x, y) char_equal_p(x, y)
|
|
||||||
#define POTTERY_OPEN_HASH_MAP_LIFECYCLE_MOVE(p,q) memcpy(p, q, sizeof (bars_t))
|
|
||||||
|
|
||||||
#include "pottery/open_hash_map/pottery_open_hash_map_static.t.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
map_achar_t dict;
|
|
||||||
map_achar_init(&dict);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
bars_t * kyle = pottery_null;
|
|
||||||
map_achar_emplace_key(&dict, s1, &kyle, pottery_null);
|
|
||||||
char_set(&kyle->key, s1);
|
|
||||||
char_set(&kyle->value, s2);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
bars_t *kyle = map_achar_find(&dict, s1);
|
|
||||||
if (kyle != NULL)
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
map_achar_destroy(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define POTTERY_VECTOR_PREFIX vec_float
|
|
||||||
#define POTTERY_VECTOR_VALUE_TYPE float
|
|
||||||
#define POTTERY_VECTOR_LIFECYCLE_BY_VALUE 1
|
|
||||||
#include "pottery/vector/pottery_vector_static.t.h"
|
|
||||||
|
|
||||||
#define POTTERY_INTRO_SORT_PREFIX sort_float
|
|
||||||
#define POTTERY_INTRO_SORT_VALUE_TYPE float
|
|
||||||
#define POTTERY_INTRO_SORT_LIFECYCLE_MOVE_BY_VALUE 1
|
|
||||||
#define POTTERY_INTRO_SORT_COMPARE_THREE_WAY(x, y) ( *x < *y ? -1 : *x > *y)
|
|
||||||
#include "pottery/intro_sort/pottery_intro_sort_static.t.h"
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
vec_float_t a1;
|
|
||||||
vec_float_init(&a1);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
vec_float_insert_last(&a1, rand_get() );
|
|
||||||
}
|
|
||||||
sort_float(vec_float_at(&a1, 0), n);
|
|
||||||
g_result = *vec_float_at(&a1, 0);
|
|
||||||
vec_float_destroy(&a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 50, "Sort",10000000, 0, test_sort, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("POTTERY", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "qlibc/qlibc.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
qvector_t *a1 = qvector(16, sizeof(unsigned int), QVECTOR_RESIZE_DOUBLE);
|
|
||||||
if (!a1) abort();
|
|
||||||
qvector_t *a2 = qvector(16, sizeof(unsigned int), QVECTOR_RESIZE_DOUBLE);
|
|
||||||
if (!a2) abort();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
unsigned int v = rand_get();
|
|
||||||
bool success = a1->addlast(a1, &v);
|
|
||||||
if (!success) abort();
|
|
||||||
v = rand_get();
|
|
||||||
success = a2->addlast(a2, &v);
|
|
||||||
if (!success) abort();
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += *(unsigned int*)a1->getat(a1, i, false) * *(unsigned int *) a2->getat(a2, i, false);
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
a1->free(a1);
|
|
||||||
a2->free(a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_list (size_t n)
|
|
||||||
{
|
|
||||||
qlist_t *a1 = qlist(0);
|
|
||||||
qlist_t *a2 = qlist(0);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
unsigned int u = rand_get(), v = rand_get();
|
|
||||||
a1->addlast(a1, &u, sizeof(unsigned int));
|
|
||||||
a2->addlast(a2, &v, sizeof(unsigned int));
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
qlist_obj_t it1, it2;
|
|
||||||
memset(&it1, 0, sizeof (it1));
|
|
||||||
memset(&it2, 0, sizeof (it2));
|
|
||||||
while (a1->getnext(a1, &it1, false) == true
|
|
||||||
&& a2->getnext(a2, &it2, false) == true) {
|
|
||||||
s += *(unsigned int*)it1.data * *(unsigned int*)it2.data;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
a1->free(a1);
|
|
||||||
a2->free(a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static int compare(const void *key1, size_t size1,
|
|
||||||
const void *key2, size_t size2)
|
|
||||||
{
|
|
||||||
assert(size1 == sizeof(unsigned long));
|
|
||||||
assert(size2 == sizeof(unsigned long));
|
|
||||||
const unsigned long *pa = key1;
|
|
||||||
const unsigned long *pb = key2;
|
|
||||||
return (*pa < *pb) ? -1 : (*pa > *pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
qtreetbl_t *tree = qtreetbl(0);
|
|
||||||
tree->set_compare(tree, compare);
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long v = rand_get();
|
|
||||||
tree->put_by_obj(tree,
|
|
||||||
&v, sizeof(unsigned long), /* key */
|
|
||||||
&v, sizeof(unsigned long) /* value */ );
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long v = rand_get();
|
|
||||||
void *obj = tree->get_by_obj(tree, (const char*)&v, sizeof(unsigned long), NULL, 0);
|
|
||||||
if (obj)
|
|
||||||
s += *(unsigned long*)obj;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
tree->free(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* qlibc hash functions only accept a string as the key */
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("QLIBC", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <QLinkedList>
|
|
||||||
#include <QVector>
|
|
||||||
#include <QSet>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QHash>
|
|
||||||
#include <QtAlgorithms>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_list(size_t n)
|
|
||||||
{
|
|
||||||
QLinkedList<unsigned int> a1, a2;
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
a1.push_back(rand_get() );
|
|
||||||
a2.push_back(rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (QLinkedList<unsigned int>::const_iterator ci1 = a1.begin(), ci2 = a2.begin (); ci1 != a1.end(); ++ci1, ++ci2) {
|
|
||||||
s += *ci1 * *ci2;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
QVector<unsigned int> a1, a2;
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
a1.push_back(rand_get() );
|
|
||||||
a2.push_back(rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += a1[i] * a2[i];
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
/* NOTE: QSet doesn't perform full ordering. I can't find any container
|
|
||||||
which is a set with total ordering within Qt. So we have to fake it. */
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
QMap<unsigned long, QHashDummyValue> tree;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
tree[rand_get()] = QHashDummyValue();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
QMap<unsigned long, QHashDummyValue>::iterator it = tree.find(rand_get());
|
|
||||||
if (it != tree.end())
|
|
||||||
s += it.key();
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict1(size_t n)
|
|
||||||
{
|
|
||||||
QMap<unsigned long, unsigned long> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
QMap<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it.value();
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
QHash<unsigned long, unsigned long> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
QHash<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it.value();
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
uint qHash(const char_array_s &k)
|
|
||||||
{
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
QHash<char_array_s, char_array_s> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
QHash<char_array_s, char_array_s>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
QVector<float> a1;
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
a1.push_back(rand_get() );
|
|
||||||
}
|
|
||||||
qSort(a1.begin(), a1.end());
|
|
||||||
g_result = a1[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict(m)", 1000000, 0, test_dict1, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42,"dict(u)", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 50, "Sort",10000000, 0, test_sort, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("QT", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
#define RAPIDJSON_HAS_STDSTRING 1
|
|
||||||
|
|
||||||
#include "rapidjson/reader.h"
|
|
||||||
#include "rapidjson/document.h"
|
|
||||||
#include "rapidjson/prettywriter.h"
|
|
||||||
#include "rapidjson/filereadstream.h"
|
|
||||||
#include "rapidjson/filewritestream.h"
|
|
||||||
#include "rapidjson/encodedstream.h"
|
|
||||||
#include "rapidjson/error/en.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
vector<string> vstring;
|
|
||||||
vector<string> vstring2;
|
|
||||||
|
|
||||||
static void
|
|
||||||
bench_vector_string_init(size_t n)
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
char buff[100];
|
|
||||||
snprintf(buff, sizeof(buff), "%zu", i);
|
|
||||||
std::string s(buff);
|
|
||||||
vstring.push_back(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bench_vector_string_init_big(size_t n)
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
char buff[100];
|
|
||||||
snprintf(buff, sizeof(buff), "%zu%zu%zu%zu%zu%zu", i, i, i, i, i, i);
|
|
||||||
std::string s(buff);
|
|
||||||
vstring.push_back(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bench_vector_string_json_run(size_t n)
|
|
||||||
{
|
|
||||||
if (vstring.size() != n) {
|
|
||||||
printf("Size are different!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *f = fopen("tmp-serial.json", "wt");
|
|
||||||
if (!f) abort();
|
|
||||||
{
|
|
||||||
// Prepare writer and output stream.
|
|
||||||
char writeBuffer[65536];
|
|
||||||
typedef rapidjson::AutoUTFOutputStream<unsigned, rapidjson::FileWriteStream> OutputStream;
|
|
||||||
rapidjson::FileWriteStream os(f, writeBuffer, sizeof(writeBuffer));
|
|
||||||
OutputStream eos(os, rapidjson::kUTF8, false);
|
|
||||||
rapidjson::PrettyWriter<OutputStream, rapidjson::UTF8<>, rapidjson::AutoUTF<unsigned> > writer(eos);
|
|
||||||
|
|
||||||
writer.StartArray();
|
|
||||||
for(size_t i = 0; i < n; i++){
|
|
||||||
writer.String(vstring[i]);
|
|
||||||
}
|
|
||||||
writer.EndArray();
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
f = fopen("tmp-serial.json", "rt");
|
|
||||||
if (!f) abort();
|
|
||||||
{
|
|
||||||
char readBuffer[65536];
|
|
||||||
rapidjson::FileReadStream is(f, readBuffer, sizeof(readBuffer));
|
|
||||||
rapidjson::Document d;
|
|
||||||
d.ParseStream(is);
|
|
||||||
for(size_t i = 0; i < d.Size(); i++) {
|
|
||||||
rapidjson::Value& s = d[i];
|
|
||||||
vstring2.push_back(s.GetString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
if (vstring2.size() != n) {
|
|
||||||
printf("Size are different!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bench_vector_string_clear(void)
|
|
||||||
{
|
|
||||||
if (vstring != vstring2) {
|
|
||||||
printf("Array are different!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
vector<unsigned long> vulong;
|
|
||||||
vector<unsigned long> vulong2;
|
|
||||||
|
|
||||||
static void
|
|
||||||
bench_vector_ulong_init(size_t n)
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
vulong.push_back(i*i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bench_vector_ulong_json_run(size_t n)
|
|
||||||
{
|
|
||||||
if (vulong.size() != n) {
|
|
||||||
printf("Size are different!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *f = fopen("tmp-serial.json", "wt");
|
|
||||||
if (!f) abort();
|
|
||||||
{
|
|
||||||
// Prepare writer and output stream.
|
|
||||||
char writeBuffer[65536];
|
|
||||||
typedef rapidjson::AutoUTFOutputStream<unsigned, rapidjson::FileWriteStream> OutputStream;
|
|
||||||
rapidjson::FileWriteStream os(f, writeBuffer, sizeof(writeBuffer));
|
|
||||||
OutputStream eos(os, rapidjson::kUTF8, false);
|
|
||||||
rapidjson::PrettyWriter<OutputStream, rapidjson::UTF8<>, rapidjson::AutoUTF<unsigned> > writer(eos);
|
|
||||||
|
|
||||||
writer.StartArray();
|
|
||||||
for(size_t i = 0; i < n; i++){
|
|
||||||
writer.Int64(vulong[i]);
|
|
||||||
}
|
|
||||||
writer.EndArray();
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
f = fopen("tmp-serial.json", "rt");
|
|
||||||
if (!f) abort();
|
|
||||||
{
|
|
||||||
char readBuffer[65536];
|
|
||||||
rapidjson::FileReadStream is(f, readBuffer, sizeof(readBuffer));
|
|
||||||
rapidjson::Document d;
|
|
||||||
d.ParseStream(is);
|
|
||||||
for(size_t i = 0; i < d.Size(); i++) {
|
|
||||||
rapidjson::Value& s = d[i];
|
|
||||||
vulong2.push_back(s.GetInt64());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
if (vulong2.size() != n) {
|
|
||||||
printf("Size are different!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bench_vector_ulong_clear(void)
|
|
||||||
{
|
|
||||||
if (vulong != vulong2) {
|
|
||||||
printf("Array are different!\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{110, "serial-json STR", 10000000, bench_vector_string_init, bench_vector_string_json_run, bench_vector_string_clear},
|
|
||||||
{111, "serial-json STR.big", 10000000, bench_vector_string_init_big, bench_vector_string_json_run, bench_vector_string_clear},
|
|
||||||
{112, "serial-json INT", 10000000, bench_vector_ulong_init, bench_vector_ulong_json_run, bench_vector_ulong_clear}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("RAPIDJSON", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <iterator>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "rigtorp/HashMap.h"
|
|
||||||
|
|
||||||
using namespace rigtorp;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
// Hash for using unsigned long as lookup key
|
|
||||||
struct UL_Hash {
|
|
||||||
size_t operator()(const unsigned long v) { return v * 7; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Equal comparison for using unsigned long as lookup key
|
|
||||||
struct UL_Equal {
|
|
||||||
bool operator()(const unsigned long lhs, const unsigned long rhs) {
|
|
||||||
return lhs == rhs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
HashMap<unsigned long, unsigned long, UL_Hash, UL_Equal> dict(16, -1UL);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
HashMap<unsigned long, unsigned long, UL_Hash, UL_Equal>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<char_array_s> {
|
|
||||||
std::size_t operator()(const char_array_s &k) const {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BIG_Hash {
|
|
||||||
size_t operator()(const char_array_s v) { return hash<char_array_s>()(v); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BIG_Equal {
|
|
||||||
bool operator()(const char_array_s lhs, const char_array_s rhs) {
|
|
||||||
return lhs == rhs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
char_array_s empty;
|
|
||||||
HashMap<char_array_s, char_array_s, BIG_Hash, BIG_Equal> dict(16, empty);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
HashMap<char_array_s, char_array_s, BIG_Hash, BIG_Equal>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct STR_Hash {
|
|
||||||
size_t operator()(const string v) { return hash<string>()(v); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct STR_Equal {
|
|
||||||
bool operator()(const string lhs, const string rhs) {
|
|
||||||
return lhs == rhs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_str(size_t n)
|
|
||||||
{
|
|
||||||
string empty;
|
|
||||||
HashMap<string, string, STR_Hash, STR_Equal> dict(16, empty);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
string s2 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
HashMap<string, string, STR_Hash, STR_Equal>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42,"dict", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 43, "DictStr", 1000000, 0, test_dict_str, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("RIGTORP-HASHMAP", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include <rigtorp/MPMCQueue.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
rigtorp::MPMCQueue<unsigned int> g_buff(4*64);
|
|
||||||
rigtorp::MPMCQueue<unsigned long long> g_final(4*64);
|
|
||||||
|
|
||||||
static void final(void *arg)
|
|
||||||
{
|
|
||||||
size_t *p_n = (size_t*) arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
unsigned long long j, s = 0;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
g_final.pop(j);
|
|
||||||
s += j;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void conso(void *arg)
|
|
||||||
{
|
|
||||||
unsigned int j;
|
|
||||||
size_t *p_n = (size_t*)arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
unsigned long long s = 0;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
g_buff.pop(j);
|
|
||||||
s += j;
|
|
||||||
}
|
|
||||||
g_final.push(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void prod(void *arg)
|
|
||||||
{
|
|
||||||
size_t *p_n = (size_t*)arg;
|
|
||||||
size_t n = *p_n;
|
|
||||||
size_t r = n;
|
|
||||||
for(unsigned int i = 0; i < n;i++) {
|
|
||||||
g_buff.push(r);
|
|
||||||
r = r * 31421U + 6927U;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_queue(size_t n)
|
|
||||||
{
|
|
||||||
const int cpu_count = get_cpu_count();
|
|
||||||
const int prod_count = cpu_count/2;
|
|
||||||
const int conso_count = cpu_count - prod_count;
|
|
||||||
if (cpu_count < 2) {
|
|
||||||
fprintf(stderr, "WARNING: Can not measure Buffer performance.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rand_get();
|
|
||||||
// Create thread
|
|
||||||
m_thread_t idx_p[prod_count];
|
|
||||||
m_thread_t idx_c[conso_count];
|
|
||||||
m_thread_t idx_final;
|
|
||||||
for(int i = 0; i < prod_count; i++) {
|
|
||||||
m_thread_create (idx_p[i], prod, &n);
|
|
||||||
}
|
|
||||||
for(int i = 0; i < conso_count; i++) {
|
|
||||||
m_thread_create (idx_c[i], conso, &n);
|
|
||||||
}
|
|
||||||
size_t n2 = conso_count;
|
|
||||||
m_thread_create(idx_final, final, &n2);
|
|
||||||
|
|
||||||
// Wait for jobs to be done.
|
|
||||||
for(int i = 0; i < prod_count; i++) {
|
|
||||||
m_thread_join(idx_p[i]);
|
|
||||||
}
|
|
||||||
for(int i = 0; i < conso_count; i++) {
|
|
||||||
m_thread_join(idx_c[i]);
|
|
||||||
}
|
|
||||||
m_thread_join(idx_final);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 60, "Queue MPMC", 1000000, 0, test_queue, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("RIGTORP-MPMC-QUEUE", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <iterator>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <sparsepp/spp.h>
|
|
||||||
|
|
||||||
using spp::sparse_hash_map;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
sparse_hash_map<unsigned long, unsigned long> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
sparse_hash_map<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<char_array_s> {
|
|
||||||
std::size_t operator()(const char_array_s &k) const {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
sparse_hash_map<char_array_s, char_array_s> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sparse_hash_map<char_array_s, char_array_s>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static void
|
|
||||||
test_dict_str(size_t n)
|
|
||||||
{
|
|
||||||
sparse_hash_map<string, string> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
string s2 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = static_cast<ostringstream*>( &(ostringstream() << rand_get()) )->str();
|
|
||||||
sparse_hash_map<string, string>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42,"dict", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 43, "DictStr", 1000000, 0, test_dict_str, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("SPARSEPP", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define i_val unsigned int
|
|
||||||
#define i_tag uint
|
|
||||||
#include <stc/cvec.h>
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
cvec_uint a1 = cvec_uint_init(), a2 = cvec_uint_init();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
cvec_uint_push_back(&a1, rand_get() );
|
|
||||||
cvec_uint_push_back(&a2, rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += *cvec_uint_at(&a1, i ) * *cvec_uint_at(&a2, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
cvec_uint_drop(&a1);
|
|
||||||
cvec_uint_drop(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
#define i_val unsigned int
|
|
||||||
#define i_tag uint
|
|
||||||
#include <stc/clist.h>
|
|
||||||
|
|
||||||
static void test_list(size_t n)
|
|
||||||
{
|
|
||||||
clist_uint a1 = clist_uint_init(), a2 = clist_uint_init();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
clist_uint_push_front(&a1, rand_get() );
|
|
||||||
clist_uint_push_front(&a2, rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(clist_uint_iter it1 = clist_uint_begin(&a1), it2 = clist_uint_begin(&a2) ;
|
|
||||||
it1.ref != clist_uint_end(&a1).ref ;
|
|
||||||
clist_uint_next(&it1), clist_uint_next(&it2) ) {
|
|
||||||
s += *it1.ref * *it2.ref;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
clist_uint_drop(&a1);
|
|
||||||
clist_uint_drop(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define i_tag ulong
|
|
||||||
#define i_key unsigned long
|
|
||||||
#include <stc/csset.h>
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
csset_ulong tree = csset_ulong_init();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
csset_ulong_insert(&tree, rand_get() );
|
|
||||||
}
|
|
||||||
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long j = rand_get();
|
|
||||||
if (csset_ulong_get(&tree, j ) != NULL)
|
|
||||||
s+= j;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
csset_ulong_drop(&tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define i_tag ulong
|
|
||||||
#define i_key unsigned long
|
|
||||||
#define i_val unsigned long
|
|
||||||
#include <stc/cmap.h>
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
cmap_ulong dict = cmap_ulong_init();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long value = rand_get();
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
cmap_ulong_insert_or_assign(&dict, key, value);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
const cmap_ulong_value*val = cmap_ulong_get(&dict, rand_get());
|
|
||||||
if (val != NULL)
|
|
||||||
s += val->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
cmap_ulong_drop(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char a[256];
|
|
||||||
} char_array_t;
|
|
||||||
static inline void char_init (char_array_t *a) { a->a[0] = 0; }
|
|
||||||
static inline void char_set (char_array_t *a, const char_array_t b) { strcpy(a->a, b.a); }
|
|
||||||
static inline bool char_equal_p (const char_array_t *a, const char_array_t *b) { return strcmp(a->a,b->a)==0; }
|
|
||||||
static inline void char_clear (char_array_t *a) { (void)a; }
|
|
||||||
static inline size_t char_hash(const char_array_t *a) {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = a->a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define i_tag achar
|
|
||||||
#define i_key char_array_t
|
|
||||||
#define i_val char_array_t
|
|
||||||
#define i_hash char_hash
|
|
||||||
#define i_eq char_equal_p
|
|
||||||
#include <stc/cmap.h>
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
cmap_achar dict = cmap_achar_init();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
cmap_achar_insert_or_assign(&dict, s1, s2);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
const cmap_achar_value*val = cmap_achar_get(&dict, s1);
|
|
||||||
if (val != NULL)
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
cmap_achar_drop(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#define i_val float
|
|
||||||
#define i_tag float
|
|
||||||
#include <stc/cvec.h>
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
cvec_float a1 = cvec_float_init();
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
cvec_float_push_back(&a1, rand_get() );
|
|
||||||
}
|
|
||||||
cvec_float_sort(&a1);
|
|
||||||
g_result = *cvec_float_at(&a1, 0);
|
|
||||||
cvec_float_drop(&a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 50, "Sort",10000000, 0, test_sort, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("STC", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,278 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <deque>
|
|
||||||
#include <list>
|
|
||||||
#include <iterator>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_list(size_t n)
|
|
||||||
{
|
|
||||||
list<unsigned int> a1, a2;
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
a1.push_back(rand_get() );
|
|
||||||
a2.push_back(rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (list<unsigned int>::const_iterator ci1 = a1.begin(), ci2 = a2.begin (); ci1 != a1.end(); ++ci1, ++ci2) {
|
|
||||||
s += *ci1 * *ci2;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
vector<unsigned int> a1, a2;
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
a1.push_back(rand_get() );
|
|
||||||
a2.push_back(rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += a1[i] * a2[i];
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_deque(size_t n)
|
|
||||||
{
|
|
||||||
deque<unsigned int> a1, a2;
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
a1.push_back(rand_get() );
|
|
||||||
a2.push_back(rand_get() );
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(auto it1 = a1.cbegin(), it2 = a2.cbegin();
|
|
||||||
it1 != a1.cend() ;it1++, it2++) {
|
|
||||||
s += *it1 * *it2;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
set<unsigned long> tree;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
tree.insert(rand_get());
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
set<unsigned long>::iterator it = tree.find(rand_get());
|
|
||||||
if (it != tree.end())
|
|
||||||
s += *it;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict1(size_t n)
|
|
||||||
{
|
|
||||||
map<unsigned long, unsigned long> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
map<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2(size_t n)
|
|
||||||
{
|
|
||||||
unordered_map<unsigned long, unsigned long> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[rand_get()] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unordered_map<unsigned long, unsigned long>::iterator it = dict.find(rand_get());
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict2_linear(size_t n)
|
|
||||||
{
|
|
||||||
unordered_map<unsigned long, unsigned long> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
dict[i] = rand_get();
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unordered_map<unsigned long, unsigned long>::iterator it = dict.find(i);
|
|
||||||
if (it != dict.end())
|
|
||||||
s += it->second;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct char_array_s {
|
|
||||||
char a[256];
|
|
||||||
char_array_s () { a[0] = 0 ; }
|
|
||||||
char_array_s ( const char_array_s & other) { strcpy(a, other.a); }
|
|
||||||
bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<char_array_s> {
|
|
||||||
std::size_t operator()(const char_array_s &k) const {
|
|
||||||
size_t hash = 0;
|
|
||||||
const char *s = k.a;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
unordered_map<char_array_s, char_array_s> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1, s2;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_s s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
unordered_map<char_array_s, char_array_s>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
static void
|
|
||||||
test_dict_str(size_t n)
|
|
||||||
{
|
|
||||||
unordered_map<string, string> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = to_string(rand_get());
|
|
||||||
string s2 = to_string(rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = to_string (rand_get());
|
|
||||||
unordered_map<string, string>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_str2(size_t n)
|
|
||||||
{
|
|
||||||
map<string, string> dict;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = to_string(rand_get());
|
|
||||||
string s2 = to_string(rand_get());
|
|
||||||
dict[s1] = s2;
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
string s1 = to_string(rand_get());
|
|
||||||
map<string, string>::iterator it = dict.find(s1);
|
|
||||||
if (it != dict.end())
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
vector<float> a1;
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
a1.push_back(rand_get() );
|
|
||||||
}
|
|
||||||
sort(a1.begin(), a1.end());
|
|
||||||
g_result = a1[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_stable_sort(size_t n)
|
|
||||||
{
|
|
||||||
vector<float> a1;
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
a1.push_back(rand_get() );
|
|
||||||
}
|
|
||||||
stable_sort(a1.begin(), a1.end());
|
|
||||||
g_result = a1[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 21, "Deque", 100000000, 0, test_deque, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict(m)", 1000000, 0, test_dict1, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 42,"dict(u)", 1000000, 0, test_dict2, 0},
|
|
||||||
{ 43,"DictStr(u)", 1000000, 0, test_dict_str, 0},
|
|
||||||
{ 44,"DictStr(m)", 1000000, 0, test_dict_str2, 0},
|
|
||||||
{ 46, "dictLinear(u)", 1000000, 0, test_dict2_linear, 0},
|
|
||||||
{ 50, "Sort",10000000, 0, test_sort, 0},
|
|
||||||
{ 51, "Stable Sort",10000000, 0, test_stable_sort, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("STL", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,323 +0,0 @@
|
|||||||
/*
|
|
||||||
* M*LIB - String Bench
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017-2024, Patrick Pelissier
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* + Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* + Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#define M_USE_SMALL_NAME 0
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include "m-string.h"
|
|
||||||
|
|
||||||
#ifdef BENCH_CAN_USE_SDS
|
|
||||||
extern "C" {
|
|
||||||
#include "sds.h"
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BENCH_CAN_USE_BSTRLIB
|
|
||||||
#include "bstrlib.h"
|
|
||||||
#include "bstrwrap.h"
|
|
||||||
#include "bstraux.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(BENCH_CAN_USE_POTTERY)
|
|
||||||
#include "pottery/string/string.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BENCH
|
|
||||||
* 2000000
|
|
||||||
* 1. Generate N strings of random numbers 32 bits.
|
|
||||||
* 2. Concat all strings in a string usigned a random permutation of N.
|
|
||||||
* 3. Replace "1234" in the string into "WELL" until nothing remains.
|
|
||||||
* 4. Replace "56789" in the string into "DONE" until nothing remains.
|
|
||||||
* Return the final string length.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned *permutation_tab = NULL;
|
|
||||||
|
|
||||||
void random_permutation(unsigned n)
|
|
||||||
{
|
|
||||||
if (permutation_tab) free(permutation_tab);
|
|
||||||
permutation_tab = (unsigned *) malloc(n * sizeof(unsigned));
|
|
||||||
if (permutation_tab == NULL) abort();
|
|
||||||
for(unsigned i = 0; i < n; i++)
|
|
||||||
permutation_tab[i] = i;
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
unsigned j = rand_get() % n;
|
|
||||||
unsigned k = rand_get() % n;
|
|
||||||
unsigned l = permutation_tab[j];
|
|
||||||
permutation_tab[j] = permutation_tab[k];
|
|
||||||
permutation_tab[k] = l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static void replace_all_stl(string &str, const char pattern[], const char replace[])
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
do {
|
|
||||||
pos = str.find(pattern, pos);
|
|
||||||
if (pos != string::npos) {
|
|
||||||
str.replace (pos, strlen(pattern), replace);
|
|
||||||
}
|
|
||||||
} while (pos != string::npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t bench_stl(unsigned n)
|
|
||||||
{
|
|
||||||
vector<string> tab;
|
|
||||||
tab.resize(n);
|
|
||||||
for(unsigned i = 0; i < n; i++)
|
|
||||||
tab[i] = to_string(rand_get());
|
|
||||||
|
|
||||||
string str;
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
str += tab[permutation_tab[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
replace_all_stl(str, "1234", "WELL");
|
|
||||||
replace_all_stl(str, "56789", "DONE");
|
|
||||||
|
|
||||||
return str.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t bench_mlib(unsigned n)
|
|
||||||
{
|
|
||||||
m_string_t *tab = (m_string_t*) malloc (n * sizeof (m_string_t));
|
|
||||||
assert (tab != 0);
|
|
||||||
// P1
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
m_string_init(tab[i]);
|
|
||||||
m_string_set_ui(tab[i], rand_get());
|
|
||||||
}
|
|
||||||
// P2
|
|
||||||
m_string_t str;
|
|
||||||
m_string_init(str);
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
m_string_cat(str, tab[permutation_tab[i]]);
|
|
||||||
}
|
|
||||||
// P3
|
|
||||||
m_string_replace_all_cstr(str, "1234", "WELL");
|
|
||||||
m_string_replace_all_cstr(str, "56789", "DONE");
|
|
||||||
size_t length = m_string_size(str);
|
|
||||||
|
|
||||||
// Clean
|
|
||||||
m_string_clear(str);
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
m_string_clear(tab[i]);
|
|
||||||
}
|
|
||||||
free(tab);
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef BENCH_CAN_USE_BSTRLIB
|
|
||||||
|
|
||||||
static void replace_all_bstrlib(CBString &str, const char pattern[], const char replace[])
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
do {
|
|
||||||
pos = str.find(pattern, pos);
|
|
||||||
if (pos != string::npos) {
|
|
||||||
str.replace (pos, strlen(pattern), replace);
|
|
||||||
}
|
|
||||||
} while (pos != string::npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t bench_bstrlib(unsigned n)
|
|
||||||
{
|
|
||||||
vector<CBString> tab;
|
|
||||||
tab.resize(n);
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
char tmp[10];
|
|
||||||
sprintf(tmp, "%u", rand_get());
|
|
||||||
tab[i] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBString str;
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
str += tab[permutation_tab[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
replace_all_bstrlib(str, "1234", "WELL");
|
|
||||||
replace_all_bstrlib(str, "56789", "DONE");
|
|
||||||
|
|
||||||
return str.length();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BENCH_CAN_USE_SDS
|
|
||||||
sds SDS_replace_at(sds str, size_t pos, size_t len, const char str2[])
|
|
||||||
{
|
|
||||||
// simple implementation as replace is not available
|
|
||||||
sds a = sdsnewlen((const void*) str, pos);
|
|
||||||
a = sdscat(a, str2);
|
|
||||||
a = sdscat(a, &str[pos+len]);
|
|
||||||
sdsfree(str);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
sds replace_all_sds(sds str, const char pattern[], const char replace[])
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
do {
|
|
||||||
char *p = strstr(&str[pos], pattern);
|
|
||||||
pos = p == NULL ? -1U : (p - str);
|
|
||||||
if (pos != -1U) {
|
|
||||||
str = SDS_replace_at(str, pos, strlen(pattern), replace);
|
|
||||||
}
|
|
||||||
} while (pos != -1U);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t bench_sds(unsigned n)
|
|
||||||
{
|
|
||||||
sds *tab = (sds*) malloc (n * sizeof (sds));
|
|
||||||
assert (tab != 0);
|
|
||||||
// P1
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
tab[i] = sdsfromlonglong(rand_get());
|
|
||||||
}
|
|
||||||
// P2
|
|
||||||
sds str = sdsempty();
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
str = sdscat(str, tab[permutation_tab[i]]);
|
|
||||||
}
|
|
||||||
// P3
|
|
||||||
str = replace_all_sds(str, "1234", "WELL");
|
|
||||||
str = replace_all_sds(str, "56789", "DONE");
|
|
||||||
// Clean
|
|
||||||
size_t length = sdslen(str);
|
|
||||||
sdsfree(str);
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
sdsfree(tab[i]);
|
|
||||||
}
|
|
||||||
free(tab);
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(BENCH_CAN_USE_POTTERY)
|
|
||||||
|
|
||||||
size_t pottery_find_cstr(string_t *b, size_t index, const char *pattern)
|
|
||||||
{
|
|
||||||
// I cannot find such function in the API
|
|
||||||
const char *s = string_cstr(b);
|
|
||||||
const char *r = strstr(&s[index], pattern);
|
|
||||||
return r == NULL ? SIZE_MAX : r - s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pottery_replace_all_str(string_t *str, const char *s, const char *d)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
while (true) {
|
|
||||||
i = pottery_find_cstr(str, i, s);
|
|
||||||
if (i==SIZE_MAX) return;
|
|
||||||
string_remove(str, i, strlen(s));
|
|
||||||
string_insert_cstr(str, i, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t bench_pottery(unsigned n)
|
|
||||||
{
|
|
||||||
string_t *tab = (string_t*) malloc (n * sizeof (string_t));
|
|
||||||
assert (tab != 0);
|
|
||||||
// P1
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
string_init(&tab[i]);
|
|
||||||
string_append_format(&tab[i], "%u", rand_get());
|
|
||||||
}
|
|
||||||
// P2
|
|
||||||
string_t str;
|
|
||||||
string_init(&str);
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
string_append_string(&str, &tab[permutation_tab[i]]);
|
|
||||||
}
|
|
||||||
// P3
|
|
||||||
|
|
||||||
pottery_replace_all_str(&str, "1234", "WELL");
|
|
||||||
pottery_replace_all_str(&str, "56789", "DONE");
|
|
||||||
size_t length = string_length(&str);
|
|
||||||
|
|
||||||
// Clean
|
|
||||||
string_clear(&str);
|
|
||||||
for(unsigned i = 0; i < n; i++) {
|
|
||||||
string_clear(&tab[i]);
|
|
||||||
}
|
|
||||||
free(tab);
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
unsigned length, n = atoi(argv[1]);
|
|
||||||
unsigned select = atoi(argv[2]);
|
|
||||||
const char *name;
|
|
||||||
random_permutation(n);
|
|
||||||
rand_init();
|
|
||||||
unsigned long long t0 = cputime();
|
|
||||||
|
|
||||||
switch (select) {
|
|
||||||
case 0:
|
|
||||||
length = bench_mlib(n);
|
|
||||||
name = "MLIB";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
length = bench_stl(n);
|
|
||||||
name = "STL";
|
|
||||||
break;
|
|
||||||
#ifdef BENCH_CAN_USE_SDS
|
|
||||||
case 2:
|
|
||||||
length = bench_sds(n);
|
|
||||||
name = "SDS";
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef BENCH_CAN_USE_BSTRLIB
|
|
||||||
case 4:
|
|
||||||
length = bench_bstrlib(n);
|
|
||||||
name = "BSTRLIB";
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if defined(BENCH_CAN_USE_POTTERY)
|
|
||||||
case 5:
|
|
||||||
length = bench_pottery(n);
|
|
||||||
name = "POTTERY";
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
unsigned long long t1 = cputime();
|
|
||||||
printf("%5.5s LENGTH=%u T= %f s\n", name, length, (t1-t0) / 1000000.0 );
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -1,221 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "tommyds/tommy.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
tommy_array a1, a2;
|
|
||||||
|
|
||||||
tommy_array_init(&a1);
|
|
||||||
tommy_array_init(&a2);
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
unsigned int v = rand_get();
|
|
||||||
tommy_array_insert(&a1, (void*)(uintptr_t) v);
|
|
||||||
v = rand_get();
|
|
||||||
tommy_array_insert(&a2, (void*)(uintptr_t) v);
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += (uintptr_t) *tommy_array_ref(&a1, i) * (uintptr_t) *tommy_array_ref(&a2, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
tommy_array_done(&a1);
|
|
||||||
tommy_array_done(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct list_node_s {
|
|
||||||
unsigned int value;
|
|
||||||
tommy_node node;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void test_list (size_t n)
|
|
||||||
{
|
|
||||||
tommy_list a1, a2;
|
|
||||||
|
|
||||||
tommy_list_init(&a1);
|
|
||||||
tommy_list_init(&a2);
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
struct list_node_s *obj;
|
|
||||||
obj = malloc(sizeof(struct list_node_s));
|
|
||||||
if (obj == NULL) abort();
|
|
||||||
obj->value = rand_get();
|
|
||||||
tommy_list_insert_tail(&a1, &obj->node, obj);
|
|
||||||
obj = malloc(sizeof(struct list_node_s));
|
|
||||||
if (obj == NULL) abort();
|
|
||||||
obj->value = rand_get();
|
|
||||||
tommy_list_insert_tail(&a2, &obj->node, obj);
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(tommy_node *it1 = tommy_list_head(&a1), *it2 = tommy_list_head(&a2)
|
|
||||||
; it1 != NULL; it1 = it1->next, it2 = it2->next ) {
|
|
||||||
struct list_node_s *obj1 = it1->data, *obj2 = it2->data;
|
|
||||||
s += obj1->value * obj2->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
tommy_list_foreach(&a1, free);
|
|
||||||
tommy_list_foreach(&a2, free);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct tree_node_s {
|
|
||||||
unsigned long value;
|
|
||||||
tommy_tree_node node;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
static int compare(const void *a, const void *b)
|
|
||||||
{
|
|
||||||
const struct tree_node_s *pa = a;
|
|
||||||
const struct tree_node_s *pb = b;
|
|
||||||
return (pa->value < pb->value) ? -1 : (pa->value > pb->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rbtree(size_t n)
|
|
||||||
{
|
|
||||||
tommy_tree tree;
|
|
||||||
tommy_tree_init(&tree, compare);
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
struct tree_node_s *obj = malloc(sizeof(struct tree_node_s));
|
|
||||||
if (obj == NULL) abort();
|
|
||||||
obj->value = rand_get();
|
|
||||||
tommy_tree_insert(&tree, &obj->node, obj);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
struct tree_node_s key = { .value = rand_get() };
|
|
||||||
struct tree_node_s *obj = tommy_tree_search (&tree, &key);
|
|
||||||
if (obj)
|
|
||||||
s += obj->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
tommy_tree_foreach(&tree, free);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct hash_i_node_s {
|
|
||||||
unsigned long key;
|
|
||||||
unsigned long value;
|
|
||||||
tommy_node node;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline size_t hash_func (const unsigned long key)
|
|
||||||
{
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int equal_func(const void* arg, const void *obj_p)
|
|
||||||
{
|
|
||||||
const struct hash_i_node_s *obj = obj_p;
|
|
||||||
const unsigned long *key = arg;
|
|
||||||
return *key != obj->key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
tommy_hashlin dict;
|
|
||||||
tommy_hashlin_init(&dict);
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
struct hash_i_node_s *obj = malloc(sizeof (struct hash_i_node_s));
|
|
||||||
if(!obj) abort();
|
|
||||||
obj->key = rand_get();
|
|
||||||
obj->value = rand_get();
|
|
||||||
tommy_hashlin_insert(&dict, &obj->node, obj, hash_func(obj->key));
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
struct hash_i_node_s *obj = tommy_hashlin_search(&dict, &equal_func,
|
|
||||||
&key,
|
|
||||||
hash_func(key));
|
|
||||||
if (obj)
|
|
||||||
s += obj->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
tommy_hashlin_done(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef char char_array_t[256];
|
|
||||||
|
|
||||||
struct hash_b_node_s {
|
|
||||||
char_array_t key;
|
|
||||||
char_array_t value;
|
|
||||||
tommy_node node;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int char_equal (const void *arg, const void *obj_p)
|
|
||||||
{
|
|
||||||
const struct hash_b_node_s *obj = obj_p;
|
|
||||||
const char_array_t *key = (const char_array_t *)arg;
|
|
||||||
return strcmp(*key, (obj->key));
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t char_hash(const char *s)
|
|
||||||
{
|
|
||||||
size_t hash = 0;
|
|
||||||
while (*s) hash = hash * 31421 + (*s++) + 6927;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
tommy_hashlin dict;
|
|
||||||
tommy_hashlin_init(&dict);
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
struct hash_b_node_s *obj = malloc(sizeof (struct hash_b_node_s));
|
|
||||||
if(!obj) abort();
|
|
||||||
sprintf(obj->key, "%u", rand_get());
|
|
||||||
sprintf(obj->value, "%u", rand_get());
|
|
||||||
/* NOTE: this is not an insert_or_replace func...
|
|
||||||
It will always insert a new node, even if the key already exists...
|
|
||||||
Maybe searching then inserting will be a better representative?
|
|
||||||
*/
|
|
||||||
tommy_hashlin_insert(&dict, &obj->node, obj, char_hash(obj->key));
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t s1;
|
|
||||||
sprintf(s1, "%u", rand_get());
|
|
||||||
struct hash_b_node_s *obj = tommy_hashlin_search(&dict, &char_equal,
|
|
||||||
&s1,
|
|
||||||
char_hash(s1));
|
|
||||||
if (obj)
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
tommy_hashlin_done(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 30, "Rbtree", 1000000, 0, test_rbtree, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("TommyDS", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "include/uthash.h"
|
|
||||||
#include "include/utarray.h"
|
|
||||||
#include "include/utlist.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static const UT_icd int_icd = {
|
|
||||||
.sz = sizeof (unsigned int),
|
|
||||||
.init = NULL,
|
|
||||||
.dtor = NULL,
|
|
||||||
.copy = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static void test_array(size_t n)
|
|
||||||
{
|
|
||||||
UT_array a1, a2;
|
|
||||||
|
|
||||||
utarray_init(&a1, &int_icd);
|
|
||||||
utarray_init(&a2, &int_icd);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
unsigned int v1 = rand_get(), v2 = rand_get();
|
|
||||||
utarray_push_back(&a1, &v1);
|
|
||||||
utarray_push_back(&a2, &v2);
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(unsigned long i = 0; i < n; i++) {
|
|
||||||
s += *(unsigned long *) utarray_eltptr(&a1, i ) * *(unsigned long *)utarray_eltptr(&a2, i );
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
utarray_done(&a1);
|
|
||||||
utarray_done(&a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct list_node_s {
|
|
||||||
unsigned int value;
|
|
||||||
struct list_node_s *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void test_list (size_t n)
|
|
||||||
{
|
|
||||||
struct list_node_s *a1 = NULL, *a2 = NULL;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
struct list_node_s *p = malloc(sizeof(struct list_node_s));
|
|
||||||
if (!p) abort();
|
|
||||||
p->value = rand_get();
|
|
||||||
LL_PREPEND(a1, p);
|
|
||||||
p = malloc(sizeof(struct list_node_s));
|
|
||||||
if (!p) abort();
|
|
||||||
p->value = rand_get();
|
|
||||||
LL_PREPEND(a2, p);
|
|
||||||
}
|
|
||||||
unsigned int s = 0;
|
|
||||||
for(struct list_node_s *it1 = a1, *it2 = a2
|
|
||||||
; it1 != NULL
|
|
||||||
; it1 = it1->next, it2 = it2->next) {
|
|
||||||
s += it1->value * it2->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
struct list_node_s *el;
|
|
||||||
LL_FOREACH(a1, el) free(el);
|
|
||||||
LL_FOREACH(a2, el) free(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
struct hash_i_node_s {
|
|
||||||
unsigned long key;
|
|
||||||
unsigned long value;
|
|
||||||
UT_hash_handle hh;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
struct hash_i_node_s *dict = NULL;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long k = rand_get();
|
|
||||||
struct hash_i_node_s *s;
|
|
||||||
HASH_FIND(hh, dict, &k, sizeof (unsigned long), s);
|
|
||||||
if (s == NULL) {
|
|
||||||
s = malloc(sizeof(struct hash_i_node_s));
|
|
||||||
if (!s) abort();
|
|
||||||
s->key = k;
|
|
||||||
s->value = rand_get();
|
|
||||||
HASH_ADD(hh, dict, key, sizeof(unsigned long), s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long k = rand_get();
|
|
||||||
struct hash_i_node_s *sp;
|
|
||||||
HASH_FIND(hh, dict, &k, sizeof (unsigned long), sp);
|
|
||||||
if (sp != NULL)
|
|
||||||
s += sp->value;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
struct hash_i_node_s *current, *tmp;
|
|
||||||
HASH_ITER(hh, dict, current, tmp) {
|
|
||||||
HASH_DEL(dict,current); /* delete it (users advances to next) */
|
|
||||||
free(current); /* free it */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char a[256];
|
|
||||||
} char_array_t;
|
|
||||||
|
|
||||||
struct hash_b_node_s {
|
|
||||||
char_array_t key;
|
|
||||||
char_array_t value;
|
|
||||||
UT_hash_handle hh;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
struct hash_b_node_s *dict = NULL;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t k;
|
|
||||||
sprintf(k.a, "%u", rand_get());
|
|
||||||
struct hash_b_node_s *s;
|
|
||||||
HASH_FIND(hh, dict, &k, sizeof (char_array_t), s);
|
|
||||||
if (s == NULL) {
|
|
||||||
s = malloc(sizeof(struct hash_b_node_s));
|
|
||||||
if (!s) abort();
|
|
||||||
memcpy(s->key.a, k.a, sizeof(s->key));
|
|
||||||
sprintf(s->value.a, "%u", rand_get());
|
|
||||||
HASH_ADD(hh, dict, key, sizeof(char_array_t), s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_array_t k;
|
|
||||||
sprintf(k.a, "%u", rand_get());
|
|
||||||
struct hash_b_node_s *sp;
|
|
||||||
HASH_FIND(hh, dict, &k, sizeof (char_array_t), sp);
|
|
||||||
if (sp != NULL)
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
struct hash_b_node_s *current, *tmp;
|
|
||||||
HASH_ITER(hh, dict, current, tmp) {
|
|
||||||
HASH_DEL(dict,current); /* delete it (users advances to next) */
|
|
||||||
free(current); /* free it */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
static const UT_icd float_icd = {
|
|
||||||
.sz = sizeof (float),
|
|
||||||
.init = NULL,
|
|
||||||
.dtor = NULL,
|
|
||||||
.copy = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static int cmp(const void *a1, const void *a2)
|
|
||||||
{
|
|
||||||
const float *f1 = a1;
|
|
||||||
const float *f2 = a2;
|
|
||||||
return (*f1 < *f2) ? -1 : (*f1 > *f2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_sort(size_t n)
|
|
||||||
{
|
|
||||||
UT_array a1;
|
|
||||||
|
|
||||||
utarray_init(&a1, &float_icd);
|
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
float v1 = rand_get();
|
|
||||||
utarray_push_back(&a1, &v1);
|
|
||||||
}
|
|
||||||
utarray_sort(&a1, cmp);
|
|
||||||
g_result = *(float *)utarray_eltptr(&a1, 0);
|
|
||||||
utarray_done(&a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 10, "List", 10000000, 0, test_list, 0},
|
|
||||||
{ 20, "Array", 100000000, 0, test_array, 0},
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
{ 50, "sort", 10000000, 0, test_sort, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("UT-HASH", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "m-core.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#define NAME umap_ulong
|
|
||||||
#define KEY_TY unsigned long
|
|
||||||
#define VAL_TY unsigned long
|
|
||||||
#include "verstable.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict(size_t n)
|
|
||||||
{
|
|
||||||
umap_ulong dict;
|
|
||||||
umap_ulong_init(&dict);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
unsigned long value = rand_get();
|
|
||||||
unsigned long key = rand_get();
|
|
||||||
umap_ulong_insert(&dict, key, value);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
umap_ulong_itr it = umap_ulong_get(&dict, rand_get());
|
|
||||||
if (!umap_ulong_is_end(it) )
|
|
||||||
s += it.data->val;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
umap_ulong_cleanup(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef CHAR_ARRAY_SIZE
|
|
||||||
#define CHAR_ARRAY_SIZE 256
|
|
||||||
#endif
|
|
||||||
typedef char char_array_t[CHAR_ARRAY_SIZE];
|
|
||||||
typedef struct { char_array_t a; } char_encap;// Cannot use char_array_t directly
|
|
||||||
static bool char_equal_p (const char_encap a, const char_encap b) { return strcmp(a.a,b.a)==0; }
|
|
||||||
static size_t char_hash(const char_encap a) { return m_core_hash (a.a, strlen(a.a)); }
|
|
||||||
|
|
||||||
#define NAME umap_char_array
|
|
||||||
#define KEY_TY char_encap
|
|
||||||
#define VAL_TY char_encap
|
|
||||||
#define HASH_FN char_hash
|
|
||||||
#define CMPR_FN char_equal_p
|
|
||||||
#include "verstable.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_dict_big(size_t n)
|
|
||||||
{
|
|
||||||
umap_char_array dict;
|
|
||||||
umap_char_array_init(&dict);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_encap s1, s2;
|
|
||||||
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
sprintf(s2.a, "%u", rand_get());
|
|
||||||
umap_char_array_insert(&dict, s1, s2);
|
|
||||||
}
|
|
||||||
rand_init();
|
|
||||||
unsigned int s = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
char_encap s1;
|
|
||||||
sprintf(s1.a, "%u", rand_get());
|
|
||||||
umap_char_array_itr it = umap_char_array_get(&dict, s1);
|
|
||||||
if (!umap_char_array_is_end(it) )
|
|
||||||
s ++;
|
|
||||||
}
|
|
||||||
g_result = s;
|
|
||||||
|
|
||||||
umap_char_array_cleanup(&dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 40, "dict", 1000000, 0, test_dict, 0},
|
|
||||||
{ 41, "dictBig", 1000000, 0, test_dict_big, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("CTL", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
#define NDEBUG
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "xxhash.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
static unsigned long *g_p;
|
|
||||||
|
|
||||||
static void test_hash_prepare(size_t n)
|
|
||||||
{
|
|
||||||
g_p = malloc (n * sizeof(unsigned long));
|
|
||||||
if (g_p == NULL) abort();
|
|
||||||
for(size_t i = 0; i < n ; i++)
|
|
||||||
g_p[i] = ((rand_get()*RAND_MAX + rand_get())*RAND_MAX+rand_get())*RAND_MAX + rand_get();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void test_hash_final(void)
|
|
||||||
{
|
|
||||||
free(g_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_hash(size_t n)
|
|
||||||
{
|
|
||||||
g_result = XXH64(g_p, sizeof(unsigned long)*n, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
const config_func_t table[] = {
|
|
||||||
{ 70,"XXHASH64", 100000000, test_hash_prepare, test_hash, test_hash_final}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
test("XXHASH", numberof(table), table, argc, argv);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
-306
@@ -1,306 +0,0 @@
|
|||||||
/*
|
|
||||||
* M*LIB - common functions for bench module
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017-2024, Patrick Pelissier
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* + Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* + Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
// Maximum supported value for repeat argument
|
|
||||||
#define MAX_REPEAT 10000
|
|
||||||
|
|
||||||
// The global result
|
|
||||||
unsigned long g_result;
|
|
||||||
|
|
||||||
// The rand value
|
|
||||||
#if defined(MULTI_THREAD_MEASURE)
|
|
||||||
M_THREAD_ATTR
|
|
||||||
#endif
|
|
||||||
unsigned int randValue = 0;
|
|
||||||
|
|
||||||
void compiler_barrier(void *p)
|
|
||||||
{
|
|
||||||
// Do nothing, but let the compiler thinks that we did.
|
|
||||||
(void) p;
|
|
||||||
// Can be used for FLTO building
|
|
||||||
// asm volatile("": "+r" (p) : :"memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct parse_opt_s {
|
|
||||||
int test_function;
|
|
||||||
double from, to, step, grow;
|
|
||||||
double within;
|
|
||||||
unsigned repeat;
|
|
||||||
bool graph, best, best_within, average, quiet;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
parse_config(struct parse_opt_s *opt, int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
char *end;
|
|
||||||
|
|
||||||
opt->test_function = 0;
|
|
||||||
opt->from = 0.0;
|
|
||||||
opt->to = 0.0;
|
|
||||||
opt->step = 0.0;
|
|
||||||
opt->grow = 1.1;
|
|
||||||
opt->graph = false;
|
|
||||||
opt->best = false;
|
|
||||||
opt->best_within = false;
|
|
||||||
opt->average = false;
|
|
||||||
opt->quiet = false;
|
|
||||||
opt->repeat = 1;
|
|
||||||
opt->within = .05;
|
|
||||||
|
|
||||||
for(int i = 1; i < argc ; i++)
|
|
||||||
{
|
|
||||||
if (argv[i][0] == '-') {
|
|
||||||
if (strcmp(argv[i], "--from") == 0){
|
|
||||||
i++;
|
|
||||||
opt->from = strtod(argv[i], &end);
|
|
||||||
opt->to = opt->from;
|
|
||||||
} else if (strcmp(argv[i], "--to") == 0) {
|
|
||||||
i++;
|
|
||||||
opt->to = strtod(argv[i], &end);
|
|
||||||
opt->grow = 1.1;
|
|
||||||
} else if (strcmp(argv[i], "--step") == 0) {
|
|
||||||
i++;
|
|
||||||
opt->step = strtod(argv[i], &end);
|
|
||||||
opt->grow = 0;
|
|
||||||
} else if (strcmp(argv[i], "--grow") == 0) {
|
|
||||||
i++;
|
|
||||||
opt->grow = strtod(argv[i], &end);
|
|
||||||
opt->step = 0;
|
|
||||||
} else if (strcmp(argv[i], "--repeat") == 0) {
|
|
||||||
i++;
|
|
||||||
opt->repeat = strtol(argv[i], &end, 10);
|
|
||||||
opt->repeat = (opt->repeat > MAX_REPEAT) ? MAX_REPEAT : opt->repeat;
|
|
||||||
} else if (strcmp(argv[i], "--graph") == 0) {
|
|
||||||
opt->graph = true;
|
|
||||||
} else if (strcmp(argv[i], "--best") == 0) {
|
|
||||||
opt->best = true;
|
|
||||||
opt->average = false;
|
|
||||||
opt->best_within = false;
|
|
||||||
} else if (strcmp(argv[i], "--best-within") == 0) {
|
|
||||||
opt->best_within = true;
|
|
||||||
opt->best = false;
|
|
||||||
opt->average = false;
|
|
||||||
i++;
|
|
||||||
opt->within = strtod(argv[i], &end) / 100.0;
|
|
||||||
} else if (strcmp(argv[i], "--average") == 0) {
|
|
||||||
opt->average = true;
|
|
||||||
opt->best = false;
|
|
||||||
opt->best_within = false;
|
|
||||||
} else if (strcmp(argv[i], "--quiet") == 0) {
|
|
||||||
opt->quiet = true;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "ERROR: Option unkown: %s.\n",
|
|
||||||
argv[i]);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
if (*end != 0) {
|
|
||||||
fprintf(stderr, "ERROR: Cannot parse %s. Expected float\n",
|
|
||||||
argv[i]);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
opt->test_function = strtol (argv[i], &end, 10);
|
|
||||||
if (*end != 0) {
|
|
||||||
fprintf(stderr, "ERROR: Cannot parse %s. Expected function number\n",
|
|
||||||
argv[i]);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
select_config(int func, size_t n, const config_func_t functions[])
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < n;i++) {
|
|
||||||
if (functions[i].num == func)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
fprintf(stderr, "ERROR: Function number %d not found. Available functions are:\n", func);
|
|
||||||
for(size_t i = 0; i < n;i++) {
|
|
||||||
fprintf(stderr, " %d: %s\n", functions[i].num, functions[i].funcname);
|
|
||||||
}
|
|
||||||
fprintf(stderr,
|
|
||||||
"USAGE: FUNC_NUMBER [--from number --to number (--grow number | --step number)] [--graph]\n"
|
|
||||||
"[--repeat number] [--best|--average|--best-within] [--quiet]\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility function for qsort
|
|
||||||
static int cmp_double(const void *pa, const void *pb)
|
|
||||||
{
|
|
||||||
const double *a = (const double *) pa, *b = (const double *)pb;
|
|
||||||
return (*a < *b) ? -1 : *a > *b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the longest sequence of values within 'f'% */
|
|
||||||
static int
|
|
||||||
get_sequence(int i, int n, double tab[], double f)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
for(j = i + 1; j < n; j++) {
|
|
||||||
if (tab[j] > f * tab[i])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return j-i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the minimum of the longest sequence of values with 'f'% */
|
|
||||||
static double
|
|
||||||
get_best_within(int n, double tab[], double f)
|
|
||||||
{
|
|
||||||
qsort(tab, n, sizeof(double), cmp_double);
|
|
||||||
int best_i = 0;
|
|
||||||
int best_seq = get_sequence(0, n, tab, f);
|
|
||||||
for(int i = 1; i < n && (n-i) > best_seq ; i++) {
|
|
||||||
int seq = get_sequence(i, n, tab, f);
|
|
||||||
if (seq > best_seq) {
|
|
||||||
best_i = i;
|
|
||||||
best_seq = seq;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tab[best_i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integer sqrt function (to avoid depending on libm)
|
|
||||||
static unsigned integer_sqrt(unsigned n)
|
|
||||||
{
|
|
||||||
// Find greatest shift.
|
|
||||||
int shift = 2;
|
|
||||||
unsigned nShifted = n >> shift;
|
|
||||||
// We check for nShifted being n, since some implementations
|
|
||||||
// perform shift operations modulo the word size.
|
|
||||||
while (nShifted != 0 && nShifted != n){
|
|
||||||
shift += 2;
|
|
||||||
nShifted = n >> shift;
|
|
||||||
}
|
|
||||||
shift -= 2;
|
|
||||||
// Find digits of result.
|
|
||||||
unsigned result = 0;
|
|
||||||
while (shift >= 0) {
|
|
||||||
result = result << 1;
|
|
||||||
unsigned candidateResult = result + 1;
|
|
||||||
if (candidateResult*candidateResult <= n >> shift) {
|
|
||||||
result = candidateResult;
|
|
||||||
}
|
|
||||||
shift -= 2;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
test(const char library[], size_t n, const config_func_t functions[], int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
// Init & parse arguments
|
|
||||||
// NUMBER
|
|
||||||
// --from NUMBER --to NUMBER --step NUMBER --grow NUMBER
|
|
||||||
// --graph --best --average --quiet
|
|
||||||
// --repeat N
|
|
||||||
struct parse_opt_s arg;
|
|
||||||
parse_config(&arg, argc, argv);
|
|
||||||
int i = select_config(arg.test_function, n, functions);
|
|
||||||
double from = (arg.from == 0) ? functions[i].default_n : arg.from;
|
|
||||||
double to = (arg.to == 0) ? functions[i].default_n : arg.to;
|
|
||||||
|
|
||||||
// Open plot file if needed
|
|
||||||
FILE *graph_file = NULL;
|
|
||||||
if (arg.graph) {
|
|
||||||
char filename[100];
|
|
||||||
sprintf(filename, "plot-%s-%d.dat", library, arg.test_function);
|
|
||||||
graph_file = fopen(filename, "wt");
|
|
||||||
if (!graph_file) {
|
|
||||||
fprintf(stderr, "ERROR: Cannot create the file '%s'\n", filename);
|
|
||||||
exit(-2);
|
|
||||||
}
|
|
||||||
fprintf(graph_file, "# plotting %s-%d : %s\n# N T", library, arg.test_function, functions[i].funcname);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the bench
|
|
||||||
for(double n = from; n <= to ; n = ((arg.grow == 0) ? n + arg.step : n * arg.grow))
|
|
||||||
{
|
|
||||||
double best = (1.0/0.0);
|
|
||||||
double avg = 0.0;
|
|
||||||
double variance = 0.0;
|
|
||||||
static double measure[MAX_REPEAT];
|
|
||||||
double ba = 0.0;
|
|
||||||
|
|
||||||
if (functions[i].init != NULL)
|
|
||||||
functions[i].init(n);
|
|
||||||
|
|
||||||
// Measure the time of the test_function
|
|
||||||
for(unsigned r = 0; r < arg.repeat; r++) {
|
|
||||||
double t0 = test_function( (arg.graph|arg.best|arg.average|arg.quiet) ? NULL : functions[i].funcname, (size_t) n, functions[i].func);
|
|
||||||
best = (t0 < best) ? t0 : best;
|
|
||||||
avg += t0;
|
|
||||||
variance += t0 * t0;
|
|
||||||
measure[r] = t0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Closure of the tests
|
|
||||||
if (functions[i].clear != NULL)
|
|
||||||
functions[i].clear();
|
|
||||||
|
|
||||||
// Finish computing the different times
|
|
||||||
if (arg.repeat > 1) {
|
|
||||||
avg /= arg.repeat;
|
|
||||||
variance = (variance - arg.repeat * avg * avg) / (arg.repeat - 1);
|
|
||||||
ba = get_best_within(arg.repeat, measure, 1. + arg.within);
|
|
||||||
} else {
|
|
||||||
ba = avg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The average value shall be around best_within (and greater)
|
|
||||||
// otherwise the result doesn't seem reliable.
|
|
||||||
bool reliable = (ba <= avg && ba * (1.0+arg.within/2) + 0.5 > avg);
|
|
||||||
|
|
||||||
// Print the result
|
|
||||||
if (arg.graph) {
|
|
||||||
fprintf(graph_file, "%f %f\n", n, arg.average ? avg : arg.best ? best : ba);
|
|
||||||
} else if (arg.quiet) {
|
|
||||||
printf("%ld\n", (long)(arg.average ? avg : arg.best ? best : reliable ? ba : -1));
|
|
||||||
} else if (arg.repeat > 1) {
|
|
||||||
if (arg.average == false && arg.best_within == false)
|
|
||||||
printf ("%20.20s time %lu ms for n = %lu *** BEST ***\n", functions[i].funcname, (unsigned long) best, (unsigned long) n);
|
|
||||||
if (arg.best == false && arg.best_within == false)
|
|
||||||
printf ("%20.20s time %lu ms +/- %u ms for n = %lu *** AVERAGE ***\n", functions[i].funcname, (unsigned long) avg, 2*integer_sqrt(variance), (unsigned long) n);
|
|
||||||
if (arg.best == false && arg.average == false)
|
|
||||||
printf ("%20.20s time %lu ms for n = %lu *** BEST within %d%% *** %s\n", functions[i].funcname, (unsigned long) ba, (unsigned long) n, (int)(100*arg.within), reliable ? "" : "(unreliable result)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the FILE if needed
|
|
||||||
if (arg.graph) {
|
|
||||||
fclose(graph_file);
|
|
||||||
printf("File plot-%s-%d.dat generated.\n"
|
|
||||||
"Run in gnuplot the following command:\n"
|
|
||||||
"\tplot 'plot-%s-%d.dat' with linespoints linestyle 1\n",
|
|
||||||
library, arg.test_function, library, arg.test_function);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
-171
@@ -1,171 +0,0 @@
|
|||||||
/*
|
|
||||||
* M*LIB - common functions for bench module
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017-2024, Patrick Pelissier
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* + Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* + Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
#ifndef __COMMON_BENCH__H
|
|
||||||
#define __COMMON_BENCH__H
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
// Needed for M_THREAD_ATTR
|
|
||||||
#if defined(MULTI_THREAD_MEASURE)
|
|
||||||
#include "m-thread.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
# include <windows.h>
|
|
||||||
#elif (defined(__APPLE__) && defined(__MACH__)) \
|
|
||||||
|| defined(__DragonFly__) || defined(__FreeBSD__) \
|
|
||||||
|| defined(__NetBSD__) || defined(__OpenBSD__)
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <sys/resource.h>
|
|
||||||
# include <sys/time.h>
|
|
||||||
# include <sys/param.h>
|
|
||||||
# include <sys/sysctl.h>
|
|
||||||
# define USE_SYSCTL
|
|
||||||
#else
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <sys/resource.h>
|
|
||||||
# include <sys/time.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Number of elements of a table
|
|
||||||
#define numberof(x) (sizeof(x)/sizeof(x[0]))
|
|
||||||
|
|
||||||
/* Get the current CPU time in microsecond. */
|
|
||||||
#if defined(_WIN32)
|
|
||||||
/* WINDOWS variant */
|
|
||||||
static inline unsigned long long
|
|
||||||
cputime (void)
|
|
||||||
{
|
|
||||||
LARGE_INTEGER freq, val;
|
|
||||||
QueryPerformanceFrequency(&freq);
|
|
||||||
QueryPerformanceCounter(&val);
|
|
||||||
return (unsigned long long) (1000000. * (double) val.QuadPart / (double) freq.QuadPart);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* UNIX variant */
|
|
||||||
static inline unsigned long long
|
|
||||||
cputime (void)
|
|
||||||
{
|
|
||||||
#if defined(MULTI_THREAD_MEASURE)
|
|
||||||
// Multi thread: Uses real time
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday (&tv, NULL);
|
|
||||||
return tv.tv_sec * 1000000ULL + tv.tv_usec;
|
|
||||||
#else
|
|
||||||
// Single thread: Uses process usage time
|
|
||||||
struct rusage rus;
|
|
||||||
getrusage (0, &rus);
|
|
||||||
return rus.ru_utime.tv_sec * 1000000ULL + rus.ru_utime.tv_usec;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The result of the bench
|
|
||||||
extern unsigned long g_result;
|
|
||||||
|
|
||||||
// The rand value
|
|
||||||
extern
|
|
||||||
#if defined(MULTI_THREAD_MEASURE)
|
|
||||||
M_THREAD_ATTR
|
|
||||||
#endif
|
|
||||||
unsigned int randValue;
|
|
||||||
|
|
||||||
// Pseudo rand value generator.
|
|
||||||
// Not very random but sufficient and fast enough for the bench
|
|
||||||
static inline void rand_init(void)
|
|
||||||
{
|
|
||||||
randValue = 0;
|
|
||||||
}
|
|
||||||
static inline unsigned int rand_get(void)
|
|
||||||
{
|
|
||||||
randValue = randValue * 31421U + 6927U;
|
|
||||||
return randValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The function that performs the bench
|
|
||||||
static inline double
|
|
||||||
test_function(const char *str, size_t n, void (*func)(size_t))
|
|
||||||
{
|
|
||||||
double result;
|
|
||||||
unsigned long long start, end;
|
|
||||||
rand_init();
|
|
||||||
start = cputime();
|
|
||||||
(*func)(n);
|
|
||||||
end = cputime();
|
|
||||||
result = (double)(end-start) / 1000.0;
|
|
||||||
if (str != NULL) {
|
|
||||||
printf ("%20.20s time %.2f ms for n = %lu [r=%lu]\n", str, result, (unsigned long) n, g_result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configuration table
|
|
||||||
typedef struct {
|
|
||||||
int num;
|
|
||||||
const char *funcname;
|
|
||||||
size_t default_n;
|
|
||||||
void (*init)(size_t);
|
|
||||||
void (*func)(size_t);
|
|
||||||
void (*clear)(void);
|
|
||||||
} config_func_t;
|
|
||||||
|
|
||||||
// Perform a parsing of the given arguments and do the bench according to the table
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
#endif
|
|
||||||
void test(const char library[], size_t n, const config_func_t functions[], int argc, const char *argv[]);
|
|
||||||
|
|
||||||
/* Return the number of CPU of the system */
|
|
||||||
static inline int get_cpu_count(void)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
SYSTEM_INFO sysinfo;
|
|
||||||
GetSystemInfo(&sysinfo);
|
|
||||||
return sysinfo.dwNumberOfProcessors;
|
|
||||||
#elif defined(USE_SYSCTL)
|
|
||||||
int nm[2];
|
|
||||||
int count = 0;
|
|
||||||
size_t len = sizeof (count);
|
|
||||||
nm[0] = CTL_HW;
|
|
||||||
nm[1] = HW_NCPU;
|
|
||||||
sysctl(nm, 2, &count, &len, NULL, 0);
|
|
||||||
return MAX(1, count);
|
|
||||||
#elif defined (_SC_NPROCESSORS_ONLN)
|
|
||||||
return sysconf(_SC_NPROCESSORS_ONLN);
|
|
||||||
#else
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
#endif
|
|
||||||
void compiler_barrier(void *p);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* MLIB - TEST module
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017-2024, Patrick Pelissier
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* + Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* + Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define NDEBUG
|
|
||||||
#include "m-dict.h"
|
|
||||||
|
|
||||||
static inline bool oor_equal_p(int64_t k, unsigned char n)
|
|
||||||
{
|
|
||||||
return k == (int)-n-1;
|
|
||||||
}
|
|
||||||
static inline void oor_set(int64_t *k, unsigned char n)
|
|
||||||
{
|
|
||||||
*k = (int)-n-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DICT_OA_DEF2(dict_int64, int64_t, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)), int64_t, M_DEFAULT_OPLIST)
|
|
||||||
|
|
||||||
static int64_t get_rand(void)
|
|
||||||
{
|
|
||||||
int64_t n;
|
|
||||||
do {
|
|
||||||
n = (rand() * RAND_MAX + rand()) * RAND_MAX + rand();
|
|
||||||
} while (n == -1 || n == -2);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let's push value into the dict until the system abandons!
|
|
||||||
static void find_max(void)
|
|
||||||
{
|
|
||||||
dict_int64_t dict;
|
|
||||||
dict_int64_init(dict);
|
|
||||||
size_t n = 0;
|
|
||||||
while (true) {
|
|
||||||
dict_int64_set_at (dict, get_rand(), get_rand());
|
|
||||||
n++;
|
|
||||||
if ((n & ((1<<20)-1)) == 0) {
|
|
||||||
printf ("n=%zu\n", n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dict_int64_clear(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
find_max();
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
CC=cc -std=c11
|
|
||||||
CXX=c++ -std=c++11
|
|
||||||
CFLAGS=-O2 -march=native -Wall
|
|
||||||
CPPFLAGS=-I../..
|
|
||||||
|
|
||||||
all: k-nucleotide
|
|
||||||
|
|
||||||
k-nucleotide: k-nucleotide.exe data.txt
|
|
||||||
./k-nucleotide.exe < data.txt
|
|
||||||
|
|
||||||
k-nucleotide.exe: nucleotide.c
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) nucleotide.c -o k-nucleotide.exe -lpthread
|
|
||||||
|
|
||||||
data.txt: fasta.exe
|
|
||||||
./fasta.exe 25000000 > data.txt
|
|
||||||
|
|
||||||
fasta.exe: fasta.c
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -fopenmp fasta.c -o fasta.exe
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.exe *~ *.o data.txt
|
|
||||||
|
|
||||||
@@ -1,344 +0,0 @@
|
|||||||
// The Computer Language Benchmarks Game
|
|
||||||
// http://benchmarksgame.alioth.debian.org/
|
|
||||||
//
|
|
||||||
// contributed by Jeremy Zerfas
|
|
||||||
// rewritten by Аноним Легионов, inspired by fasta Rust #2 program
|
|
||||||
// use two OpenMP locks instead of one critical section
|
|
||||||
// decouples IO activity from random number generation
|
|
||||||
//
|
|
||||||
// modified by Josh Goldfoot, adding use of a buffer for fasta_repeat
|
|
||||||
|
|
||||||
|
|
||||||
// This controls the width of lines that are output by this program.
|
|
||||||
#define MAXIMUM_LINE_WIDTH 60
|
|
||||||
|
|
||||||
// This program will generate the random nucleotide sequences in parallel which
|
|
||||||
// are worked on in blocks of lines. The number of lines in those blocks is
|
|
||||||
// controlled by this setting.
|
|
||||||
#define LINES_PER_BLOCK 1024
|
|
||||||
|
|
||||||
#define CHARACTERS_PER_BLOCK (MAXIMUM_LINE_WIDTH*LINES_PER_BLOCK)
|
|
||||||
|
|
||||||
#define THREADS_TO_USE 4
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#include <omp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// intptr_t should be the native integer type on most sane systems.
|
|
||||||
typedef intptr_t intnative_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char letter;
|
|
||||||
float probability;
|
|
||||||
} nucleotide_info;
|
|
||||||
|
|
||||||
|
|
||||||
// Repeatedly print string_To_Repeat until it has printed
|
|
||||||
// number_Of_Characters_To_Create. The output is also wrapped to
|
|
||||||
// MAXIMUM_LINE_WIDTH columns.
|
|
||||||
static char* make_Sequence_Buffer(const char string_To_Repeat[])
|
|
||||||
{
|
|
||||||
const intnative_t string_To_Repeat_Length = strlen(string_To_Repeat);
|
|
||||||
|
|
||||||
// JG: Changed to that this writes a sequence to a buffer, which is used
|
|
||||||
intnative_t number_Of_Characters_To_Create = string_To_Repeat_Length * MAXIMUM_LINE_WIDTH;
|
|
||||||
char* buffer = (char*) malloc(number_Of_Characters_To_Create +
|
|
||||||
number_Of_Characters_To_Create / MAXIMUM_LINE_WIDTH + 1);
|
|
||||||
if (buffer == NULL)
|
|
||||||
exit(-1);
|
|
||||||
char* bufferOffset = buffer;
|
|
||||||
|
|
||||||
// Create an extended_String_To_Repeat which is a copy of string_To_Repeat
|
|
||||||
// but extended with another copy of the first MAXIMUM_LINE_WIDTH characters
|
|
||||||
// of string_To_Repeat appended to the end. Later on this allows us to
|
|
||||||
// generate a line of output just by doing simple memory copies using an
|
|
||||||
// appropriate offset into extended_String_To_Repeat.
|
|
||||||
char extended_String_To_Repeat[string_To_Repeat_Length + MAXIMUM_LINE_WIDTH];
|
|
||||||
for (intnative_t column = 0; column<string_To_Repeat_Length + MAXIMUM_LINE_WIDTH;
|
|
||||||
column++)
|
|
||||||
extended_String_To_Repeat[column] =
|
|
||||||
string_To_Repeat[column%string_To_Repeat_Length];
|
|
||||||
intnative_t offset = 0;
|
|
||||||
|
|
||||||
char line[MAXIMUM_LINE_WIDTH + 1];
|
|
||||||
line[MAXIMUM_LINE_WIDTH] = '\n';
|
|
||||||
|
|
||||||
for (intnative_t current_Number_Of_Characters_To_Create =
|
|
||||||
number_Of_Characters_To_Create;
|
|
||||||
current_Number_Of_Characters_To_Create>0;)
|
|
||||||
{
|
|
||||||
// Figure out the length of the line we need to write. If it's less than
|
|
||||||
// MAXIMUM_LINE_WIDTH then we also need to add a line feed in the right
|
|
||||||
// spot too.
|
|
||||||
intnative_t line_Length = MAXIMUM_LINE_WIDTH;
|
|
||||||
if (current_Number_Of_Characters_To_Create<MAXIMUM_LINE_WIDTH)
|
|
||||||
{
|
|
||||||
line_Length = current_Number_Of_Characters_To_Create;
|
|
||||||
line[line_Length] = '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(line, extended_String_To_Repeat + offset, line_Length);
|
|
||||||
|
|
||||||
// Update the offset, reducing it by string_To_Repeat_Length if
|
|
||||||
// necessary.
|
|
||||||
offset += line_Length;
|
|
||||||
if (offset>string_To_Repeat_Length)
|
|
||||||
offset -= string_To_Repeat_Length;
|
|
||||||
|
|
||||||
// "Output" that line to our buffer and update the
|
|
||||||
// current_Number_Of_Characters_To_Create.
|
|
||||||
memcpy(bufferOffset, line, line_Length + 1); // JG: used to be fwrite(line, line_Length + 1, 1, stdout);
|
|
||||||
bufferOffset += line_Length + 1;
|
|
||||||
current_Number_Of_Characters_To_Create -= line_Length;
|
|
||||||
}
|
|
||||||
*bufferOffset = 0;
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void repeat_And_Wrap_String(const char string_To_Repeat[], intnative_t number_Of_Characters_To_Create)
|
|
||||||
{
|
|
||||||
/* JG: fasta_repeat repeats every len(alu) * line-length = 287 * 61 = 17507 characters.
|
|
||||||
So, calculate this once, then just print that buffer over and over. */
|
|
||||||
char* sequence = make_Sequence_Buffer(string_To_Repeat);
|
|
||||||
intnative_t sequenceLen = (intnative_t) strlen(sequence);
|
|
||||||
intnative_t outputBytes = number_Of_Characters_To_Create + number_Of_Characters_To_Create / 60;
|
|
||||||
while (outputBytes >= sequenceLen) {
|
|
||||||
fwrite(sequence, sequenceLen, 1, stdout);
|
|
||||||
outputBytes -= sequenceLen;
|
|
||||||
}
|
|
||||||
if (outputBytes > 0) {
|
|
||||||
fwrite(sequence, outputBytes, 1, stdout);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
free(sequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Generate a pseudorandom number from 0 to max using a linear
|
|
||||||
// congruential generator.
|
|
||||||
#define IM 139968
|
|
||||||
#define IA 3877
|
|
||||||
#define IC 29573
|
|
||||||
uint32_t seed = 42;
|
|
||||||
|
|
||||||
int rng_tid; //Thread ID
|
|
||||||
int rng_tnum = 1; //Thread number
|
|
||||||
intnative_t rng_cnt = 0;
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
omp_lock_t rng_lock;
|
|
||||||
#define RNG_LOCK_INIT() omp_init_lock(&rng_lock)
|
|
||||||
#define RNG_LOCK() omp_set_lock(&rng_lock)
|
|
||||||
#define RNG_FREE() omp_unset_lock(&rng_lock)
|
|
||||||
#else
|
|
||||||
#define RNG_LOCK_INIT() do{}while(0)
|
|
||||||
#define RNG_LOCK() do{}while(0)
|
|
||||||
#define RNG_FREE() do{}while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void rng_init(void)
|
|
||||||
{
|
|
||||||
RNG_LOCK_INIT();
|
|
||||||
rng_tid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static intnative_t rng_gen_blk(uint32_t * buf, intnative_t len, int curr_tid)
|
|
||||||
{
|
|
||||||
intnative_t gen_cnt = -1;//Error by default
|
|
||||||
RNG_LOCK();
|
|
||||||
|
|
||||||
if (rng_tid == curr_tid)
|
|
||||||
{
|
|
||||||
if (++rng_tid >= rng_tnum)
|
|
||||||
{
|
|
||||||
rng_tid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_cnt = (len<rng_cnt) ? len : rng_cnt;
|
|
||||||
rng_cnt -= gen_cnt;
|
|
||||||
|
|
||||||
len = gen_cnt;
|
|
||||||
|
|
||||||
while (0 != len--)
|
|
||||||
{
|
|
||||||
seed = (seed*IA + IC) % IM;
|
|
||||||
*(buf++) = seed;//This is stupid actually!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RNG_FREE();
|
|
||||||
return gen_cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
int out_tid; //Thread ID
|
|
||||||
int out_tnum = 1; //Thread number
|
|
||||||
#ifdef _OPENMP
|
|
||||||
omp_lock_t out_lock;
|
|
||||||
#define OUT_LOCK_INIT() omp_init_lock(&out_lock)
|
|
||||||
#define OUT_LOCK() omp_set_lock(&out_lock)
|
|
||||||
#define OUT_FREE() omp_unset_lock(&out_lock)
|
|
||||||
#else
|
|
||||||
#define OUT_LOCK_INIT() do{}while(0)
|
|
||||||
#define OUT_LOCK() do{}while(0)
|
|
||||||
#define OUT_FREE() do{}while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void out_init(void)
|
|
||||||
{
|
|
||||||
OUT_LOCK_INIT();
|
|
||||||
rng_tid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static intnative_t out_write(char * buf, intnative_t len, int curr_tid)
|
|
||||||
{
|
|
||||||
intnative_t wr_cnt = -1;//Error by default
|
|
||||||
OUT_LOCK();
|
|
||||||
|
|
||||||
if (out_tid == curr_tid)
|
|
||||||
{
|
|
||||||
if (++out_tid >= out_tnum)
|
|
||||||
{
|
|
||||||
out_tid = 0;
|
|
||||||
}
|
|
||||||
wr_cnt = fwrite(buf, len, 1, stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
OUT_FREE();
|
|
||||||
return wr_cnt; //-1 - thread error, 0 - IO error, 1 - ОК
|
|
||||||
}
|
|
||||||
|
|
||||||
static void generate_And_Wrap_Pseudorandom_DNA_Sequence(
|
|
||||||
const nucleotide_info nucl_info[],
|
|
||||||
const intnative_t nucl_num,
|
|
||||||
const intnative_t char_num)
|
|
||||||
{
|
|
||||||
uint32_t cumul_p[nucl_num];
|
|
||||||
float cumul_acc = 0.0;
|
|
||||||
|
|
||||||
for (intnative_t i = 0; i<nucl_num; i++)
|
|
||||||
{
|
|
||||||
cumul_acc += nucl_info[i].probability;
|
|
||||||
cumul_p[i] = 1ul + (uint32_t)(cumul_acc*(float)IM); //Compensate rounding errors on test file
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
intnative_t tnum = omp_get_num_procs();
|
|
||||||
if (tnum>THREADS_TO_USE) tnum = THREADS_TO_USE;
|
|
||||||
omp_set_num_threads(tnum);
|
|
||||||
rng_tnum = tnum;
|
|
||||||
out_tnum = tnum;
|
|
||||||
#endif
|
|
||||||
rng_tid = 0;
|
|
||||||
out_tid = 0;
|
|
||||||
rng_cnt = char_num;
|
|
||||||
|
|
||||||
#pragma omp parallel
|
|
||||||
{
|
|
||||||
char block[CHARACTERS_PER_BLOCK + LINES_PER_BLOCK];
|
|
||||||
char * line;
|
|
||||||
uint32_t rnd[CHARACTERS_PER_BLOCK], r;
|
|
||||||
intnative_t cnt, col, prid, nid, ncnt;
|
|
||||||
int cur_tid;
|
|
||||||
#ifdef _OPENMP
|
|
||||||
cur_tid = omp_get_thread_num();
|
|
||||||
#else
|
|
||||||
cur_tid = 0;
|
|
||||||
#endif
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
cnt = rng_gen_blk(rnd, CHARACTERS_PER_BLOCK, cur_tid);
|
|
||||||
} while (-1 == cnt);
|
|
||||||
|
|
||||||
if (0 == cnt)
|
|
||||||
{
|
|
||||||
break;//Work finished!
|
|
||||||
}
|
|
||||||
|
|
||||||
line = block;
|
|
||||||
|
|
||||||
for (col = 0, prid = 0; prid < cnt; prid++)
|
|
||||||
{
|
|
||||||
r = rnd[prid];
|
|
||||||
|
|
||||||
ncnt = 0;
|
|
||||||
for (nid = 0; nid < nucl_num; nid++)
|
|
||||||
{
|
|
||||||
if (cumul_p[nid] <= r)
|
|
||||||
{
|
|
||||||
ncnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*line++ = nucl_info[ncnt].letter;
|
|
||||||
if (++col >= MAXIMUM_LINE_WIDTH)
|
|
||||||
{
|
|
||||||
col = 0;
|
|
||||||
*line++ = '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Check if we need to end the line
|
|
||||||
if (0 != col)
|
|
||||||
{
|
|
||||||
//Last iteration didn't end the line, so finish the job.
|
|
||||||
*line++ = '\n';
|
|
||||||
}
|
|
||||||
//Print results
|
|
||||||
do
|
|
||||||
{
|
|
||||||
cnt = out_write(block, line - block, cur_tid);
|
|
||||||
} while (-1 == cnt);
|
|
||||||
//Check fot IO error
|
|
||||||
if (0 == cnt)
|
|
||||||
{
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char ** argv)
|
|
||||||
{
|
|
||||||
const intnative_t n = atoi(argv[1]);
|
|
||||||
|
|
||||||
fputs(">ONE Homo sapiens alu\n", stdout);
|
|
||||||
const char homo_Sapiens_Alu[] =
|
|
||||||
"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTC"
|
|
||||||
"AGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCG"
|
|
||||||
"TGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGG"
|
|
||||||
"AGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
|
|
||||||
repeat_And_Wrap_String(homo_Sapiens_Alu, 2 * n);
|
|
||||||
|
|
||||||
rng_init();
|
|
||||||
out_init();
|
|
||||||
|
|
||||||
fputs(">TWO IUB ambiguity codes\n", stdout);
|
|
||||||
nucleotide_info iub_Nucleotides_Information[] =
|
|
||||||
{
|
|
||||||
{ 'a', 0.27 },{ 'c', 0.12 },{ 'g', 0.12 },{ 't', 0.27 },{ 'B', 0.02 },
|
|
||||||
{ 'D', 0.02 },{ 'H', 0.02 },{ 'K', 0.02 },{ 'M', 0.02 },{ 'N', 0.02 },
|
|
||||||
{ 'R', 0.02 },{ 'S', 0.02 },{ 'V', 0.02 },{ 'W', 0.02 },{ 'Y', 0.02 }
|
|
||||||
};
|
|
||||||
generate_And_Wrap_Pseudorandom_DNA_Sequence(iub_Nucleotides_Information,
|
|
||||||
sizeof(iub_Nucleotides_Information) / sizeof(nucleotide_info), 3 * n);
|
|
||||||
|
|
||||||
fputs(">THREE Homo sapiens frequency\n", stdout);
|
|
||||||
nucleotide_info homo_Sapien_Nucleotides_Information[] =
|
|
||||||
{
|
|
||||||
{ 'a', 0.3029549426680 },{ 'c', 0.1979883004921 },
|
|
||||||
{ 'g', 0.1975473066391 },{ 't', 0.3015094502008 }
|
|
||||||
};
|
|
||||||
generate_And_Wrap_Pseudorandom_DNA_Sequence(homo_Sapien_Nucleotides_Information,
|
|
||||||
sizeof(homo_Sapien_Nucleotides_Information) / sizeof(nucleotide_info), 5 * n);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
// The Computer Language Benchmarks Game
|
|
||||||
// http://benchmarksgame.alioth.debian.org/
|
|
||||||
//
|
|
||||||
// Original version Contributed by Jeremy Zerfas
|
|
||||||
// M*LIB port contributed by Patrick Pélissier
|
|
||||||
#define NDEBUG
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "m-worker.h"
|
|
||||||
#include "m-dict.h"
|
|
||||||
#include "m-bptree.h"
|
|
||||||
|
|
||||||
// This controls the maximum length for each set of oligonucleotide frequencies
|
|
||||||
// and each oligonucleotide count output by this program.
|
|
||||||
#define MAXIMUM_OUTPUT_LENGTH 4096
|
|
||||||
|
|
||||||
// Number of outputs to display
|
|
||||||
#define MAXMUM_NUMBER_OUTPUT 7
|
|
||||||
|
|
||||||
/* Define the needed containers */
|
|
||||||
/* Define Open Addressing dictionary of uint64_t --> uint32_t. Need to define how to handle out of bound data. */
|
|
||||||
static inline bool my_oor_equal_p(uint64_t k, unsigned char n)
|
|
||||||
{
|
|
||||||
return k == ~(uint64_t) n;
|
|
||||||
}
|
|
||||||
static inline void my_oor_set(uint64_t *k, unsigned char n)
|
|
||||||
{
|
|
||||||
*k = ~(uint64_t)n;
|
|
||||||
}
|
|
||||||
static inline size_t my_hash(uint64_t key)
|
|
||||||
{
|
|
||||||
return ((key) ^ (key)>>7);
|
|
||||||
}
|
|
||||||
DICT_OA_DEF2(dict_oligonucleotide,
|
|
||||||
uint64_t, M_OPEXTEND(M_DEFAULT_OPLIST, HASH(my_hash), OOR_EQUAL(my_oor_equal_p), OOR_SET(my_oor_set M_IPTR)),
|
|
||||||
uint32_t, M_DEFAULT_OPLIST)
|
|
||||||
#define M_OPL_dict_oligonucleotide_t() DICT_OPLIST(dict_oligonucleotide, M_OPEXTEND(M_DEFAULT_OPLIST, HASH(my_hash), OOR_EQUAL(my_oor_equal_p), OOR_SET(my_oor_set M_IPTR)), M_DEFAULT_OPLIST)
|
|
||||||
|
|
||||||
// Define a B*TREE-21 of uint32_t --> uint64_t and register its oplist
|
|
||||||
#define TREE_CMP(a,b) ((a) > (b) ? -1 : (a) < (b)) /* reverse natural order */
|
|
||||||
BPTREE_DEF2(tree_dict_oligonucleotide, 21, uint32_t, M_OPEXTEND(M_DEFAULT_OPLIST, CMP(TREE_CMP)), uint64_t, M_DEFAULT_OPLIST)
|
|
||||||
#define M_OPL_tree_dict_oligonucleotide_t() BPTREE_OPLIST2(tree_dict_oligonucleotide, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST)
|
|
||||||
|
|
||||||
/* Define the data to analyse (a plain array) */
|
|
||||||
ARRAY_DEF(polynucleotide, unsigned char)
|
|
||||||
|
|
||||||
// Macro to convert a nucleotide character to a code. Note that upper and lower
|
|
||||||
// case ASCII letters only differ in the fifth bit from the right and we only
|
|
||||||
// need the three least significant bits to differentiate the letters 'A', 'C',
|
|
||||||
// 'G', and 'T'. Spaces in this array/string will never be used as long as
|
|
||||||
// characters other than 'A', 'C', 'G', and 'T' aren't used.
|
|
||||||
#define CODE_FOR_NUCLEOTIDE(nucleotide) (" \0 \1\3 \2"[nucleotide & 0x7])
|
|
||||||
|
|
||||||
// And one more macro to convert the codes back to nucleotide characters.
|
|
||||||
#define NUCLEOTIDE_FOR_CODE(code) ("ACGT"[code & 0x3])
|
|
||||||
|
|
||||||
static worker_t worker;
|
|
||||||
|
|
||||||
// Read from the given stream the data and fill in the array with the converted one.
|
|
||||||
static void polynucleotide_init_stream(polynucleotide_t p, FILE *stream)
|
|
||||||
{
|
|
||||||
char buffer[MAXIMUM_OUTPUT_LENGTH], c;
|
|
||||||
|
|
||||||
polynucleotide_init(p);
|
|
||||||
polynucleotide_reserve(p, MAXIMUM_OUTPUT_LENGTH);
|
|
||||||
// Find the start of the third polynucleotide.
|
|
||||||
while(fgets(buffer, sizeof(buffer), stream) && memcmp(">THREE", buffer, 6));
|
|
||||||
// Start reading and encoding the third polynucleotide.
|
|
||||||
while(fgets(buffer, sizeof(buffer), stream) && buffer[0]!='>'){
|
|
||||||
for(size_t i = 0; (c = buffer[i]) !='\0'; i++) {
|
|
||||||
if (c != '\n') {
|
|
||||||
polynucleotide_push_back(p, CODE_FOR_NUCLEOTIDE(c));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the function which does 95% of the work.
|
|
||||||
/* NOTE: paralelisation is not done by cutting the input set in two.
|
|
||||||
This is not efficient as the size of the output table will be the same
|
|
||||||
as for the whole table. */
|
|
||||||
static void init_hash(dict_oligonucleotide_t hash_Table, const size_t size, const unsigned char tab[size], const size_t desiredLength, const size_t offset, const size_t skip)
|
|
||||||
{
|
|
||||||
uint64_t key = 0;
|
|
||||||
const uint64_t mask = (1ULL<<(2*desiredLength))-1;
|
|
||||||
assert (2*desiredLength < 64 && desiredLength < size);
|
|
||||||
assert ((1 == skip || 4 == skip) && offset < size);
|
|
||||||
|
|
||||||
// For the first several nucleotides we only need to append them to key in
|
|
||||||
// preparation for the insertion of complete oligonucleotides to hash.
|
|
||||||
for(size_t i = 0; i < desiredLength - 1 + offset; i++)
|
|
||||||
key = (key<<2) | tab[i];
|
|
||||||
key &= mask;
|
|
||||||
|
|
||||||
dict_oligonucleotide_t hash;
|
|
||||||
dict_oligonucleotide_init(hash);
|
|
||||||
|
|
||||||
// Add all the complete oligonucleotides of
|
|
||||||
// desiredLength to hash, updating their count
|
|
||||||
if (skip == 1) {
|
|
||||||
for(size_t i = desiredLength-1+offset ; i < size; i++) {
|
|
||||||
key = (key<<2) | tab[i+0];
|
|
||||||
key &= mask;
|
|
||||||
uint32_t *p = dict_oligonucleotide_get(hash, key);
|
|
||||||
if (p != NULL) {
|
|
||||||
(*p) ++;
|
|
||||||
} else {
|
|
||||||
dict_oligonucleotide_set_at(hash, key, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // skip = 4
|
|
||||||
for(size_t i = desiredLength-1+offset ; i < size; i+=4) {
|
|
||||||
for (size_t j = 0; j < 4; j++)
|
|
||||||
key = (key<<2) | tab[i+j];
|
|
||||||
key &= mask;
|
|
||||||
uint32_t *p = dict_oligonucleotide_get(hash, key);
|
|
||||||
if (p != NULL) {
|
|
||||||
(*p) ++;
|
|
||||||
} else {
|
|
||||||
dict_oligonucleotide_set_at(hash, key, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dict_oligonucleotide_init_move(hash_Table, hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void compute_hash(dict_oligonucleotide_t hash_Table, const polynucleotide_t p, const size_t desiredLength)
|
|
||||||
{
|
|
||||||
size_t size = polynucleotide_size(p);
|
|
||||||
unsigned char *tab = polynucleotide_get(p, 0);
|
|
||||||
if (desiredLength < 8) {
|
|
||||||
init_hash(hash_Table, size, tab, desiredLength, 0, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
worker_sync_t block; // Define a synchronization block
|
|
||||||
worker_start(block, worker);
|
|
||||||
dict_oligonucleotide_t hash_Table3, *p_hash_Table3 = &hash_Table3;
|
|
||||||
dict_oligonucleotide_t hash_Table2, *p_hash_Table2 = &hash_Table2;
|
|
||||||
dict_oligonucleotide_t hash_Table1, *p_hash_Table1 = &hash_Table1;
|
|
||||||
WORKER_SPAWN(block, (p_hash_Table1, size, tab, desiredLength), {
|
|
||||||
init_hash(*p_hash_Table1, size, tab, desiredLength, 3, 4);
|
|
||||||
}, (/*no output*/));
|
|
||||||
WORKER_SPAWN(block, (p_hash_Table2, size, tab, desiredLength), {
|
|
||||||
init_hash(*p_hash_Table2, size, tab, desiredLength, 2, 4);
|
|
||||||
}, (/*no output*/));
|
|
||||||
WORKER_SPAWN(block, (p_hash_Table3, size, tab, desiredLength), {
|
|
||||||
init_hash(*p_hash_Table3, size, tab, desiredLength, 1, 4);
|
|
||||||
}, (/*no output*/));
|
|
||||||
init_hash(hash_Table, size, tab, desiredLength, 0, 4);
|
|
||||||
worker_sync(block);
|
|
||||||
|
|
||||||
// Merge all hashtables
|
|
||||||
dict_oligonucleotide_splice(hash_Table, hash_Table1);
|
|
||||||
dict_oligonucleotide_splice(hash_Table, hash_Table2);
|
|
||||||
dict_oligonucleotide_splice(hash_Table, hash_Table3);
|
|
||||||
// Clear extra hashtables
|
|
||||||
dict_oligonucleotide_clear(hash_Table3);
|
|
||||||
dict_oligonucleotide_clear(hash_Table2);
|
|
||||||
dict_oligonucleotide_clear(hash_Table1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate frequencies for all oligonucleotides in polynucleotide that are of
|
|
||||||
// desiredLength and then save it to output.
|
|
||||||
static void compute_freq(const polynucleotide_t p, const size_t desiredLength, char output[])
|
|
||||||
{
|
|
||||||
dict_oligonucleotide_t hash_Table;
|
|
||||||
compute_hash(hash_Table, p, desiredLength);
|
|
||||||
|
|
||||||
// Order key is the count frequency (inverse value & key)
|
|
||||||
tree_dict_oligonucleotide_t tree;
|
|
||||||
tree_dict_oligonucleotide_init(tree);
|
|
||||||
for M_EACH(item, hash_Table, dict_oligonucleotide_t) {
|
|
||||||
tree_dict_oligonucleotide_set_at (tree, item->value, item->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Output
|
|
||||||
char oligonucleotide[64];
|
|
||||||
const double invSum = 100.0 / (double) (polynucleotide_size(p) - desiredLength + 1);
|
|
||||||
int output_Position = 0;
|
|
||||||
for M_EACH(item, tree, tree_dict_oligonucleotide_t) {
|
|
||||||
// Convert the key for the oligonucleotide to a string.
|
|
||||||
uint64_t freq = *item->value_ptr;
|
|
||||||
uint32_t count = *item->key_ptr;
|
|
||||||
for(size_t j = desiredLength-1; j < desiredLength; j--){
|
|
||||||
oligonucleotide[j]=NUCLEOTIDE_FOR_CODE(freq);
|
|
||||||
freq>>=2;
|
|
||||||
}
|
|
||||||
oligonucleotide[desiredLength]='\0';
|
|
||||||
// Output the frequency for oligonucleotide to output.
|
|
||||||
output_Position+=snprintf(output+output_Position, MAXIMUM_OUTPUT_LENGTH-output_Position,
|
|
||||||
"%s %.3f\n", oligonucleotide, invSum * count);
|
|
||||||
}
|
|
||||||
|
|
||||||
dict_oligonucleotide_clear(hash_Table);
|
|
||||||
tree_dict_oligonucleotide_clear(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a count for the number of times oligonucleotide appears in
|
|
||||||
// polynucleotide and then save it to output.
|
|
||||||
static void compute_count(polynucleotide_t p, const char oligonucleotide[], char output[])
|
|
||||||
{
|
|
||||||
const size_t oligonucleotide_Length = strlen(oligonucleotide);
|
|
||||||
dict_oligonucleotide_t hash_Table;
|
|
||||||
compute_hash(hash_Table, p, oligonucleotide_Length);
|
|
||||||
|
|
||||||
// Generate the key for oligonucleotide.
|
|
||||||
uint64_t key=0;
|
|
||||||
for(size_t i=0; i<oligonucleotide_Length; i++)
|
|
||||||
key = (key<<2) | CODE_FOR_NUCLEOTIDE(oligonucleotide[i]);
|
|
||||||
|
|
||||||
// Output the count for oligonucleotide to output.
|
|
||||||
uint32_t *val = dict_oligonucleotide_get(hash_Table, key);
|
|
||||||
uintmax_t count= val== NULL ? 0 : *val;
|
|
||||||
snprintf(output, MAXIMUM_OUTPUT_LENGTH, "%ju\t%s", count, oligonucleotide);
|
|
||||||
|
|
||||||
dict_oligonucleotide_clear(hash_Table);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
// Initialize the different worker threads by auto-detecting the number of cores of the system
|
|
||||||
worker_init(worker, -1, 0, NULL);
|
|
||||||
|
|
||||||
// Read the input
|
|
||||||
polynucleotide_t p, *ptr = &p;
|
|
||||||
polynucleotide_init_stream(p, stdin);
|
|
||||||
|
|
||||||
// Prepare outputs
|
|
||||||
char outputBuffer[MAXMUM_NUMBER_OUTPUT][MAXIMUM_OUTPUT_LENGTH];
|
|
||||||
char (*output)[MAXIMUM_OUTPUT_LENGTH] = outputBuffer;
|
|
||||||
|
|
||||||
// Do the following functions in parallel.
|
|
||||||
worker_sync_t block; // Define a synchronization block
|
|
||||||
worker_start(block, worker);
|
|
||||||
|
|
||||||
WORKER_SPAWN(block, (ptr, output), {
|
|
||||||
compute_count(*ptr, "GGTATTTTAATTTATAGT", output[6]);
|
|
||||||
}, (/*no output*/));
|
|
||||||
WORKER_SPAWN(block, (ptr, output), {
|
|
||||||
compute_count(*ptr, "GGTATTTTAATT", output[5]);
|
|
||||||
}, (/*no output*/));
|
|
||||||
WORKER_SPAWN(block, (ptr, output), {
|
|
||||||
compute_count(*ptr, "GGTATT", output[4]);
|
|
||||||
}, (/*no output*/));
|
|
||||||
WORKER_SPAWN(block, (ptr, output), {
|
|
||||||
compute_count(*ptr, "GGTA", output[3]);
|
|
||||||
}, (/*no output*/));
|
|
||||||
compute_count(*ptr, "GGT", output[2]);
|
|
||||||
compute_freq(*ptr, 2, output[1]);
|
|
||||||
compute_freq(p, 1, output[0]);
|
|
||||||
worker_sync(block);
|
|
||||||
|
|
||||||
// Output the results to stdout.
|
|
||||||
for(int i=0; i<MAXMUM_NUMBER_OUTPUT; i++)
|
|
||||||
printf("%s\n", outputBuffer[i]);
|
|
||||||
|
|
||||||
polynucleotide_clear(p);
|
|
||||||
worker_clear(worker);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
-940
@@ -1,940 +0,0 @@
|
|||||||
/**
|
|
||||||
* Memory pool benchmark.
|
|
||||||
*
|
|
||||||
* Results (the better values for each measure from at least 3 runs)for
|
|
||||||
* Intel Core i7-4650U CPU 1.70GHz, 8GB RAM:
|
|
||||||
*
|
|
||||||
* small object size: 24
|
|
||||||
* big object size: 240
|
|
||||||
* huge object size: 8305
|
|
||||||
*
|
|
||||||
* boost::pool (Small): 258ms
|
|
||||||
* boost::pool w/ free (Small): 165ms
|
|
||||||
* boost::pool (Big): 174ms
|
|
||||||
* boost::pool w/ free (Big): 154ms
|
|
||||||
* boost::pool cr. & destr.: 133ms
|
|
||||||
*
|
|
||||||
* ngx_pool (Small): 305ms
|
|
||||||
* ngx_pool (Big): 132ms
|
|
||||||
* ngx_pool w/ free (Mix): 542ms
|
|
||||||
* ngx_pool cr. & destr.: 98ms
|
|
||||||
*
|
|
||||||
* tfw_pool (Small): 279ms
|
|
||||||
* tfw_pool w/ free (Small): 101ms
|
|
||||||
* tfw_pool (Big): 106ms
|
|
||||||
* tfw_pool w/ free (Big): 50ms
|
|
||||||
* tfw_pool w/ free (Mix): 107ms
|
|
||||||
* tfw_pool cr. & destr.: 53ms
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015 Alexander Krizhanovsky (ak@natsys-lab.com).
|
|
||||||
*
|
|
||||||
* This file is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published
|
|
||||||
* by the Free Software Foundation; either version 3, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
* See http://www.gnu.org/licenses/lgpl.html .
|
|
||||||
*
|
|
||||||
* From https://github.com/natsys/blog/tree/master/mempool
|
|
||||||
*/
|
|
||||||
#define NDEBUG
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <functional>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#ifdef USE_BOOST
|
|
||||||
#include <boost/pool/object_pool.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_GLIB
|
|
||||||
#include <glib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const size_t PAGE_SIZE = 4096;
|
|
||||||
|
|
||||||
// sizeof(TfwStr)
|
|
||||||
struct Small {
|
|
||||||
long l[3];
|
|
||||||
|
|
||||||
std::string
|
|
||||||
operator+(const char *str)
|
|
||||||
{ return std::string(str) + " (Small)"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// size of common HTTP headers table
|
|
||||||
struct Big {
|
|
||||||
Small s[10];
|
|
||||||
|
|
||||||
std::string
|
|
||||||
operator+(const char *str)
|
|
||||||
{ return std::string(str) + " (Big)"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// very big allocation
|
|
||||||
struct Huge {
|
|
||||||
char c[PAGE_SIZE * 2 + 113];
|
|
||||||
|
|
||||||
std::string
|
|
||||||
operator+(const char *str)
|
|
||||||
{ return std::string(str) + " (Huge)"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
static const size_t N = 20 * 1000 * 1000;
|
|
||||||
|
|
||||||
void
|
|
||||||
benchmark(std::string &&desc, std::function<void ()> cb)
|
|
||||||
{
|
|
||||||
using namespace std::chrono;
|
|
||||||
|
|
||||||
// steady_clock has the same resolution as high_resolution_clock
|
|
||||||
auto t(steady_clock::now());
|
|
||||||
|
|
||||||
cb();
|
|
||||||
|
|
||||||
auto dt = steady_clock::now() - t;
|
|
||||||
std::cout << std::setw(30) << std::right << desc << ": "
|
|
||||||
<< duration_cast<milliseconds>(dt).count()
|
|
||||||
<< "ms" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define touch_obj(o) \
|
|
||||||
if (__builtin_expect(!o, 0)) { \
|
|
||||||
std::cerr << "failed alloc" << std::endl; \
|
|
||||||
break; \
|
|
||||||
} else { \
|
|
||||||
*(long *)o = 1; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
* Boost::pool
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#ifdef USE_BOOST
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void
|
|
||||||
benchmark_boost_pool()
|
|
||||||
{
|
|
||||||
boost::object_pool<T> p;
|
|
||||||
|
|
||||||
benchmark(std::move(T() + "boost::pool"), [&]() {
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
T *o = p.malloc();
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void
|
|
||||||
benchmark_boost_pool_free()
|
|
||||||
{
|
|
||||||
boost::object_pool<T> p;
|
|
||||||
|
|
||||||
benchmark(std::move(T() + "boost::pool w/ free"), [&]() {
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
T *o = p.malloc();
|
|
||||||
touch_obj(o);
|
|
||||||
if (__builtin_expect(!(i & 3), 0))
|
|
||||||
p.free(o);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
benchmark_boost_pool_create_and_destroy()
|
|
||||||
{
|
|
||||||
benchmark(std::move(std::string("boost::pool cr. & destr.")), []() {
|
|
||||||
for (size_t i = 0; i < N / 100; ++i) {
|
|
||||||
if (__builtin_expect(!(i & 3), 0)) {
|
|
||||||
boost::object_pool<Big> p;
|
|
||||||
for (size_t j = 0; j < 100; ++j) {
|
|
||||||
Big *o = p.malloc();
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
boost::object_pool<Small> p;
|
|
||||||
for (size_t j = 0; j < 100; ++j) {
|
|
||||||
Small *o = p.malloc();
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
* malloc/free
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
template<class T>
|
|
||||||
void
|
|
||||||
benchmark_mallocfree()
|
|
||||||
{
|
|
||||||
benchmark(std::move(T() + "mallocfree"), [&]() {
|
|
||||||
static __thread T *ptrs[N * sizeof(Small) / sizeof(T)];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
T *o = (T*)malloc(sizeof(T));
|
|
||||||
ptrs[i] = o;
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
free(ptrs[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void
|
|
||||||
benchmark_mallocfree_free()
|
|
||||||
{
|
|
||||||
benchmark(std::move(T() + "mallocfree w/ free"), [&]() {
|
|
||||||
static __thread T *ptrs[N * sizeof(Small) / sizeof(T)];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
T *o = (T*)malloc(sizeof(T));
|
|
||||||
ptrs[i] = o;
|
|
||||||
touch_obj(o);
|
|
||||||
|
|
||||||
if (__builtin_expect(!(i & 3), 0)) {
|
|
||||||
free(o);
|
|
||||||
ptrs[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
free(ptrs[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
* GLib slices
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#ifdef USE_GLIB
|
|
||||||
template<class T>
|
|
||||||
void
|
|
||||||
benchmark_glib_slices()
|
|
||||||
{
|
|
||||||
benchmark(std::move(T() + "GLib slices"), [&]() {
|
|
||||||
static __thread T *ptrs[N * sizeof(Small) / sizeof(T)];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
T *o = (T*)g_slice_alloc(sizeof(T));
|
|
||||||
ptrs[i] = o;
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
g_slice_free1(sizeof(T), ptrs[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void
|
|
||||||
benchmark_glib_slices_free()
|
|
||||||
{
|
|
||||||
benchmark(std::move(T() + "GLib slices w/ free"), [&]() {
|
|
||||||
static __thread T *ptrs[N * sizeof(Small) / sizeof(T)];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
T *o = (T*)g_slice_alloc(sizeof(T));
|
|
||||||
ptrs[i] = o;
|
|
||||||
touch_obj(o);
|
|
||||||
|
|
||||||
if (__builtin_expect(!(i & 3), 0)) {
|
|
||||||
g_slice_free1(sizeof(T), o);
|
|
||||||
ptrs[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
g_slice_free1(sizeof(T), ptrs[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
* Nginx pool
|
|
||||||
* Simplified version of src/core/ngx_palloc.c from nginx-1.9.5 with
|
|
||||||
* some code adjustments to be built in this benchmark.
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
struct ngx_pool_t;
|
|
||||||
typedef uintptr_t ngx_uint_t;
|
|
||||||
|
|
||||||
#define NGX_POOL_ALIGNMENT 16
|
|
||||||
#define NGX_ALIGNMENT sizeof(unsigned long)
|
|
||||||
#define ngx_align_ptr(p, a) \
|
|
||||||
(u_char *)(((uintptr_t)(p) + ((uintptr_t)a - 1)) & ~((uintptr_t)a - 1))
|
|
||||||
#define NGX_MAX_ALLOC_FROM_POOL ((size_t)PAGE_SIZE - 1)
|
|
||||||
|
|
||||||
struct ngx_pool_data_t {
|
|
||||||
unsigned char *last;
|
|
||||||
unsigned char *end;
|
|
||||||
ngx_pool_t *next;
|
|
||||||
unsigned int failed;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ngx_pool_large_t {
|
|
||||||
ngx_pool_large_t *next;
|
|
||||||
void *alloc;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ngx_pool_t {
|
|
||||||
ngx_pool_data_t d;
|
|
||||||
size_t max;
|
|
||||||
ngx_pool_t *current;
|
|
||||||
ngx_pool_large_t *large;
|
|
||||||
};
|
|
||||||
|
|
||||||
ngx_pool_t *
|
|
||||||
ngx_create_pool(size_t size)
|
|
||||||
{
|
|
||||||
ngx_pool_t *p;
|
|
||||||
|
|
||||||
if (posix_memalign((void **)&p, NGX_POOL_ALIGNMENT, size))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
p->d.last = (unsigned char *)p + sizeof(ngx_pool_t);
|
|
||||||
p->d.end = (unsigned char *)p + size;
|
|
||||||
p->d.next = NULL;
|
|
||||||
p->d.failed = 0;
|
|
||||||
|
|
||||||
size = size - sizeof(ngx_pool_t);
|
|
||||||
p->max = (size < NGX_MAX_ALLOC_FROM_POOL)
|
|
||||||
? size : NGX_MAX_ALLOC_FROM_POOL;
|
|
||||||
|
|
||||||
p->current = p;
|
|
||||||
p->large = NULL;
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ngx_destroy_pool(ngx_pool_t *pool)
|
|
||||||
{
|
|
||||||
ngx_pool_t *p, *n;
|
|
||||||
ngx_pool_large_t *l;
|
|
||||||
|
|
||||||
for (l = pool->large; l; l = l->next) {
|
|
||||||
if (l->alloc)
|
|
||||||
free(l->alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (p = pool, n = pool->d.next; ; p = n, n = n->d.next) {
|
|
||||||
free(p);
|
|
||||||
if (n == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
ngx_palloc_block(ngx_pool_t *pool, size_t size)
|
|
||||||
{
|
|
||||||
unsigned char *m;
|
|
||||||
size_t psize = (size_t)(pool->d.end - (unsigned char *)pool);
|
|
||||||
ngx_pool_t *p, *p_new;
|
|
||||||
|
|
||||||
if (posix_memalign((void **)&m, NGX_POOL_ALIGNMENT, psize))
|
|
||||||
return NULL;
|
|
||||||
p_new = (ngx_pool_t *)m;
|
|
||||||
|
|
||||||
p_new->d.end = m + psize;
|
|
||||||
p_new->d.next = NULL;
|
|
||||||
p_new->d.failed = 0;
|
|
||||||
|
|
||||||
m += sizeof(ngx_pool_data_t);
|
|
||||||
m = ngx_align_ptr(m, NGX_ALIGNMENT);
|
|
||||||
p_new->d.last = m + size;
|
|
||||||
|
|
||||||
for (p = pool->current; p->d.next; p = p->d.next) {
|
|
||||||
if (p->d.failed++ > 4)
|
|
||||||
pool->current = p->d.next;
|
|
||||||
}
|
|
||||||
p->d.next = p_new;
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ngx_palloc(ngx_pool_t *pool, size_t size);
|
|
||||||
|
|
||||||
static void *
|
|
||||||
ngx_palloc_large(ngx_pool_t *pool, size_t size)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
unsigned int n = 0;
|
|
||||||
ngx_pool_large_t *large;
|
|
||||||
|
|
||||||
p = malloc(size);
|
|
||||||
if (p == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (large = pool->large; large; large = large->next) {
|
|
||||||
if (large->alloc == NULL) {
|
|
||||||
large->alloc = p;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
if (n++ > 3)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
large = (ngx_pool_large_t *)ngx_palloc(pool, sizeof(ngx_pool_large_t));
|
|
||||||
if (large == NULL) {
|
|
||||||
free(p);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
large->alloc = p;
|
|
||||||
large->next = pool->large;
|
|
||||||
pool->large = large;
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
ngx_palloc(ngx_pool_t *pool, size_t size)
|
|
||||||
{
|
|
||||||
unsigned char *m;
|
|
||||||
ngx_pool_t *p;
|
|
||||||
|
|
||||||
if (size <= pool->max) {
|
|
||||||
p = pool->current;
|
|
||||||
do {
|
|
||||||
m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);
|
|
||||||
if ((size_t)(p->d.end - m) >= size) {
|
|
||||||
p->d.last = m + size;
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
p = p->d.next;
|
|
||||||
} while (p);
|
|
||||||
|
|
||||||
return ngx_palloc_block(pool, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ngx_palloc_large(pool, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ngx_pfree(ngx_pool_t *pool, void *p)
|
|
||||||
{
|
|
||||||
ngx_pool_large_t *l;
|
|
||||||
|
|
||||||
for (l = pool->large; l; l = l->next) {
|
|
||||||
if (p == l->alloc) {
|
|
||||||
free(l->alloc);
|
|
||||||
l->alloc = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void
|
|
||||||
benchmark_ngx_pool()
|
|
||||||
{
|
|
||||||
ngx_pool_t *p = ngx_create_pool(PAGE_SIZE);
|
|
||||||
assert(p);
|
|
||||||
|
|
||||||
benchmark(std::move(T() + "ngx_pool"), [=]() {
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
T *o = (T *)ngx_palloc(p, sizeof(T));
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ngx_destroy_pool(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
benchmark_ngx_pool_mix_free()
|
|
||||||
{
|
|
||||||
ngx_pool_t *p = ngx_create_pool(PAGE_SIZE);
|
|
||||||
assert(p);
|
|
||||||
|
|
||||||
benchmark(std::move(std::string("ngx_pool w/ free (Mix)")), [=]() {
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
|
||||||
if (__builtin_expect(!(i & 0xfff), 0)) {
|
|
||||||
Huge *o;
|
|
||||||
o = (Huge *)ngx_palloc(p, sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
if (!(i & 1))
|
|
||||||
ngx_pfree(p, o);
|
|
||||||
}
|
|
||||||
else if (__builtin_expect(!(i & 3), 0)) {
|
|
||||||
Big *o = (Big *)ngx_palloc(p, sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
if (!(i & 1))
|
|
||||||
ngx_pfree(p, o);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Small *o = (Small *)ngx_palloc(p, sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
if (!(i & 1))
|
|
||||||
ngx_pfree(p, o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ngx_destroy_pool(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
benchmark_ngx_pool_create_and_destroy()
|
|
||||||
{
|
|
||||||
benchmark(std::move(std::string("ngx_pool cr. & destr.")), []() {
|
|
||||||
for (size_t i = 0; i < N / 100; ++i) {
|
|
||||||
ngx_pool_t *p = ngx_create_pool(PAGE_SIZE);
|
|
||||||
for (size_t j = 0; j < 100; ++j) {
|
|
||||||
if (__builtin_expect(!(i & 3), 0)) {
|
|
||||||
Big *o;
|
|
||||||
o = (Big *)ngx_palloc(p, sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
} else {
|
|
||||||
Small *o;
|
|
||||||
o = (Small *)ngx_palloc(p, sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ngx_destroy_pool(p);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
* Tempesta FW pool
|
|
||||||
* Simplified and ported to user-space from
|
|
||||||
* https://github.com/natsys/tempesta/blob/master/tempesta_fw/pool.c
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Emulation of Linux buddy allocator.
|
|
||||||
*/
|
|
||||||
#define GFP_ATOMIC 0
|
|
||||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
|
||||||
#define likely(x) __builtin_expect(x, 1)
|
|
||||||
#define unlikely(x) __builtin_expect(x, 0)
|
|
||||||
#define free_pages(p, o) free((void *)(p))
|
|
||||||
#define get_order(n) (assert((n) < PAGE_SIZE * 128), \
|
|
||||||
(n) < PAGE_SIZE ? 0 \
|
|
||||||
: (n) < PAGE_SIZE * 2 ? 1 \
|
|
||||||
: (n) < PAGE_SIZE * 4 ? 2 \
|
|
||||||
: (n) < PAGE_SIZE * 8 ? 3 \
|
|
||||||
: (n) < PAGE_SIZE * 16 ? 4 \
|
|
||||||
: (n) < PAGE_SIZE * 32 ? 5 \
|
|
||||||
: (n) < PAGE_SIZE * 64 ? 6 \
|
|
||||||
: 7)
|
|
||||||
|
|
||||||
static inline unsigned long
|
|
||||||
__get_free_pages(int flags __attribute__((unused)), int order)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
if (posix_memalign((void **)&p, PAGE_SIZE, PAGE_SIZE << order))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return (unsigned long)p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory pool chunk descriptor.
|
|
||||||
*
|
|
||||||
* @next - pointer to next memory chunk;
|
|
||||||
* @order - order of number of pages in the chunk;
|
|
||||||
* @off - current chunk offset;
|
|
||||||
*/
|
|
||||||
struct TfwPoolChunk {
|
|
||||||
TfwPoolChunk *next;
|
|
||||||
unsigned int order;
|
|
||||||
unsigned int off;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory pool descriptor.
|
|
||||||
*
|
|
||||||
* @curr - current chunk to allocate memory from;
|
|
||||||
* @order,@off - cached members of @curr;
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
TfwPoolChunk *curr;
|
|
||||||
unsigned int order;
|
|
||||||
unsigned int off;
|
|
||||||
} TfwPool;
|
|
||||||
|
|
||||||
#define TFW_POOL_CHUNK_SZ(p) (PAGE_SIZE << (p)->order)
|
|
||||||
#define TFW_POOL_CHUNK_BASE(c) ((unsigned long)(c) & PAGE_MASK)
|
|
||||||
#define TFW_POOL_CHUNK_END(p) (TFW_POOL_CHUNK_BASE((p)->curr) + (p)->off)
|
|
||||||
#define TFW_POOL_ALIGN_SZ(n) (((n) + 7) & ~7UL)
|
|
||||||
#define TFW_POOL_HEAD_OFF (TFW_POOL_ALIGN_SZ(sizeof(TfwPool)) \
|
|
||||||
+ TFW_POOL_ALIGN_SZ(sizeof(TfwPoolChunk)))
|
|
||||||
#define TFW_POOL_PGCACHE_SZ 256
|
|
||||||
|
|
||||||
static unsigned int pg_next;
|
|
||||||
static unsigned long pg_cache[TFW_POOL_PGCACHE_SZ];
|
|
||||||
|
|
||||||
static unsigned long
|
|
||||||
tfw_pool_alloc_pages(unsigned int order)
|
|
||||||
{
|
|
||||||
if (likely(pg_next && !order))
|
|
||||||
return pg_cache[--pg_next];
|
|
||||||
return __get_free_pages(GFP_ATOMIC, order);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
tfw_pool_free_pages(unsigned long addr, unsigned int order)
|
|
||||||
{
|
|
||||||
if (likely(pg_next < TFW_POOL_PGCACHE_SZ && !order)) {
|
|
||||||
pg_cache[pg_next++] = addr;
|
|
||||||
} else {
|
|
||||||
free_pages(addr, order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TfwPool *
|
|
||||||
__tfw_pool_new(size_t n)
|
|
||||||
{
|
|
||||||
TfwPool *p;
|
|
||||||
TfwPoolChunk *c;
|
|
||||||
unsigned int order;
|
|
||||||
|
|
||||||
order = get_order(TFW_POOL_ALIGN_SZ(n) + TFW_POOL_HEAD_OFF);
|
|
||||||
|
|
||||||
c = (TfwPoolChunk *)tfw_pool_alloc_pages(order);
|
|
||||||
if (unlikely(!c))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
p = (TfwPool *)((char *)c + TFW_POOL_ALIGN_SZ(sizeof(*c)));
|
|
||||||
c->next = NULL;
|
|
||||||
|
|
||||||
p->order = order;
|
|
||||||
p->off = TFW_POOL_HEAD_OFF;
|
|
||||||
p->curr = c;
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
tfw_pool_alloc(TfwPool *p, size_t n)
|
|
||||||
{
|
|
||||||
void *a;
|
|
||||||
|
|
||||||
n = TFW_POOL_ALIGN_SZ(n);
|
|
||||||
|
|
||||||
if (unlikely(p->off + n > TFW_POOL_CHUNK_SZ(p))) {
|
|
||||||
TfwPoolChunk *c, *curr = p->curr;
|
|
||||||
unsigned int off = TFW_POOL_ALIGN_SZ(sizeof(TfwPoolChunk)) + n;
|
|
||||||
unsigned int order = get_order(off);
|
|
||||||
|
|
||||||
c = (TfwPoolChunk *)tfw_pool_alloc_pages(order);
|
|
||||||
if (!c)
|
|
||||||
return NULL;
|
|
||||||
c->next = curr;
|
|
||||||
|
|
||||||
curr->order = p->order;
|
|
||||||
curr->off = p->off;
|
|
||||||
|
|
||||||
p->order = order;
|
|
||||||
p->off = off;
|
|
||||||
p->curr = c;
|
|
||||||
|
|
||||||
return (void *)TFW_POOL_ALIGN_SZ((unsigned long)(c + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
a = (char *)TFW_POOL_CHUNK_END(p);
|
|
||||||
p->off += n;
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tfw_pool_free(TfwPool *p, void *ptr, size_t n)
|
|
||||||
{
|
|
||||||
n = TFW_POOL_ALIGN_SZ(n);
|
|
||||||
|
|
||||||
/* Stack-like usage is expected. */
|
|
||||||
if (unlikely((char *)ptr + n != (char *)TFW_POOL_CHUNK_END(p)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
p->off -= n;
|
|
||||||
|
|
||||||
/* Free empty chunk which doesn't contain the pool header. */
|
|
||||||
if (unlikely(p->off == TFW_POOL_ALIGN_SZ(sizeof(TfwPoolChunk)))) {
|
|
||||||
TfwPoolChunk *next = p->curr->next;
|
|
||||||
tfw_pool_free_pages(TFW_POOL_CHUNK_BASE(p->curr), p->order);
|
|
||||||
p->curr = next;
|
|
||||||
p->order = next->order;
|
|
||||||
p->off = next->off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tfw_pool_destroy(TfwPool *p)
|
|
||||||
{
|
|
||||||
TfwPoolChunk *c, *next;
|
|
||||||
|
|
||||||
for (c = p->curr; c; c = next) {
|
|
||||||
next = c->next;
|
|
||||||
tfw_pool_free_pages(TFW_POOL_CHUNK_BASE(c), c->order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void
|
|
||||||
benchmark_tfw_pool()
|
|
||||||
{
|
|
||||||
TfwPool *p = __tfw_pool_new(0);
|
|
||||||
assert(p);
|
|
||||||
|
|
||||||
benchmark(std::move(T() + "tfw_pool"), [=]() {
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
T *o = (T *)tfw_pool_alloc(p, sizeof(T));
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tfw_pool_destroy(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void
|
|
||||||
benchmark_tfw_pool_free()
|
|
||||||
{
|
|
||||||
TfwPool *p = __tfw_pool_new(0);
|
|
||||||
assert(p);
|
|
||||||
|
|
||||||
benchmark(std::move(T() + "tfw_pool w/ free"), [&]() {
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(T); ++i) {
|
|
||||||
T *o = (T *)tfw_pool_alloc(p, sizeof(T));
|
|
||||||
touch_obj(o);
|
|
||||||
if (__builtin_expect(!(i & 3), 0))
|
|
||||||
tfw_pool_free(p, o, sizeof(T));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tfw_pool_destroy(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
benchmark_tfw_pool_mix_free()
|
|
||||||
{
|
|
||||||
TfwPool *p = __tfw_pool_new(0);
|
|
||||||
assert(p);
|
|
||||||
|
|
||||||
benchmark(std::move(std::string("tfw_pool w/ free (Mix)")), [=]() {
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
|
||||||
if (__builtin_expect(!(i & 0xfff), 0)) {
|
|
||||||
Huge *o;
|
|
||||||
o = (Huge *)tfw_pool_alloc(p, sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
if (!(i & 1))
|
|
||||||
tfw_pool_free(p, o, sizeof(*o));
|
|
||||||
}
|
|
||||||
else if (__builtin_expect(!(i & 3), 0)) {
|
|
||||||
Big *o = (Big *)tfw_pool_alloc(p, sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
if (!(i & 1))
|
|
||||||
tfw_pool_free(p, o, sizeof(*o));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Small *o;
|
|
||||||
o = (Small *)tfw_pool_alloc(p, sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tfw_pool_destroy(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
benchmark_tfw_pool_create_and_destroy()
|
|
||||||
{
|
|
||||||
benchmark(std::move(std::string("tfw_pool cr. & destr.")), []() {
|
|
||||||
for (size_t i = 0; i < N / 100; ++i) {
|
|
||||||
TfwPool *p = __tfw_pool_new(0);
|
|
||||||
for (size_t j = 0; j < 100; ++j) {
|
|
||||||
if (__builtin_expect(!(i & 3), 0)) {
|
|
||||||
Big *o;
|
|
||||||
o = (Big *)tfw_pool_alloc(p,
|
|
||||||
sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
} else {
|
|
||||||
Small *o;
|
|
||||||
o = (Small *)tfw_pool_alloc(p,
|
|
||||||
sizeof(*o));
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tfw_pool_destroy(p);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Adding M*LIB mempool */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include "m-mempool.h"
|
|
||||||
|
|
||||||
MEMPOOL_DEF(mempool_small, Small)
|
|
||||||
MEMPOOL_DEF(mempool_big, Big)
|
|
||||||
MEMPOOL_DEF(mempool_huge, Huge)
|
|
||||||
|
|
||||||
void
|
|
||||||
benchmark_mempool_small()
|
|
||||||
{
|
|
||||||
mempool_small_t p;
|
|
||||||
mempool_small_init (p);
|
|
||||||
mempool_small_t *ptr = &p; // C++ lambda !
|
|
||||||
|
|
||||||
benchmark(std::move(Small() + "M*LIB mempool"), [=]() {
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(Small); ++i) {
|
|
||||||
Small *o = mempool_small_alloc(*ptr);
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mempool_small_clear(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
benchmark_mempool_big()
|
|
||||||
{
|
|
||||||
mempool_big_t p;
|
|
||||||
mempool_big_init (p);
|
|
||||||
mempool_big_t *ptr = &p; // C++ lambda !
|
|
||||||
|
|
||||||
benchmark(std::move(Big() + "M*LIB mempool"), [=]() {
|
|
||||||
for (size_t i = 0; i < N * sizeof(Small) / sizeof(Big); ++i) {
|
|
||||||
Big *o = mempool_big_alloc(*ptr);
|
|
||||||
touch_obj(o);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mempool_big_clear(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
benchmark_mempool_mix_free()
|
|
||||||
{
|
|
||||||
mempool_small_t s, *ptr_s = &s;
|
|
||||||
mempool_big_t b, *ptr_b = &b;
|
|
||||||
mempool_huge_t h, *ptr_h = &h;
|
|
||||||
|
|
||||||
mempool_small_init (s);
|
|
||||||
mempool_big_init (b);
|
|
||||||
mempool_huge_init (h);
|
|
||||||
|
|
||||||
benchmark(std::move(std::string("M*LIB mempool w/ free (Mix)")), [=]() {
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
|
||||||
if (__builtin_expect(!(i & 0xfff), 0)) {
|
|
||||||
Huge *o = mempool_huge_alloc (*ptr_h);
|
|
||||||
touch_obj(o);
|
|
||||||
if (!(i & 1))
|
|
||||||
mempool_huge_free (*ptr_h, o);
|
|
||||||
}
|
|
||||||
else if (__builtin_expect(!(i & 3), 0)) {
|
|
||||||
Big *o = mempool_big_alloc(*ptr_b);
|
|
||||||
touch_obj(o);
|
|
||||||
if (!(i & 1))
|
|
||||||
mempool_big_free (*ptr_b, o);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Small *o = mempool_small_alloc (*ptr_s);
|
|
||||||
touch_obj(o);
|
|
||||||
if (!(i & 1))
|
|
||||||
mempool_small_free (*ptr_s, o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mempool_small_clear (s);
|
|
||||||
mempool_big_clear (b);
|
|
||||||
mempool_huge_clear (h);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
* Main part of the benchmark
|
|
||||||
* ------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
main()
|
|
||||||
{
|
|
||||||
std::cout << std::setw(35) << std::right << "small object size: "
|
|
||||||
<< sizeof(Small) << std::endl;
|
|
||||||
std::cout << std::setw(35) << std::right << "big object size: "
|
|
||||||
<< sizeof(Big) << std::endl;
|
|
||||||
std::cout << std::setw(35) << std::right << "huge object size: "
|
|
||||||
<< sizeof(Huge) << "\n" << std::endl;
|
|
||||||
|
|
||||||
// Warm up malloc().
|
|
||||||
static const size_t n = N * sizeof(Big);
|
|
||||||
void *p = malloc(n);
|
|
||||||
assert(p);
|
|
||||||
memset(p, 0, n);
|
|
||||||
free(p);
|
|
||||||
|
|
||||||
benchmark_mallocfree<Small>();
|
|
||||||
benchmark_mallocfree_free<Small>();
|
|
||||||
benchmark_mallocfree<Big>();
|
|
||||||
benchmark_mallocfree_free<Big>();
|
|
||||||
std::cout << std::endl;
|
|
||||||
|
|
||||||
#ifdef USE_GLIB
|
|
||||||
benchmark_glib_slices<Small>();
|
|
||||||
benchmark_glib_slices_free<Small>();
|
|
||||||
benchmark_glib_slices<Big>();
|
|
||||||
benchmark_glib_slices_free<Big>();
|
|
||||||
std::cout << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_BOOST
|
|
||||||
benchmark_boost_pool<Small>();
|
|
||||||
benchmark_boost_pool_free<Small>();
|
|
||||||
benchmark_boost_pool<Big>();
|
|
||||||
benchmark_boost_pool_free<Big>();
|
|
||||||
benchmark_boost_pool_create_and_destroy();
|
|
||||||
std::cout << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
benchmark_ngx_pool<Small>();
|
|
||||||
benchmark_ngx_pool<Big>();
|
|
||||||
benchmark_ngx_pool_mix_free();
|
|
||||||
benchmark_ngx_pool_create_and_destroy();
|
|
||||||
std::cout << std::endl;
|
|
||||||
|
|
||||||
benchmark_mempool_small();
|
|
||||||
benchmark_mempool_big();
|
|
||||||
benchmark_mempool_mix_free();
|
|
||||||
std::cout << std::endl;
|
|
||||||
|
|
||||||
benchmark_tfw_pool<Small>();
|
|
||||||
benchmark_tfw_pool_free<Small>();
|
|
||||||
benchmark_tfw_pool<Big>();
|
|
||||||
benchmark_tfw_pool_free<Big>();
|
|
||||||
benchmark_tfw_pool_mix_free();
|
|
||||||
benchmark_tfw_pool_create_and_destroy();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
CC= gcc
|
|
||||||
CXX= g++
|
|
||||||
CFLAGS= -g -Wall -O2 -fomit-frame-pointer -march=native -lm -include stddef.h
|
|
||||||
CXXFLAGS= $(CFLAGS)
|
|
||||||
LDFLAGS=
|
|
||||||
OBJS=
|
|
||||||
LIBS= -lm
|
|
||||||
|
|
||||||
all: run
|
|
||||||
|
|
||||||
benchmarks:
|
|
||||||
git clone https://github.com/attractivechaos/benchmarks.git
|
|
||||||
|
|
||||||
build: benchmarks
|
|
||||||
mkdir -p benchmarks/udb/mlib
|
|
||||||
cp test-mlib.c benchmarks/udb/mlib/test.c
|
|
||||||
cp Makefile-mlib benchmarks/udb/mlib/Makefile
|
|
||||||
mkdir -p benchmarks/udb/mlib-oa
|
|
||||||
cp test-mlib-oa.c benchmarks/udb/mlib-oa/test.c
|
|
||||||
cp Makefile-mlib benchmarks/udb/mlib-oa/Makefile
|
|
||||||
touch build
|
|
||||||
|
|
||||||
all-recur: build
|
|
||||||
cd benchmarks/udb; \
|
|
||||||
wdir=`pwd`; \
|
|
||||||
list_c=`find . -name 'test.c'`; \
|
|
||||||
list_cc=`find . -name 'test.cc'`; \
|
|
||||||
for t in $$list_c $$list_cc ; do \
|
|
||||||
subdir=`dirname $$t`; \
|
|
||||||
cd $$subdir; \
|
|
||||||
$(MAKE) CC="$(CC)" CXX="$(CXX)" DFLAGS="$(DFLAGS)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" || exit 1; \
|
|
||||||
cd $$wdir; \
|
|
||||||
done;
|
|
||||||
|
|
||||||
run: all-recur
|
|
||||||
@cd benchmarks/udb; \
|
|
||||||
echo ; echo "LIBRARY | INT TIME | STR TIME" ; \
|
|
||||||
for i in `find . -name 'test'` ; do \
|
|
||||||
printf "%s|" `dirname $$i|sed -e 's+./++g'`; \
|
|
||||||
$$i -is | awk ' \
|
|
||||||
/\[int data\] # element/ { nbInt= $$5 } \
|
|
||||||
/\[int data\] CPU time/ {timeInt= $$5 } \
|
|
||||||
/\[str data\] # element/ { nbStr= $$5 } \
|
|
||||||
/\[str data\] CPU time/ {timeStr= $$5 } \
|
|
||||||
END { \
|
|
||||||
if (nbInt != 624444) timeInt="BRK" ; \
|
|
||||||
if (nbStr != 624444) timeStr="BRK" ; \
|
|
||||||
print timeInt,"|" ,timeStr \
|
|
||||||
}' ; \
|
|
||||||
done
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf benchmarks build
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
CC= gcc
|
|
||||||
CFLAGS= -g -Wall -O2 -march=native
|
|
||||||
OBJS= ../benchmark/benchmark.o ../runit/runlib.o test.o
|
|
||||||
DFLAGS=
|
|
||||||
INCLUDES= -I../benchmark -I../runit -I../../../../..
|
|
||||||
LIBS=
|
|
||||||
|
|
||||||
.SUFFIXES:.c .o
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) -std=gnu11 -DNDEBUG -c $(INCLUDES) $(CFLAGS) $(DFLAGS) $< -o $@
|
|
||||||
|
|
||||||
all:test
|
|
||||||
|
|
||||||
test:$(OBJS)
|
|
||||||
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)
|
|
||||||
|
|
||||||
cleanlocal:
|
|
||||||
rm -f *.o a.out *~ test
|
|
||||||
|
|
||||||
clean:cleanlocal
|
|
||||||
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "benchmark.h"
|
|
||||||
#include "m-dict.h"
|
|
||||||
#include "m-mempool.h"
|
|
||||||
|
|
||||||
static inline bool oor_equal_p(int k, unsigned char n)
|
|
||||||
{
|
|
||||||
return k == (int)-n - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void oor_set(int *k, unsigned char n)
|
|
||||||
{
|
|
||||||
*k = (int)-n - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DICT_OA_DEF2(dict_int,
|
|
||||||
int, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)),
|
|
||||||
int, M_DEFAULT_OPLIST)
|
|
||||||
|
|
||||||
static const char *const oor[2] = { "EMPTY", "DELETED" };
|
|
||||||
|
|
||||||
static inline bool str_oor_equal_p(const char *k, unsigned char n)
|
|
||||||
{
|
|
||||||
return k == oor[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void str_oor_set(const char * *k, unsigned char n)
|
|
||||||
{
|
|
||||||
*k = oor[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
DICT_OA_DEF2(dict_str, const char *,
|
|
||||||
M_OPEXTEND (M_CSTR_OPLIST, OOR_EQUAL(str_oor_equal_p), OOR_SET(str_oor_set M_IPTR)),
|
|
||||||
int, M_DEFAULT_OPLIST)
|
|
||||||
|
|
||||||
|
|
||||||
int test_int(int N, const unsigned *data)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
M_LET(h, DICT_OPLIST(dict_int)) {
|
|
||||||
for (int i = 0; i < N; ++i) {
|
|
||||||
if (dict_int_get (h, data[i]) == NULL) {
|
|
||||||
dict_int_set_at (h, data[i], i);
|
|
||||||
} else {
|
|
||||||
dict_int_erase(h, data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = (int)dict_int_size(h);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int test_str(int N, char * const *data)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
M_LET(h, DICT_OPLIST(dict_str)) {
|
|
||||||
for (int i = 0; i < N; ++i) {
|
|
||||||
if (dict_str_get (h, data[i]) == NULL) {
|
|
||||||
dict_str_set_at (h, data[i], i);
|
|
||||||
} else {
|
|
||||||
dict_str_erase(h, data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = (int)dict_str_size(h);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
return udb_benchmark(argc, argv, test_int, test_str);
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "benchmark.h"
|
|
||||||
#include "m-dict.h"
|
|
||||||
#include "m-mempool.h"
|
|
||||||
|
|
||||||
DICT_STOREHASH_DEF2(dict_int,
|
|
||||||
int, M_OPEXTEND(M_DEFAULT_OPLIST, MEMPOOL(mpool_int), MEMPOOL_LINKAGE(static)),
|
|
||||||
int, M_DEFAULT_OPLIST)
|
|
||||||
DICT_STOREHASH_DEF2(dict_str,
|
|
||||||
const char *, M_OPEXTEND (M_CSTR_OPLIST, MEMPOOL(mpool_str), MEMPOOL_LINKAGE(static)),
|
|
||||||
int, M_DEFAULT_OPLIST)
|
|
||||||
|
|
||||||
int test_int(int N, const unsigned *data)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
dict_int_list_pair_mempool_init(mpool_int);
|
|
||||||
M_LET(h, DICT_OPLIST(dict_int)) {
|
|
||||||
for (int i = 0; i < N; ++i) {
|
|
||||||
if (dict_int_get (h, data[i]) == NULL) {
|
|
||||||
dict_int_set_at (h, data[i], i);
|
|
||||||
} else {
|
|
||||||
dict_int_erase(h, data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = (int)dict_int_size(h);
|
|
||||||
}
|
|
||||||
dict_int_list_pair_mempool_clear(mpool_int);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int test_str(int N, char * const *data)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
dict_str_list_pair_mempool_init(mpool_str);
|
|
||||||
M_LET(h, DICT_OPLIST(dict_str)) {
|
|
||||||
for (int i = 0; i < N; ++i) {
|
|
||||||
if (dict_str_get (h, data[i]) == NULL) {
|
|
||||||
dict_str_set_at (h, data[i], i);
|
|
||||||
} else {
|
|
||||||
dict_str_erase(h, data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = (int)dict_str_size(h);
|
|
||||||
}
|
|
||||||
dict_str_list_pair_mempool_clear(mpool_str);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
return udb_benchmark(argc, argv, test_int, test_str);
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
CC= gcc
|
|
||||||
CXX= g++
|
|
||||||
CFLAGS= -g -Wall -O2 -fomit-frame-pointer -march=native -lm -include stddef.h
|
|
||||||
CXXFLAGS= $(CFLAGS)
|
|
||||||
LDFLAGS=
|
|
||||||
OBJS=
|
|
||||||
LIBS=
|
|
||||||
|
|
||||||
all: run
|
|
||||||
|
|
||||||
udb2:
|
|
||||||
git clone https://github.com/attractivechaos/udb2.git
|
|
||||||
|
|
||||||
build: udb2
|
|
||||||
mkdir -p udb2/mlib
|
|
||||||
cp test-mlib.c udb2/mlib/test.c
|
|
||||||
cp Makefile-mlib udb2/mlib/Makefile
|
|
||||||
touch build
|
|
||||||
|
|
||||||
all-recur: build
|
|
||||||
cd udb2/stb && make CC="gcc -lm"
|
|
||||||
cd udb2 && for dir in `ls | egrep -v '^(Makefile|common.c|_)'`; do cd $$dir && make && cd -; done
|
|
||||||
|
|
||||||
run: all-recur
|
|
||||||
@cd udb2; \
|
|
||||||
echo ; echo RUNNING BENCH ; echo ; \
|
|
||||||
for i in `find . -name 'run-test'` ; do \
|
|
||||||
echo ; echo `dirname $$i|sed -e 's+./++g'`; \
|
|
||||||
$$i ; \
|
|
||||||
done
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf udb2 build *~
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
all:run-test
|
|
||||||
|
|
||||||
run-test:test.c ../common.c
|
|
||||||
$(CC) -std=gnu99 -O2 -Wall -I../../../.. $< -o $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f run-test* *~
|
|
||||||
rm -rf mlib
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#include "../common.c"
|
|
||||||
#define M_USE_DICT_OA_PROBING(s) 1
|
|
||||||
#include "m-dict.h"
|
|
||||||
|
|
||||||
static inline bool oor_equal_p(unsigned int k, unsigned char n)
|
|
||||||
{
|
|
||||||
return k == (unsigned int)n;
|
|
||||||
}
|
|
||||||
static inline void oor_set(unsigned int *k, unsigned char n)
|
|
||||||
{
|
|
||||||
*k = (unsigned int)n;
|
|
||||||
}
|
|
||||||
|
|
||||||
DICT_OA_DEF2(dict_oa_uint,
|
|
||||||
unsigned int, M_OPEXTEND(M_DEFAULT_OPLIST, HASH(hash_fn), OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)),
|
|
||||||
unsigned int, M_DEFAULT_OPLIST)
|
|
||||||
|
|
||||||
uint32_t test_int(uint32_t n, uint32_t x0)
|
|
||||||
{
|
|
||||||
uint32_t i, x, z = 0;
|
|
||||||
dict_oa_uint_t h;
|
|
||||||
dict_oa_uint_init(h);
|
|
||||||
for (i = 0, x = x0; i < n; ++i) {
|
|
||||||
x = hash32(x);
|
|
||||||
unsigned int key = get_key(n, x);
|
|
||||||
unsigned int *ptr = dict_oa_uint_get_at(h, key);
|
|
||||||
(*ptr)++;
|
|
||||||
z += *ptr;
|
|
||||||
}
|
|
||||||
fprintf(stderr, "# unique keys: %d; checksum: %u\n", (int) dict_oa_uint_size(h), z);
|
|
||||||
z = dict_oa_uint_size(h);
|
|
||||||
dict_oa_uint_clear(h);
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user