File: test_hash_map_block_cache.cpp

package info (click to toggle)
libstxxl 1.4.1-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,476 kB
  • sloc: cpp: 45,101; ansic: 4,071; perl: 610; sh: 555; xml: 174; makefile: 18
file content (155 lines) | stat: -rw-r--r-- 5,792 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/***************************************************************************
 *  tests/containers/hash_map/test_hash_map_block_cache.cpp
 *
 *  Part of the STXXL. See http://stxxl.sourceforge.net
 *
 *  Copyright (C) 2007 Markus Westphal <marwes@users.sourceforge.net>
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt)
 **************************************************************************/

#include <iostream>

#include <stxxl.h>
#include <stxxl/bits/common/seed.h>
#include <stxxl/bits/containers/hash_map/block_cache.h>

bool test_block_cache()
{
    typedef std::pair<int, int> value_type;

    const unsigned subblock_raw_size = 1024 * 8; // 8KB subblocks
    const unsigned block_size = 128;             // 1MB blocks (=128 subblocks)

    const unsigned num_blocks = 64;              // number of blocks to use for this test
    const unsigned cache_size = 8;               // size of cache in blocks

    typedef stxxl::typed_block<subblock_raw_size, value_type> subblock_type;
    typedef stxxl::typed_block<block_size* sizeof(subblock_type), subblock_type> block_type;

    const unsigned subblock_size = subblock_type::size;          // size in values

    typedef block_type::bid_type bid_type;
    typedef std::vector<bid_type> bid_container_type;

    // prepare test: allocate blocks, fill them with values and write to disk
    bid_container_type bids(num_blocks);
    stxxl::block_manager* bm = stxxl::block_manager::get_instance();
    bm->new_blocks(stxxl::striping(), bids.begin(), bids.end());

    block_type* block = new block_type;
    for (unsigned i_block = 0; i_block < num_blocks; i_block++) {
        for (unsigned i_subblock = 0; i_subblock < block_size; i_subblock++) {
            for (unsigned i_value = 0; i_value < subblock_size; i_value++) {
                int value = i_value + i_subblock * subblock_size + i_block * block_size;
                (*block)[i_subblock][i_value] = value_type(value, value);
            }
        }
        stxxl::request_ptr req = block->write(bids[i_block]);
        req->wait();
    }

    stxxl::random_number32 rand32;

    // create block_cache
    typedef stxxl::hash_map::block_cache<block_type> cache_type;
    cache_type cache(cache_size);

    // load random subblocks and check for values
    int n_runs = cache_size * 10;
    for (int i_run = 0; i_run < n_runs; i_run++) {
        int i_block = rand32() % num_blocks;
        int i_subblock = rand32() % block_size;

        subblock_type* subblock = cache.get_subblock(bids[i_block], i_subblock);

        int expected = i_block * block_size + i_subblock * subblock_size + 1;
        STXXL_CHECK((*subblock)[1].first == expected);
    }

    // do the same again but this time with prefetching
    for (int i_run = 0; i_run < n_runs; i_run++) {
        int i_block = rand32() % num_blocks;
        int i_subblock = rand32() % block_size;

        cache.prefetch_block(bids[i_block]);
        subblock_type* subblock = cache.get_subblock(bids[i_block], i_subblock);
        int expected = i_block * block_size + i_subblock * subblock_size + 1;
        STXXL_CHECK((*subblock)[1].first == expected);
    }

    // load and modify some subblocks; flush cache and check values
    unsigned myseed = stxxl::get_next_seed();
    stxxl::set_seed(myseed);
    for (int i_run = 0; i_run < n_runs; i_run++) {
        int i_block = rand32() % num_blocks;
        int i_subblock = rand32() % block_size;

        subblock_type* subblock = cache.get_subblock(bids[i_block], i_subblock);

        STXXL_CHECK(cache.make_dirty(bids[i_block]));
        (*subblock)[1].first = (*subblock)[1].second + 42;
    }
    stxxl::set_seed(myseed);
    for (int i_run = 0; i_run < n_runs; i_run++) {
        int i_block = rand32() % num_blocks;
        int i_subblock = rand32() % block_size;
        subblock_type* subblock = cache.get_subblock(bids[i_block], i_subblock);

        int expected = i_block * block_size + i_subblock * subblock_size + 1;
        STXXL_CHECK((*subblock)[1].first == expected + 42);
    }

    // test retaining
    cache.clear();

    // not yet cached
    STXXL_CHECK(cache.retain_block(bids[0]) == false);
    cache.prefetch_block(bids[0]);

    // cached, should be retained
    STXXL_CHECK(cache.retain_block(bids[0]) == true);
    // release again
    STXXL_CHECK(cache.release_block(bids[0]) == true);
    // retrain-count should be 0, release fails
    STXXL_CHECK(cache.release_block(bids[0]) == false);

    // cache new block
    subblock_type* kicked_subblock = cache.get_subblock(bids[1], 0);
    // load other blocks, so that kicked_subblock, well, gets kicked
    for (unsigned i = 0; i < cache_size + 5; i++) {
        cache.prefetch_block(bids[i + 3]);
    }
    // load kicked subblock again, should be at a different location
    STXXL_CHECK(cache.get_subblock(bids[1], 0) != kicked_subblock);

    subblock_type* retained_subblock = cache.get_subblock(bids[1], 0);
    // now retain subblock
    STXXL_CHECK(cache.retain_block(bids[1]) == true);
    for (unsigned i = 0; i < cache_size + 5; i++) {
        cache.prefetch_block(bids[i + 3]);
    }
    // retained_subblock should not have been kicked
    STXXL_CHECK(cache.get_subblock(bids[1], 0) == retained_subblock);
    cache.clear();

    // test swapping
    subblock_type* a_subblock = cache.get_subblock(bids[6], 1);
    cache_type cache2(cache_size / 2);
    std::swap(cache, cache2);
    STXXL_CHECK(cache.size() == cache_size / 2);
    STXXL_CHECK(cache2.size() == cache_size);
    STXXL_CHECK(cache2.get_subblock(bids[6], 1) == a_subblock);

    STXXL_MSG("Passed Block-Cache Test");

    return true;
}

int main()
{
    test_block_cache();
    return 0;
}