add some caching and speed it up