2019-05-29 17:18:02 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-12-15 02:08:14 +03:00
/*
* benchmark . c :
* Author : Konstantin Khlebnikov < koct9i @ gmail . com >
*/
# include <linux/radix-tree.h>
# include <linux/slab.h>
# include <linux/errno.h>
# include <time.h>
# include "test.h"
# define NSEC_PER_SEC 1000000000L
static long long benchmark_iter ( struct radix_tree_root * root , bool tagged )
{
volatile unsigned long sink = 0 ;
struct radix_tree_iter iter ;
struct timespec start , finish ;
long long nsec ;
int l , loops = 1 ;
void * * slot ;
# ifdef BENCHMARK
again :
# endif
clock_gettime ( CLOCK_MONOTONIC , & start ) ;
for ( l = 0 ; l < loops ; l + + ) {
if ( tagged ) {
radix_tree_for_each_tagged ( slot , root , & iter , 0 , 0 )
sink ^ = ( unsigned long ) slot ;
} else {
radix_tree_for_each_slot ( slot , root , & iter , 0 )
sink ^ = ( unsigned long ) slot ;
}
}
clock_gettime ( CLOCK_MONOTONIC , & finish ) ;
nsec = ( finish . tv_sec - start . tv_sec ) * NSEC_PER_SEC +
( finish . tv_nsec - start . tv_nsec ) ;
# ifdef BENCHMARK
if ( loops = = 1 & & nsec * 5 < NSEC_PER_SEC ) {
loops = NSEC_PER_SEC / nsec / 4 + 1 ;
goto again ;
}
# endif
nsec / = loops ;
return nsec ;
}
2017-02-27 00:17:00 +03:00
static void benchmark_insert ( struct radix_tree_root * root ,
2018-09-13 06:12:47 +03:00
unsigned long size , unsigned long step )
2017-02-27 00:17:00 +03:00
{
struct timespec start , finish ;
unsigned long index ;
long long nsec ;
clock_gettime ( CLOCK_MONOTONIC , & start ) ;
for ( index = 0 ; index < size ; index + = step )
2018-09-13 06:12:47 +03:00
item_insert ( root , index ) ;
2017-02-27 00:17:00 +03:00
clock_gettime ( CLOCK_MONOTONIC , & finish ) ;
nsec = ( finish . tv_sec - start . tv_sec ) * NSEC_PER_SEC +
( finish . tv_nsec - start . tv_nsec ) ;
2018-09-13 06:12:47 +03:00
printv ( 2 , " Size: %8ld, step: %8ld, insertion: %15lld ns \n " ,
size , step , nsec ) ;
2017-02-27 00:17:00 +03:00
}
static void benchmark_tagging ( struct radix_tree_root * root ,
2018-09-13 06:12:47 +03:00
unsigned long size , unsigned long step )
2017-02-27 00:17:00 +03:00
{
struct timespec start , finish ;
unsigned long index ;
long long nsec ;
clock_gettime ( CLOCK_MONOTONIC , & start ) ;
for ( index = 0 ; index < size ; index + = step )
radix_tree_tag_set ( root , index , 0 ) ;
clock_gettime ( CLOCK_MONOTONIC , & finish ) ;
nsec = ( finish . tv_sec - start . tv_sec ) * NSEC_PER_SEC +
( finish . tv_nsec - start . tv_nsec ) ;
2018-09-13 06:12:47 +03:00
printv ( 2 , " Size: %8ld, step: %8ld, tagging: %17lld ns \n " ,
size , step , nsec ) ;
2017-02-27 00:17:00 +03:00
}
static void benchmark_delete ( struct radix_tree_root * root ,
2018-09-13 06:12:47 +03:00
unsigned long size , unsigned long step )
2017-02-27 00:17:00 +03:00
{
struct timespec start , finish ;
2018-09-13 06:12:47 +03:00
unsigned long index ;
2017-02-27 00:17:00 +03:00
long long nsec ;
clock_gettime ( CLOCK_MONOTONIC , & start ) ;
for ( index = 0 ; index < size ; index + = step )
2018-09-13 06:12:47 +03:00
item_delete ( root , index ) ;
2017-02-27 00:17:00 +03:00
clock_gettime ( CLOCK_MONOTONIC , & finish ) ;
nsec = ( finish . tv_sec - start . tv_sec ) * NSEC_PER_SEC +
( finish . tv_nsec - start . tv_nsec ) ;
2018-09-13 06:12:47 +03:00
printv ( 2 , " Size: %8ld, step: %8ld, deletion: %16lld ns \n " ,
size , step , nsec ) ;
2017-02-27 00:17:00 +03:00
}
2018-09-13 06:12:47 +03:00
static void benchmark_size ( unsigned long size , unsigned long step )
2016-12-15 02:08:14 +03:00
{
RADIX_TREE ( tree , GFP_KERNEL ) ;
long long normal , tagged ;
2018-09-13 06:12:47 +03:00
benchmark_insert ( & tree , size , step ) ;
benchmark_tagging ( & tree , size , step ) ;
2016-12-15 02:08:14 +03:00
tagged = benchmark_iter ( & tree , true ) ;
normal = benchmark_iter ( & tree , false ) ;
2018-09-13 06:12:47 +03:00
printv ( 2 , " Size: %8ld, step: %8ld, tagged iteration: %8lld ns \n " ,
size , step , tagged ) ;
printv ( 2 , " Size: %8ld, step: %8ld, normal iteration: %8lld ns \n " ,
size , step , normal ) ;
2017-02-27 00:17:00 +03:00
2018-09-13 06:12:47 +03:00
benchmark_delete ( & tree , size , step ) ;
2016-12-15 02:08:14 +03:00
item_kill_tree ( & tree ) ;
rcu_barrier ( ) ;
}
void benchmark ( void )
{
unsigned long size [ ] = { 1 < < 10 , 1 < < 20 , 0 } ;
unsigned long step [ ] = { 1 , 2 , 7 , 15 , 63 , 64 , 65 ,
128 , 256 , 512 , 12345 , 0 } ;
int c , s ;
2017-01-04 19:55:00 +03:00
printv ( 1 , " starting benchmarks \n " ) ;
printv ( 1 , " RADIX_TREE_MAP_SHIFT = %d \n " , RADIX_TREE_MAP_SHIFT ) ;
2016-12-15 02:08:14 +03:00
for ( c = 0 ; size [ c ] ; c + + )
for ( s = 0 ; step [ s ] ; s + + )
2018-09-13 06:12:47 +03:00
benchmark_size ( size [ c ] , step [ s ] ) ;
2016-12-15 02:08:14 +03:00
}