diff options
Diffstat (limited to '')
-rw-r--r-- | ltable.c | 27 |
1 files changed, 20 insertions, 7 deletions
@@ -471,12 +471,23 @@ typedef struct { | |||
471 | unsigned nums[MAXABITS + 1]; | 471 | unsigned nums[MAXABITS + 1]; |
472 | } Counters; | 472 | } Counters; |
473 | 473 | ||
474 | |||
475 | /* | ||
476 | ** Check whether it is worth to use 'na' array entries instead of 'nh' | ||
477 | ** hash nodes. (A hash node uses ~3 times more memory than an array | ||
478 | ** entry: Two values plus 'next' versus one value.) Evaluate with size_t | ||
479 | ** to avoid overflows. | ||
480 | */ | ||
481 | #define arrayXhash(na,nh) (cast_sizet(na) <= cast_sizet(nh) * 3) | ||
482 | |||
474 | /* | 483 | /* |
475 | ** Compute the optimal size for the array part of table 't'. | 484 | ** Compute the optimal size for the array part of table 't'. |
485 | ** This size maximizes the number of elements going to the array part | ||
486 | ** while satisfying the condition 'arrayXhash' with the use of memory if | ||
487 | ** all those elements went to the hash part. | ||
476 | ** 'ct->na' enters with the total number of array indices in the table | 488 | ** 'ct->na' enters with the total number of array indices in the table |
477 | ** and leaves with the number of keys that will go to the array part; | 489 | ** and leaves with the number of keys that will go to the array part; |
478 | ** return the optimal size. (The condition 'twotoi > 0' in the for loop | 490 | ** return the optimal size for the array part. |
479 | ** stops the loop if 'twotoi' overflows.) | ||
480 | */ | 491 | */ |
481 | static unsigned computesizes (Counters *ct) { | 492 | static unsigned computesizes (Counters *ct) { |
482 | int i; | 493 | int i; |
@@ -484,17 +495,19 @@ static unsigned computesizes (Counters *ct) { | |||
484 | unsigned int a = 0; /* number of elements smaller than 2^i */ | 495 | unsigned int a = 0; /* number of elements smaller than 2^i */ |
485 | unsigned int na = 0; /* number of elements to go to array part */ | 496 | unsigned int na = 0; /* number of elements to go to array part */ |
486 | unsigned int optimal = 0; /* optimal size for array part */ | 497 | unsigned int optimal = 0; /* optimal size for array part */ |
487 | /* loop while keys can fill more than half of total size */ | 498 | /* traverse slices while 'twotoi' does not overflow and total of array |
499 | indices still can satisfy 'arrayXhash' against the array size */ | ||
488 | for (i = 0, twotoi = 1; | 500 | for (i = 0, twotoi = 1; |
489 | twotoi > 0 && ct->na > twotoi / 2; | 501 | twotoi > 0 && arrayXhash(twotoi, ct->na); |
490 | i++, twotoi *= 2) { | 502 | i++, twotoi *= 2) { |
491 | a += ct->nums[i]; | 503 | unsigned nums = ct->nums[i]; |
492 | if (a > twotoi/2) { /* more than half elements present? */ | 504 | a += nums; |
505 | if (nums > 0 && /* grows array only if it gets more elements... */ | ||
506 | arrayXhash(twotoi, a)) { /* ...while using "less memory" */ | ||
493 | optimal = twotoi; /* optimal size (till now) */ | 507 | optimal = twotoi; /* optimal size (till now) */ |
494 | na = a; /* all elements up to 'optimal' will go to array part */ | 508 | na = a; /* all elements up to 'optimal' will go to array part */ |
495 | } | 509 | } |
496 | } | 510 | } |
497 | lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); | ||
498 | ct->na = na; | 511 | ct->na = na; |
499 | return optimal; | 512 | return optimal; |
500 | } | 513 | } |