7

I am looking for minimalistic alternative for std::map<long, int>, which would go into Windows kernel driver, so it should be quite fast.. it is expected to hold a relatively small (~200 in working set) amount of keys and a large amount of inserts.

Looking for solution that can cut key search cost.

kagali-san
  • 2,964
  • 7
  • 48
  • 87
  • If you're feeling daring, you can implement your own hash map - if it has a very specific use, you could make it very efficient and as minimal as needed. – RageD Sep 19 '11 at 15:47
  • 1
    "which change value often." - That is, the keys are mostly frozen but there are lots of inserts with the same keys? –  Sep 19 '11 at 15:47
  • @delnan, yes, for single key there is about 100-200 changes per lifetime – kagali-san Sep 19 '11 at 15:49
  • 3
    Have you proven `std::map` is too slow? – AJG85 Sep 19 '11 at 15:57
  • I'd go with an AVL tree, but I'll leave for someone who can link you a such for windows to answer. – Per Johansson Sep 19 '11 at 15:59
  • 2
    @AJG85: stl code can throw exceptions, he said he's looking to put this code in a driver so stl cannot be used (if he's sane) – James Sep 19 '11 at 16:25
  • @James oops glossed over that apparently. He may still be able to use a fixed container size to avoid exceptions. – AJG85 Sep 19 '11 at 16:36

7 Answers7

8

Already done for you.

See the RtlXxxGenericTable and RtlXxxGenericTableAvl calls.

  • RtlInitializeElementGenericTable
  • RtlDeleteElementGenericTable
  • RtlEnumerateGenericTable
  • RtlEnumerateGenericTableWithoutSplaying
  • RtlGetElementGenericTable
  • RtlInsertElementGenericTable
  • RtlLookupElementGenericTable
  • RtlNumberGenericTableElements

  • RtlInitializeElementGenericTableAvl

  • RtlDeleteElementGenericTableAvl
  • RtlEnumerateGenericTableAvl
  • RtlGetElementGenericTableAvl
  • RtlInitializeGenericTable
  • RtlInsertElementGenericTableAvl
  • RtlLookupElementGenericTableAvl
  • RtlNumberGenericTableElementsAvl
mheyman
  • 4,211
  • 37
  • 34
3

If the number of keys is very small, e.g. 10 or something, perhaps you can get away with just a linear search. If you take care to keep the key-space compressed in memory to maximise cache hits, it can be pretty fast and have very low overhead in terms of memory allocations and so on.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 3
    If you keep the keys in order, you can do a binary search without the need for a special data structure. Insertions may be a little expensive (but really they aren't), but lookup is fast and storage is efficient. – Kerrek SB Sep 19 '11 at 15:57
  • Insertions can be made nearly O(log(n)) if nodes are gapped, which should have minimal impact on lookup _as long as_ the tree remains at least half-full. – Mooing Duck Sep 19 '11 at 18:12
3

You could implement std::map semantics in C as well. Only that it will not be template.

Here is the start:

struct KeyValuePair
{
   KeyType key;
   ValueType value;
};

struct Map
{
   KeyValuePair *list; //it can be linkedlist as well
};

//these are the interfaces which operate on map
void Insert(Map * map, KeyType key, ValueType value);
void Update(Map * map, KeyType key, ValueType value);
int Find(Map * map, KeyType key, ValueType *outValue);

//Implement Get in terms of Find
ValueType Get(Map * map, KeyType key)
{
     ValueType value;
     Find(map, key, &value);
     return value;
}
John Humphreys
  • 37,047
  • 37
  • 155
  • 255
Nawaz
  • 353,942
  • 115
  • 666
  • 851
3

In the past, for maps with less than a few thousand objects, I've found that creating a std::vector sorted on the key value that is then searched for using a binary search is significantly faster than using a std::map.

Goz
  • 61,365
  • 24
  • 124
  • 204
  • This is not the case if you use a faster allocator for the map. Both GCC (__gnu_cxx::pool_allocator) and MSVC (stdext::allocator_variable_size) come with allocators designed for this purpose. I don't understand when to use which of MSVC's though. I'll have to test sometime. – Mooing Duck Sep 19 '11 at 18:20
2

STL map implementation is a red-black tree I believe

http://en.wikipedia.org/wiki/Map_%28C%2B%2B%29

http://en.wikipedia.org/wiki/Self-balancing_binary_search_tree

Bob Yoplait
  • 2,421
  • 1
  • 23
  • 35
  • +1 for trees. if you know there's an upper limit on how many nodes you'll need, statically allocate them and have a stack of free nodes instead of doing a malloc() for every insert. – Brian McFarland Sep 19 '11 at 17:10
  • @Brian: Tree is a horrible structure for kernal modules (lots of pointers). In kernal mode you should prefer fixed size structures (or with very few moving parts). Though you can implement a balanced tree using an array. – Martin York Sep 19 '11 at 18:13
  • Please explain. In C, arrays are little more than syntactic sugar for pointers. W/ regard to fixed-size, that's why i suggested statically allocating a pool of nodes. – Brian McFarland Sep 19 '11 at 18:43
  • @Brian: Arrays decay into pointers. That does not make them the same. – Martin York Sep 19 '11 at 19:05
1

You'll need two companion arrays in C: one for keys, the other for values. It'd help if you could encapsulate the two so users could stick to map semantics.

duffymo
  • 305,152
  • 44
  • 369
  • 561
1

If you need a simple implementation of a dictionary in C, it's funnier to implement a dictionary in C one day... but we don't have always time to do it.

So you could try to have a look to iniparser module one, it is a little dictionary usable in a kernel and/or embedded world.

Cédric Julien
  • 78,516
  • 15
  • 127
  • 132