Java Code Examples for sun.misc.Unsafe#ARRAY_LONG_INDEX_SCALE

The following examples show how to use sun.misc.Unsafe#ARRAY_LONG_INDEX_SCALE . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 6 votes vote down vote up
@Override
public void apply(final String[] tags, final long value, final long timestamp) {

  final long index = index(tags, false);

  // Failed to grow table, silently drop the measurement
  if (index == NOT_FOUND) {
    return;
  }

  // Decode table index and slot index from a long.
  // Upper 32 bits represent the table index and lower 32 bits represent the slot index.
  // This logic is replicated in multiple places for performance reasons.
  int tableIndex = (int) ((index & TABLE_MASK) >> 32);
  int slotIndex = (int) (index & SLOT_MASK);
  long[] table = tables.get(tableIndex);

  final long base = Unsafe.ARRAY_LONG_BASE_OFFSET + slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE;
  unsafe.putLongVolatile(table, base + Unsafe.ARRAY_LONG_INDEX_SCALE, timestamp);

  combine(table, base, value);
}
 
Example 2
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 6 votes vote down vote up
/**
 * Adds a new double value to the existing value in the given field index.
 *
 * @param table the table containing the values
 * @param baseOffset base offset of the record in the table containing the left hand value
 * @param index index of the field
 * @param value value to be added
 * @return new accumulated value of the field index
 */
protected double add(final long[] table, final long baseOffset, final long index,
    final double value) {
  final long offset = ((RESERVED_FIELDS + index) * Unsafe.ARRAY_LONG_INDEX_SCALE) + baseOffset;
  long old;
  double old_d, new_d;
  do {
    old = unsafe.getLongVolatile(table, offset);
    old_d = Double.longBitsToDouble(old);
    new_d = old_d + value;
    ///CLOVER:OFF
    // No reliable way to test without being able to mock unsafe
  } while (!unsafe.compareAndSwapLong(table, offset, old, Double.doubleToRawLongBits(new_d)));
  ///CLOVER:ON
  return new_d;
}
 
Example 3
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 6 votes vote down vote up
@Override
public boolean next() {
  i++;
  if (i >= tagSets.length || tagSets[i] == null) {
    return false;
  }

  long index = index(tagSets[i], true);

  if (NOT_FOUND == index) {
    LOGGER.error("Missing index on Read. Tags: {}. Concurrency error or bug",
        Arrays.asList(tagSets[i]));
    return false;
  }

  // Decode table index and slot index from long.
  // Upper 32 bits represent the table index and lower 32 bits represent the slot index.
  // This logic is replicated in multiple places for performance reasons.
  int tableIndex = (int) ((index & TABLE_MASK) >> 32);
  int slotIndex = (int) (index & SLOT_MASK);

  table = tables.get(tableIndex);
  base = Unsafe.ARRAY_LONG_BASE_OFFSET + slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE;
  return true;
}
 
Example 4
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 6 votes vote down vote up
/**
 * Set a new double value as maximum if its higher than existing value in the given field index.
 *
 * @param table the table containing the values
 * @param baseOffset base offset of the record in the table containing the left hand value
 * @param index index of the field
 * @param value new value
 */
protected void max(final long[] table, final long baseOffset, final long index,
    final double value) {
  final long offset = baseOffset + (RESERVED_FIELDS + index) * Unsafe.ARRAY_LONG_INDEX_SCALE;
  long old;
  double old_d;
  do {
    old = unsafe.getLong(table, offset);
    old_d = Double.longBitsToDouble(old);
    if (value <= old_d) {
      return;
    }
    ///CLOVER:OFF
    // No reliable way to test without being able to mock unsafe
  } while (!unsafe.compareAndSwapLong(table, offset, old, Double.doubleToRawLongBits(value)));
  ///CLOVER:ON
}
 
Example 5
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 6 votes vote down vote up
/**
 * Set a new double value as minimum if its lower than existing value in the given field index.
 *
 * @param table the table containing the values
 * @param baseOffset base offset of the record in the table containing the left hand value
 * @param index index of the field
 * @param value new value
 */
protected void min(final long[] table, final long baseOffset, final long index,
    final double value) {
  final long offset = baseOffset + (RESERVED_FIELDS + index) * Unsafe.ARRAY_LONG_INDEX_SCALE;
  long old;
  double old_d;
  do {
    old = unsafe.getLong(table, offset);
    old_d = Double.longBitsToDouble(old);
    if (value >= old_d) {
      return;
    }
    ///CLOVER:OFF
    // No reliable way to test without being able to mock unsafe
  } while (!unsafe.compareAndSwapLong(table, offset, old, Double.doubleToRawLongBits(value)));
  ///CLOVER:ON
}
 
Example 6
Source File: RawHashTable.java    From metrics with Apache License 2.0 5 votes vote down vote up
private long getLong(final String[] tags, int offset) {
  final long hashCode = Arrays.hashCode(tags);
  final int i = index(hashCode);
  final long base = Unsafe.ARRAY_LONG_BASE_OFFSET + i * Unsafe.ARRAY_LONG_INDEX_SCALE;

  return unsafe.getLongVolatile(table, base + offset * Unsafe.ARRAY_LONG_INDEX_SCALE);
}
 
Example 7
Source File: RawHashTable.java    From metrics with Apache License 2.0 5 votes vote down vote up
public void put(final String[] tags, final long value) {
  final long hashCode = Arrays.hashCode(tags);
  final int i = index(hashCode);
  final long base = Unsafe.ARRAY_LONG_BASE_OFFSET + i * Unsafe.ARRAY_LONG_INDEX_SCALE;

  unsafe.getAndAddLong(table, base + Unsafe.ARRAY_LONG_INDEX_SCALE, 1L);
  unsafe.getAndAddLong(table, base + 2 * Unsafe.ARRAY_LONG_INDEX_SCALE, value);
  min(base + 3 * Unsafe.ARRAY_LONG_INDEX_SCALE, value);
  max(base + 4 * Unsafe.ARRAY_LONG_INDEX_SCALE, value);
}
 
Example 8
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 5 votes vote down vote up
/**
 * Set a new value as minimum if its lower than existing value in the given field index.
 *
 * @param table the table containing the values
 * @param baseOffset base offset of the record in the table containing the left hand value
 * @param index index of the field
 * @param value new value
 */
protected void min(final long[] table, final long baseOffset, final long index,
    final long value) {
  final long offset = baseOffset + (RESERVED_FIELDS + index) * Unsafe.ARRAY_LONG_INDEX_SCALE;
  long old;
  do {
    old = unsafe.getLong(table, offset);
    if (value >= old) {
      return;
    }
    ///CLOVER:OFF
    // No reliable way to test without being able to mock unsafe
  } while (!unsafe.compareAndSwapLong(table, offset, old, value));
  ///CLOVER:ON
}
 
Example 9
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 5 votes vote down vote up
/**
 * Set a new value as maximum if its higher than existing value in the given field index.
 *
 * @param table the table containing the values
 * @param baseOffset base offset of the record in the table containing the left hand value
 * @param index index of the field
 * @param value new value
 */
protected void max(final long[] table, final long baseOffset, final long index,
    final long value) {
  final long offset = baseOffset + (RESERVED_FIELDS + index) * Unsafe.ARRAY_LONG_INDEX_SCALE;
  long old;
  do {
    old = unsafe.getLong(table, offset);
    if (value <= old) {
      return;
    }
    ///CLOVER:OFF
    // No reliable way to test without being able to mock unsafe
  } while (!unsafe.compareAndSwapLong(table, offset, old, value));
  ///CLOVER:ON
}
 
Example 10
Source File: VirtualArrayNode.java    From openjdk-jdk9 with GNU General Public License v2.0 4 votes vote down vote up
public static int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind, ResolvedJavaType componentType, int length) {
    int baseOffset;
    int indexScale;
    switch (componentType.getJavaKind()) {
        case Boolean:
            baseOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
            indexScale = Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
            break;
        case Byte:
            baseOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET;
            indexScale = Unsafe.ARRAY_BYTE_INDEX_SCALE;
            break;
        case Short:
            baseOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET;
            indexScale = Unsafe.ARRAY_SHORT_INDEX_SCALE;
            break;
        case Char:
            baseOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET;
            indexScale = Unsafe.ARRAY_CHAR_INDEX_SCALE;
            break;
        case Int:
            baseOffset = Unsafe.ARRAY_INT_BASE_OFFSET;
            indexScale = Unsafe.ARRAY_INT_INDEX_SCALE;
            break;
        case Long:
            baseOffset = Unsafe.ARRAY_LONG_BASE_OFFSET;
            indexScale = Unsafe.ARRAY_LONG_INDEX_SCALE;
            break;
        case Float:
            baseOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET;
            indexScale = Unsafe.ARRAY_FLOAT_INDEX_SCALE;
            break;
        case Double:
            baseOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
            indexScale = Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
            break;
        case Object:
            baseOffset = Unsafe.ARRAY_OBJECT_BASE_OFFSET;
            indexScale = Unsafe.ARRAY_OBJECT_INDEX_SCALE;
            break;
        default:
            return -1;
    }
    long offset;
    if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN && componentType.isPrimitive()) {
        // On big endian, we do just get expect the type be right aligned in this memory slot
        offset = constantOffset - (componentType.getJavaKind().getByteCount() - Math.min(componentType.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount()));
    } else {
        offset = constantOffset;
    }
    long index = offset - baseOffset;
    if (index % indexScale != 0) {
        return -1;
    }
    long elementIndex = index / indexScale;
    if (elementIndex < 0 || elementIndex >= length) {
        return -1;
    }
    return (int) elementIndex;
}
 
Example 11
Source File: ConcurrentMonoidIntTable.java    From metrics with Apache License 2.0 4 votes vote down vote up
private long getDataFieldOffset(long baseOffset, int index) {
  return baseOffset + (RESERVED_FIELDS + numAggFields) * Unsafe.ARRAY_LONG_INDEX_SCALE
      + (index - numAggFields) * Unsafe.ARRAY_INT_INDEX_SCALE;
}
 
Example 12
Source File: ConcurrentMonoidIntTable.java    From metrics with Apache License 2.0 4 votes vote down vote up
private long getAggFieldOffset(long baseOffset, int index) {
  return baseOffset + (RESERVED_FIELDS + index) * Unsafe.ARRAY_LONG_INDEX_SCALE;
}
 
Example 13
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 4 votes vote down vote up
/**
 * Find index of the record for the given key in the linear probing table.
 *
 * <p>When a slot in the table is taken, it will never be released nor changed.</p>
 *
 * @param tags key to use for table
 * @return index position in the table for the record. The 64 bit long value has two int values
 * encoded into it. The higher 32 bits represent the table index and the lower 32 bits represent
 * the slot index. And returns {@link #NOT_FOUND} if record not found.
 */
long index(final String[] tags, final boolean isReading) {
  final long key = hashCode(tags);
  for (int tableIndex = 0; tableIndex < tables.size(); tableIndex++) {
    long[] table = tables.get(tableIndex);
    AtomicInteger recordCount = recordCounts.get(tableIndex);
    int tableCapacity = tableCapacities.get(tableIndex);
    final int slot = getSlot(key, table.length / recordSize);
    final int startIndex = slot * recordSize;
    int slotIndex = startIndex;
    for (; ; ) {
      long offset = Unsafe.ARRAY_LONG_BASE_OFFSET + slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE;
      long candidate = unsafe.getLongVolatile(table, offset);

      // check if we found our key
      if (key == candidate) {
        // Encode table index and slot index into a long.
        // Upper 32 bits represent the table index and lower 32 bits represent the slot index.
        // This logic is replicated in multiple places for performance reasons.
        return ((long) tableIndex) << 32 | ((long) slotIndex);
      }

      boolean emptySlot = 0L == candidate;

      if (emptySlot) {

        if (isReading) {
          break; // If the slot is empty while reading, skip to the next table.
        } else if (recordCount.get() >= tableCapacity) {
          break; // we're writing but the table is 70% full
        } else {
          ///CLOVER:OFF
          // No reliable way to test without being able to mock unsafe
          if (unsafe.compareAndSwapLong(table, offset, 0L, key)) { // try to reserve it
            ///CLOVER:ON

            //increment the record count
            recordCount.incrementAndGet();

            // reset update timestamp
            unsafe.putLongVolatile(table, offset + Unsafe.ARRAY_LONG_INDEX_SCALE, 0L);
            // It is ok if we lose some data from other threads while writing identity
            for (int j = 0; j < identity.length; j++) {
              unsafe.putLongVolatile(table,
                  offset + (RESERVED_FIELDS + j) * Unsafe.ARRAY_LONG_INDEX_SCALE, identity[j]);
            }

            //increment the total size;
            int tagIndex = unsafe.getAndAddInt(this, usedOffset, 1);
            if (tagIndex >= tagSets.length) {
              // grow tag set
              synchronized (this) {
                if (tagIndex >= tagSets.length) {
                  final int oldLength = tagSets.length;
                  final int newLength =
                      oldLength > TAGSETS_MAX_INCREMENT ? oldLength + TAGSETS_MAX_INCREMENT
                          : oldLength * 2;
                  tagSets = Arrays.copyOf(tagSets, newLength);
                }
              }
            }

            // Store tags in the tag array for iteration purposes only
            tagSets[tagIndex] = Arrays.copyOf(tags, tags.length);

            // Encode table index and slot index into a long.
            // Upper 32 bits represent the table index and lower 32 bits represent the slot index.
            // This logic is replicated in multiple places for performance reasons.
            return ((long) tableIndex) << 32 | ((long) slotIndex);
          }
        }
      } else {
        slotIndex += recordSize;
        if (slotIndex >= table.length) {
          slotIndex = 0;
        }
        if (slotIndex == startIndex) {
          break; // check the next table
        }
      }
    }
  }
  if (isReading) {
    return NOT_FOUND;
  } else {
    if (growTable()) {
      return index(tags, isReading);
    } else {
      return NOT_FOUND;
    }
  }
}
 
Example 14
Source File: RawHashTable.java    From metrics with Apache License 2.0 4 votes vote down vote up
int index(final long key) {
  int start = (Math.abs((int) key) % capacity);
  int i = start < 0 ? 0 : start * RECORD_SIZE;
  boolean failSafe = false;

  for (int counter = 1; ; counter++) {

    final long offset = Unsafe.ARRAY_LONG_BASE_OFFSET + i * Unsafe.ARRAY_LONG_INDEX_SCALE;

    // check if we found our key
    final long candidate = unsafe.getLongVolatile(table, offset);
    if (key == candidate) {
      unsafe.putIntVolatile(this, scanLengthOffset, counter);
      return i;
    }

    // check if we found empty slot
    if (0L == candidate) {
      // try to reserve it

      ///CLOVER:OFF
      // No reliable way to test without being able to mock unsafe
      if (unsafe.compareAndSwapLong(table, offset, 0L, key)) {
        ///CLOVER:ON

        final int localUsed = unsafe.getAndAddInt(this, usedOffset, 1) + 1;
        unsafe.putLongVolatile(table, offset + 3 * Unsafe.ARRAY_LONG_INDEX_SCALE, Long.MAX_VALUE);
        unsafe.putLongVolatile(table, offset + 4 * Unsafe.ARRAY_LONG_INDEX_SCALE, Long.MIN_VALUE);

        unsafe.putIntVolatile(this, scanLengthOffset, counter);
        return i;
      }
    } else {
      // go to next record
      i += RECORD_SIZE;
      if (i >= table.length) {
        if (failSafe) {
          throw new IllegalStateException("No more space in linear probing table");
        } else {
          i = 0;
          failSafe = true;
        }
      }
    }
  }
}
 
Example 15
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 2 votes vote down vote up
/**
 * Replaces the existing double value in the given field index with the given value.
 *
 * @param table the table containing the values
 * @param baseOffset base offset of the record in the table containing the left hand value
 * @param index index of the field
 * @param value new value
 */
protected void set(final long[] table, final long baseOffset, final long index,
    final double value) {
  final long offset = baseOffset + (RESERVED_FIELDS + index) * Unsafe.ARRAY_LONG_INDEX_SCALE;
  unsafe.putLongVolatile(table, offset, Double.doubleToLongBits(value));
}
 
Example 16
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 2 votes vote down vote up
/**
 * Replaces the existing value in the given field index with the given value.
 *
 * @param table the table containing the values
 * @param baseOffset base offset of the record in the table containing the left hand value
 * @param index index of the field
 * @param value new value
 */
protected void set(final long[] table, final long baseOffset, final long index,
    final long value) {
  final long offset = baseOffset + (RESERVED_FIELDS + index) * Unsafe.ARRAY_LONG_INDEX_SCALE;
  unsafe.putLongVolatile(table, offset, value);
}
 
Example 17
Source File: ConcurrentMonoidLongTable.java    From metrics with Apache License 2.0 2 votes vote down vote up
/**
 * Adds a new value to the existing value in the given field index.
 *
 * @param table the table containing the values
 * @param baseOffset base offset of the record in the table containing the left hand value
 * @param index index of the field
 * @param value value to be added
 * @return new accumulated value of the field index
 */
protected long add(final long[] table, final long baseOffset, final long index,
    final long value) {
  final long offset = baseOffset + (RESERVED_FIELDS + index) * Unsafe.ARRAY_LONG_INDEX_SCALE;
  return unsafe.getAndAddLong(table, offset, value) + value;
}