private static Map<Integer, Long> divideHybridHashTableMemory(
      MapJoinTableContainer[] mapJoinTables, MapJoinDesc desc,
      long totalSize, long totalHashTableMemory) {
    int smallTableCount = Math.max(mapJoinTables.length - 1, 1);
    Map<Integer, Long> tableMemorySizes = new HashMap<Integer, Long>();
    // If any table has bad size estimate, we need to fall back to sizing each table equally
    boolean fallbackToEqualProportions = totalSize <= 0;

    if (!fallbackToEqualProportions) {
      for (Map.Entry<Integer, Long> tableSizeEntry : desc.getParentDataSizes().entrySet()) {
        if (tableSizeEntry.getKey() == desc.getPosBigTable()) {
          continue;
        }

        long tableSize = tableSizeEntry.getValue();
        if (tableSize <= 0) {
          fallbackToEqualProportions = true;
          break;
        }
        float percentage = (float) tableSize / totalSize;
        long tableMemory = (long) (totalHashTableMemory * percentage);
        tableMemorySizes.put(tableSizeEntry.getKey(), tableMemory);
      }
    }

    if (fallbackToEqualProportions) {
      // Just give each table the same amount of memory.
      long equalPortion = totalHashTableMemory / smallTableCount;
      for (Integer pos : desc.getParentDataSizes().keySet()) {
        if (pos == desc.getPosBigTable()) {
          break;
        }
        tableMemorySizes.put(pos, equalPortion);
      }
    }

    return tableMemorySizes;
  }
HashTableLoader for Tez constructs the hashtable from records read from
a broadcast edge.
ql/src/java/org/apache/hadoop/hive/ql/exec/tez/HashTableLoader.java