Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v5.1] [Heap Trace Standalone] hash map uses doubly linked list, but single linked would be better (IDFGH-9846) #11173

Closed
chipweinberger opened this issue Apr 10, 2023 · 17 comments
Assignees
Labels
Resolution: NA Issue resolution is unavailable Status: Done Issue is done internally Type: Feature Request Feature request for IDF

Comments

@chipweinberger
Copy link
Contributor

chipweinberger commented Apr 10, 2023

@SoucheSouche

Again, thanks for your work on this PR.

It looks like the hash map entries are storing a doubly linked list. i.e. TAILQ

/* Define struct: linked list of records */
TAILQ_HEAD(heap_trace_record_list_struct_t, heap_trace_record_t); 
typedef struct heap_trace_record_list_struct_t heap_trace_record_list_t;
static heap_trace_hash_list_t hash_map[(size_t)CONFIG_HEAP_TRACE_HASH_MAP_SIZE]; // Buffer used for hashmap entries

AFAICT, a singly linked list is all we need, and would save 50% of the memory.

SLIST_HEAD(heap_trace_record_list_struct_t, heap_trace_record_t*);

Thanks again.

@chipweinberger chipweinberger added the Type: Feature Request Feature request for IDF label Apr 10, 2023
@github-actions github-actions bot changed the title [v5.1] [Heap Trace Standalone] hash map uses ~10x more ram than necessary [v5.1] [Heap Trace Standalone] hash map uses ~10x more ram than necessary (IDFGH-9846) Apr 10, 2023
@espressif-bot espressif-bot added the Status: Opened Issue is new label Apr 10, 2023
@chipweinberger chipweinberger changed the title [v5.1] [Heap Trace Standalone] hash map uses ~10x more ram than necessary (IDFGH-9846) [v5.1] [Heap Trace Standalone] hash map uses more ram than necessary (IDFGH-9846) Apr 11, 2023
@chipweinberger
Copy link
Contributor Author

I edited this issue. Hopefully your internal issue tracker supports edits.

@chipweinberger chipweinberger changed the title [v5.1] [Heap Trace Standalone] hash map uses more ram than necessary (IDFGH-9846) [v5.1] [Heap Trace Standalone] hash map uses doubly linked list when single linked list would suffice (IDFGH-9846) Apr 11, 2023
@chipweinberger chipweinberger changed the title [v5.1] [Heap Trace Standalone] hash map uses doubly linked list when single linked list would suffice (IDFGH-9846) [v5.1] [Heap Trace Standalone] hash map uses doubly linked list when single linked list would be better (IDFGH-9846) Apr 11, 2023
@chipweinberger chipweinberger changed the title [v5.1] [Heap Trace Standalone] hash map uses doubly linked list when single linked list would be better (IDFGH-9846) [v5.1] [Heap Trace Standalone] hash map uses doubly linked list, but single linked list would be better (IDFGH-9846) Apr 11, 2023
@chipweinberger chipweinberger changed the title [v5.1] [Heap Trace Standalone] hash map uses doubly linked list, but single linked list would be better (IDFGH-9846) [v5.1] [Heap Trace Standalone] hash map uses doubly linked list, but single linked would be better (IDFGH-9846) Apr 11, 2023
@chipweinberger
Copy link
Contributor Author

chipweinberger commented Apr 11, 2023

Note, the records themselves are doubly linked because:

  • during freeing, we traverse backwards
  • during printing, we traverse forwards (chronological)

But the hash map does not need this feature.

Also, because the hash map should be large as possible to avoid collisions, we care more that each entry is as small as possible.

@SoucheSouche
Copy link
Collaborator

SoucheSouche commented Apr 12, 2023

Hi @chipweinberger, thanks for reporting this. It is true that we could use a singly linked list in the hashmap. I will update the feature and get back to you with perf results.

@SoucheSouche
Copy link
Collaborator

So it seems that the SLIST has a complexity of O(n) when removing elements from the list. Meanwhile, TAILQ has a complexity of O(1) while removing. To get the same perf with the SLIST has we have with the TAILQ, we have to increase the size of the hashmap in a way that results in taking more memory space than with TAILQ.

@chipweinberger
Copy link
Contributor Author

chipweinberger commented Apr 12, 2023

STAILQ is more appropriate than SLIST. (my bad)

STAILQ lets you remove from the end in O(1)

SLIST lets you remove from the begining in O(1)

@SoucheSouche
Copy link
Collaborator

SoucheSouche commented Apr 12, 2023

SLIST_REMOVE and STAILQ_REMOVE are traversing the entire list. Only TAILQ_REMOVE allows for O(1) removal from the list. So I will keep using the doubly linked list.

@chipweinberger
Copy link
Contributor Author

Ya, thats a good point. Looking at the code, you are right.

Closing this.

@espressif-bot espressif-bot added Resolution: Won't Do This will not be worked on Status: Done Issue is done internally and removed Status: In Progress Work is in progress labels Apr 13, 2023
@chipweinberger
Copy link
Contributor Author

chipweinberger commented May 26, 2023

We actually could support this.

To use SLIST (saving 50% of the ram!) without hurting perf, we need to replace map_find (which already does a linear traversal), with new methods map_find_and_remove + list_find_and_remove, that way we can traverse the list and remove it at the same time.

This would require a small code change.

       
        if (r_found) {
            if (mode == HEAP_TRACE_ALL) {

                heap_trace_record_t *r_found = list_find(p);

                // add 'freed_by' info to the record
                memcpy(r_found->freed_by, callers, sizeof(void *) * STACK_DEPTH);

            } else { // HEAP_TRACE_LEAKS

                heap_trace_record_t *r_found = list_find_and_remove(p);

                // Leak trace mode, once an allocation is freed
                // we remove it from the list & hashmap
                list_remove(r_found);
            }
        }

@espressif-bot espressif-bot added the Status: Opened Issue is new label Oct 4, 2023
@espressif-bot espressif-bot added Status: In Progress Work is in progress Status: Selected for Development Issue is selected for development and removed Status: Done Issue is done internally Resolution: Won't Do This will not be worked on Status: Opened Issue is new Status: In Progress Work is in progress labels Oct 4, 2023
@SoucheSouche
Copy link
Collaborator

SoucheSouche commented Oct 4, 2023

Hi @chipweinberger, I am finally back from my extended leave! I will take a look at that idea as soon as I can :) I'll keep you posted!

@chipweinberger
Copy link
Contributor Author

Wow nice to hear from you! I was wondering what happened to you =P

Hope you enjoyed your time off!

@SoucheSouche
Copy link
Collaborator

yes I did very much! I was on paternity leave :)

@SoucheSouche
Copy link
Collaborator

@chipweinberger , I had a look at the code. I am not sure I follow you here. Are you suggesting to make only hash_map a singly linked list?

@chipweinberger
Copy link
Contributor Author

chipweinberger commented Oct 12, 2023

correct

Note, the records themselves are doubly linked because:

  • during freeing, we traverse backwards
  • during printing, we traverse forwards (chronological)

But the hash map does not need this feature.

Also, because the hash map should be large as possible to avoid collisions, we care more that each entry is as small as possible.

@SoucheSouche
Copy link
Collaborator

I will update hash_map to a singly linked list.

@espressif-bot espressif-bot added Status: In Progress Work is in progress Status: Reviewing Issue is being reviewed and removed Status: Selected for Development Issue is selected for development Status: In Progress Work is in progress labels Oct 12, 2023
@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: NA Issue resolution is unavailable and removed Status: Reviewing Issue is being reviewed labels Oct 23, 2023
@SoucheSouche
Copy link
Collaborator

The update of the hash map was merged internally.

@chipweinberger
Copy link
Contributor Author

awesome! glad it worked out!

@SoucheSouche
Copy link
Collaborator

the update will be available on next github sync. I will close the issue now.

espressif-bot pushed a commit that referenced this issue Oct 25, 2023
Previously, the hash map was a doubly linked list but was never
using the characteristics of it.

This commit switches the hash map to a singly linked list instead

This commit also fixes memory leak in heap trace tests by setting
hashmap size to 10 for the tests (instead of the default value of 250)

See #11173
movsb pushed a commit to movsb/esp-idf that referenced this issue Dec 1, 2023
Previously, the hash map was a doubly linked list but was never
using the characteristics of it.

This commit switches the hash map to a singly linked list instead

This commit also fixes memory leak in heap trace tests by setting
hashmap size to 10 for the tests (instead of the default value of 250)

See espressif#11173
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: NA Issue resolution is unavailable Status: Done Issue is done internally Type: Feature Request Feature request for IDF
Projects
None yet
Development

No branches or pull requests

3 participants