>From 7f1d677f3d085b5891e1adbd5f602185d68ba81a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 22 Apr 2016 12:50:00 -0700 Subject: fixup to {09,10,11}/11 diff --git a/include/qemu/qht.h b/include/qemu/qht.h index a0a1aa8..2d0b58f 100644 --- a/include/qemu/qht.h +++ b/include/qemu/qht.h @@ -49,6 +49,14 @@ void qht_grow(struct qht *ht); void *qht_lookup(struct qht *ht, qht_lookup_func_t func, const void *userp, uint32_t hash); -double qht_avg_bucket_chain_length(struct qht *ht, size_t *n_head_buckets); + +struct qht_stats { + size_t used_buckets; + size_t max_buckets; + size_t used_entries; + size_t max_chain; +}; + +struct qht_stats qht_statistics(struct qht *ht); #endif /* QHT_H */ diff --git a/translate-all.c b/translate-all.c index 3b73b46..a9ceb0a 100644 --- a/translate-all.c +++ b/translate-all.c @@ -1664,8 +1664,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) { size_t target_code_size, max_target_code_size; unsigned direct_jmp_count, direct_jmp2_count, cross_page; - unsigned used_buckets, max_chain, hash_tbs; - TranslationBlock *tb; + struct qht_stats hinfo; int i; target_code_size = 0; @@ -1673,35 +1672,23 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) cross_page = 0; direct_jmp_count = 0; direct_jmp2_count = 0; - used_buckets = 0; - hash_tbs = 0; - max_chain = 0; - - for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) { - if (tcg_ctx.tb_ctx.tb_phys_hash[i]) { - unsigned this_chain = 0; - for (tb = tcg_ctx.tb_ctx.tb_phys_hash[i]; tb != NULL; - tb = tb->phys_hash_next) { - this_chain++; - hash_tbs++; - target_code_size += tb->size; - if (tb->page_addr[1] != -1) { - cross_page++; - } - if (tb->tb_next_offset[0] != 0xffff) { - direct_jmp_count++; - if (tb->tb_next_offset[1] != 0xffff) { - direct_jmp2_count++; - } - } - } - if (this_chain > max_chain) { - max_chain = this_chain; + + for (i = 0; i < tcg_ctx.tb_ctx.nb_tbs; i++) { + const TranslationBlock *tb = &tcg_ctx.tb_ctx.tbs[i]; + target_code_size += tb->size; + if (tb->page_addr[1] != -1) { + cross_page++; + } + if (tb->tb_next_offset[0] != 0xffff) { + direct_jmp_count++; + if (tb->tb_next_offset[1] != 0xffff) { + direct_jmp2_count++; } - used_buckets++; } } - assert(hash_tbs == + + hinfo = qht_statistics(&tcg_ctx.tb_ctx.htable); + assert(hinfo.used_entries == tcg_ctx.tb_ctx.nb_tbs - tcg_ctx.tb_ctx.tb_phys_invalidate_count); cpu_fprintf(f, "Translation buffer state:\n"); @@ -1731,11 +1718,12 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) direct_jmp2_count, tcg_ctx.tb_ctx.nb_tbs ? (direct_jmp2_count * 100) / tcg_ctx.tb_ctx.nb_tbs : 0); - cpu_fprintf(f, "TB hash buckets %u/%d\n", - used_buckets, CODE_GEN_PHYS_HASH_SIZE); - cpu_fprintf(f, "TB hash avg chain %0.3f max=%u\n", - used_buckets ? (double)hash_tbs / used_buckets : 0.0, - max_chain); + cpu_fprintf(f, "TB hash buckets %zu/%zu\n", + hinfo.used_buckets, hinfo.max_buckets); + cpu_fprintf(f, "TB hash avg chain %0.3f max=%zu\n", + hinfo.used_buckets + ? (double)hinfo.used_entries / hinfo.used_buckets : 0.0, + hinfo.max_chain); cpu_fprintf(f, "\nStatistics:\n"); cpu_fprintf(f, "TB flush count %d\n", tcg_ctx.tb_ctx.tb_flush_count); cpu_fprintf(f, "TB invalidate count %d\n", diff --git a/util/qht.c b/util/qht.c index 05ea5e8..535057b 100644 --- a/util/qht.c +++ b/util/qht.c @@ -556,35 +556,45 @@ void qht_grow(struct qht *ht) * value should be close to 1. * Note that each bucket tracks up to QHT_BUCKET_ENTRIES items. */ -double qht_avg_bucket_chain_length(struct qht *ht, size_t *n_head_buckets) +struct qht_stats qht_statistics(struct qht *ht) { struct qht_map *map; - size_t count = 0; - size_t i; + struct qht_stats s = {}; + size_t i, n; map = atomic_read(&ht->map); /* paired with smp_wmb() before setting ht->map */ smp_rmb(); + s.max_buckets = n = map->n; - for (i = 0; i < map->n; i++) { + for (i = 0; i < n; i++) { struct qht_bucket *head = &map->buckets[i]; struct qht_bucket *b; - size_t bucket_count; + size_t this_chain; uint32_t version; do { version = seqlock_read_begin(&head->sequence); - bucket_count = 0; + this_chain = 0; b = head; do { - bucket_count++; + int j; + for (j = 0; j < QHT_BUCKET_ENTRIES; j++) { + if (b->hashes[j]) { + this_chain++; + } + } b = b->next; } while (b); } while (seqlock_read_retry(&head->sequence, version)); - count += bucket_count; - } - if (n_head_buckets) { - *n_head_buckets = map->n; + if (this_chain != 0) { + s.used_entries += this_chain; + if (s.max_chain < this_chain) { + s.max_chain = this_chain; + } + s.used_buckets++; + } } - return (double)count / map->n; + + return s; }