1. Jun 13, 2020
    • Steve Bennett's avatar
      85a55907
    • Steve Bennett's avatar
      core: dict: don't leak references for dup keys · dc2a759f
      Steve Bennett authored
      
      
      In list -> dict conversion, the new key needs to
      be decremented.
      
      Signed-off-by: default avatarSteve Bennett <steveb@workware.net.au>
      dc2a759f
    • Steve Bennett's avatar
      core: dict: fix for dup keys when converting list -> dict · 18c690f0
      Steve Bennett authored
      
      
      When converting a list to a dict, ensure that the last duplicate
      wins, not the first duplicate.
      
      Signed-off-by: default avatarSteve Bennett <steveb@workware.net.au>
      18c690f0
    • Steve Bennett's avatar
      core: dict: need to mark removed hash entries · dc3f796f
      Steve Bennett authored
      
      
      If a hash collision occurs and then the original
      entry that cased the hash collision is removed, we
      still need to continue iterating when searching for the
      new key. Don't stop at the now-empty slow.
      So mark these entries with offset=-1 to indicate that they
      need to be skipped.
      
      Signed-off-by: default avatarSteve Bennett <steveb@workware.net.au>
      dc3f796f
    • Steve Bennett's avatar
      core: dicts (and arrays) now preserve insertion order · dc71006b
      Steve Bennett authored
      
      
      Although the documentation has always stated that, like Tcl,
      insertion order of dictionaries was preserved, this has never
      been the case. Instead, dictionaries were implemented as simple
      hash tables that did not preserve order.
      
      Now, a new implementation of dictionaries preserves insertion
      order and has a number of other benefits.
      
      Instead of hashing keys and storing keys and values in the hash table,
      the keys and values are not stored in a separate table, exactly as
      lists are stored, with alternating key, value pairs. Iterating over the
      dictionary is exactly like iterating over a list, where the order is consistent.
      
      The hash table uses closed hashing rather than open hashing to avoid
      allocatation of hash entry structures. Instead a fixed (but expandable)
      hash table maps the key hash to the offset in the key/value table.
      This use of offsets means that if the key/value table grows, the offsets
      remain valid. Likewise, if the hash table needs to grow, the key, value table
      remains unchanged.
      
      In addition to the offset (which indexes to the value, and 0 means the hash table entry is unused),
      the original hash is stored in the hash table. This reduces the need for object
      comparisons on hash entry collisions.
      
      The collision resolution algorithm is the same as that used by Python:
      
      	peturb >>= 5;
      	idx = (5 * idx + 1 + peturb) & dict->sizemask;
      
      In order to reduce collisions, the hash table is expanded once it reaches
      half full. This is more conservative that Python where the table is expanded
      when it is two thirds full.
      
      In addition, the new faster hashing algorithm from Tcl 8.7 is used.
      This the hash for integers to be calculated efficiently without requiring
      them to be converted to string form first.
      
      This implementation is modelled largely on the Python dict implementation.
      
      Overall the performance should be an improvement over the current implementation,
      whilst preserving order. Dictionary creating and insertion should be faster
      as hash entries do not need to be allocated and resizing should be slightly faster.
      Entry lookup should be about the same, except may be faster for pure integer keys.
      
      Below are some indicative benchmarks.
      
                                                          OLD     NEW
      dict-create-1.1  Create empty dict               97.2ns       .
      dict-create-1.2  Create small dict                440ns    -27%
      dict-create-1.3  Create medium dict              1.54us    -57%
      dict-create-1.4  Create large dict (int keys)     130us    -80%
      dict-create-1.5  Create large dict (string keys)  143us    -75%
         dict-set-1.1  Replace existing item            258ns    -34%
         dict-set-1.2  Replace nonexistent item         365ns    -49%
      dict-exists-1.1  Find existing item              55.7ns     -5%
      dict-exists-1.2  Find nonexistent item           55.0ns     -5%
      
      Signed-off-by: default avatarSteve Bennett <steveb@workware.net.au>
      dc71006b
  2. Jun 12, 2020
  3. Jun 11, 2020
  4. Jun 10, 2020
  5. Jun 05, 2020
  6. May 30, 2020
  7. May 28, 2020
  8. May 27, 2020
  9. May 23, 2020
  10. May 07, 2020
  11. May 06, 2020
  12. May 05, 2020
  13. May 04, 2020