diff --git a/include/sigar_util.h b/include/sigar_util.h
index da4a7a79..26f64bfa 100644
--- a/include/sigar_util.h
+++ b/include/sigar_util.h
@@ -69,4 +69,17 @@ double sigar_file_system_usage_calc_used(sigar_t *sigar,
 
 void sigar_cpu_model_adjust(sigar_t *sigar, sigar_cpu_info_t *info);
 
+typedef struct sigar_cache_entry_t sigar_cache_entry_t;
+
+struct sigar_cache_entry_t {
+    sigar_cache_entry_t *next;
+    sigar_uint64_t id;
+    void *value;
+};
+
+typedef struct {
+    sigar_cache_entry_t **entries;
+    unsigned int count, size;
+} sigar_cache_t;
+
 #endif /* SIGAR_UTIL_H */
diff --git a/src/sigar_cache.c b/src/sigar_cache.c
new file mode 100644
index 00000000..0dc6181c
--- /dev/null
+++ b/src/sigar_cache.c
@@ -0,0 +1,81 @@
+#include "sigar.h"
+#include "sigar_private.h"
+#include "sigar_util.h"
+
+/*
+ * hash table to cache values where key is a unique number
+ * such as:
+ *  pid -> some process data
+ *  uid -> user name
+ *  gid -> group name
+ */
+
+#define ENTRIES_SIZE(n) \
+    (sizeof(sigar_cache_entry_t *) * (n))
+
+sigar_cache_t *sigar_cache_new(int size)
+{
+    sigar_cache_t *table = malloc(sizeof(*table));
+    table->count = 0;
+    table->size = size;
+    table->entries = malloc(ENTRIES_SIZE(size));
+    memset(table->entries, '\0', ENTRIES_SIZE(size));
+    return table;
+}
+
+sigar_cache_entry_t *sigar_cache_get(sigar_cache_t *table,
+                                     sigar_uint64_t key)
+{
+    sigar_cache_entry_t *entry, **ptr;
+
+    for (ptr = table->entries + (key % table->size), entry = *ptr;
+         entry; ptr = &entry->next, entry = *ptr)
+    {
+        if (entry->id == key) {
+            return entry;
+        }
+    }
+
+    if (table->count++ > table->size) {
+        unsigned int new_size = table->size * 2;
+
+        table->entries =
+            realloc(table->entries, ENTRIES_SIZE(new_size));
+
+        memset(table->entries + table->size, '\0',
+               ENTRIES_SIZE(new_size - table->size));
+
+        table->size = new_size;
+    }
+
+    *ptr = entry = malloc(sizeof(*entry));
+    entry->id = key;
+    entry->value = NULL;
+    entry->next = NULL;
+
+    return entry;
+}
+
+void sigar_cache_destroy(sigar_cache_t *table)
+{
+    int i;
+    sigar_cache_entry_t **entries = table->entries;
+
+    for (i=0; i<table->size; i++) {
+        sigar_cache_entry_t *entry, *ptr;
+        entry = ptr = *entries++;
+
+        if (!entry) {
+            continue;
+        }
+
+        do {
+            if (ptr->value) {
+                free(ptr->value);
+            }
+        } while (ptr = ptr->next);
+        free(entry);
+    }
+
+    free(table->entries);
+}