Use vectors for storage, to cut down on cache-misses.

This commit is contained in:
2025-09-16 22:43:11 -04:00
parent 905a01efd3
commit e8e2027a1a
2 changed files with 19 additions and 10 deletions

View File

@ -277,7 +277,7 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
int int
main() main()
{ {
std::deque< std::string > program; std::vector< std::string > program;
while( std::cin ) while( std::cin )
{ {

View File

@ -12,6 +12,9 @@ static_assert( __cplusplus >= 2023'02 );
#include <string> #include <string>
#include <variant> #include <variant>
#include <deque> #include <deque>
#include <list>
#include <boost/container/flat_map.hpp>
namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
{ {
@ -36,20 +39,26 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
// It grows on the "back". // It grows on the "back".
// A `std::deque` is used instead of `std::vector`, because // A `std::deque` is used instead of `std::vector`, because
// it helps cut down on large allocations, by subdividing things. // it helps cut down on large allocations, by subdividing things.
std::deque< std::variant< std::string, Integer > > stack; std::vector< std::variant< std::string, Integer > > stack;
// TODO: Should these tokens be binary? // TODO: Should these tokens be binary?
// Upside: compressed. // Upside: compressed.
// Downside: more memory management in the machine end? // Downside: more memory management in the machine end?
std::deque< std::string > tokens;
// It's `void *` to break the cycle with itself
struct TokenHolder;
//using Token= std::variant< std::string, TokenHolder * >;
using Token= std::string;
std::vector< std::string > tokens;
struct Tokenizer struct Tokenizer
{ {
std::deque< std::string >::const_iterator pos; std::vector< Token >::const_iterator pos;
std::deque< std::string >::const_iterator end; std::vector< Token >::const_iterator end;
explicit explicit
Tokenizer( const std::deque< std::string > &tokens ) Tokenizer( const std::vector< Token > &tokens )
: pos( tokens.begin() ), end( tokens.end() ) {} : pos( tokens.begin() ), end( tokens.end() ) {}
bool hasNext() const { return pos != end; } bool hasNext() const { return pos != end; }
@ -60,8 +69,8 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
std::vector< Tokenizer > tokenStack; std::vector< Tokenizer > tokenStack;
std::deque< std::string > wordNames; std::list< std::string > wordNames;
std::unordered_map< std::string_view, std::deque< std::string > > words; std::unordered_map< std::string_view, std::vector< std::string > > words;
// Which side of the current conditional to take. // Which side of the current conditional to take.
enum ConditionalState { If, Else, Skipped }; enum ConditionalState { If, Else, Skipped };
@ -78,7 +87,7 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
void runWord( std::string_view word ); void runWord( std::string_view word );
std::variant< std::string, Integer > pop(); std::variant< std::string, Integer > pop();
const std::variant< std::string, Integer > &peek(); std::variant< std::string, Integer > &peek();
void push( std::string s ); void push( std::string s );
void push( Integer s ); void push( Integer s );
@ -99,7 +108,7 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
StackMachine( std::ostream &output= std::cout ); StackMachine( std::ostream &output= std::cout );
void void
loadProgram( std::deque< std::string > tokens ) loadProgram( std::vector< std::string > tokens )
{ {
this->tokens= std::move( tokens ); this->tokens= std::move( tokens );
tokenStack.clear(); tokenStack.clear();