Skip to content

Commit

Permalink
Add metrics for allocated and in-use objects (#163)
Browse files Browse the repository at this point in the history
Rebased and cleaned up version of #149
  • Loading branch information
chrisvest committed Jun 2, 2024
2 parents bd3a332 + aee9fe3 commit 95ae482
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/main/java/stormpot/AllocationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,14 @@ abstract class AllocationController<T extends Poolable> {
* @see ManagedPool#getLeakedObjectsCount()
*/
abstract long countLeakedObjects();

/**
* @see ManagedPool#getCurrentAllocatedCount()
*/
abstract int allocatedSize();

/**
* @see ManagedPool#getCurrentInUseCount()
*/
abstract int inUse();
}
16 changes: 16 additions & 0 deletions src/main/java/stormpot/BAllocThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -390,4 +390,20 @@ long countLeakedObjects() {
void offerDeadSlot(BSlot<T> slot) {
dead.offer(slot);
}

int allocatedSize() {
return size;
}

int inUse() {
int inUse = 0;
int liveSize = 0;
for (BSlot<T> slot: live) {
liveSize++;
if (slot.isClaimedOrThreadLocal()) {
inUse++;
}
}
return size - liveSize + inUse;
}
}
5 changes: 5 additions & 0 deletions src/main/java/stormpot/BSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ boolean isLive() {
boolean isClaimed() {
return get() == CLAIMED;
}

boolean isClaimedOrThreadLocal() {
int state = get();
return state == CLAIMED || state == TLR_CLAIMED;
}

void incrementClaims() {
claims++;
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/stormpot/BlazePool.java
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,14 @@ public double getDeallocationLatencyPercentile(double percentile) {
public long getLeakedObjectsCount() {
return allocator.countLeakedObjects();
}

@Override
public int getCurrentAllocatedCount() {
return allocator.allocatedSize();
}

@Override
public int getCurrentInUseCount() {
return allocator.inUse();
}
}
18 changes: 18 additions & 0 deletions src/main/java/stormpot/DirectAllocationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,22 @@ long getFailedAllocationCount() {
long countLeakedObjects() {
return -1;
}

@Override
public int allocatedSize() {
return size;
}

@Override
int inUse() {
int inUse = 0;
int liveSize = 0;
for (BSlot<T> slot: live) {
liveSize++;
if (slot.isClaimedOrThreadLocal()) {
inUse++;
}
}
return size - liveSize + inUse;
}
}
18 changes: 18 additions & 0 deletions src/main/java/stormpot/InlineAllocationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -362,4 +362,22 @@ private void recordObjectLifetimeSample(long nanoseconds) {
metricsRecorder.recordObjectLifetimeSampleMillis(milliseconds);
}
}

@Override
public int allocatedSize() {
return live.size() - poisonedSlots.get();
}

@Override
int inUse() {
int inUse = 0;
int liveSize = 0;
for (BSlot<T> slot: live) {
liveSize++;
if (slot.isClaimedOrThreadLocal()) {
inUse++;
}
}
return size - liveSize + inUse;
}
}
33 changes: 33 additions & 0 deletions src/main/java/stormpot/ManagedPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package stormpot;

import javax.management.MXBean;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
* This is the JMX management interface for Stormpot object pools.
Expand Down Expand Up @@ -181,4 +182,36 @@ public interface ManagedPool {
* the pool.
*/
double getDeallocationLatencyPercentile(double percentile);

/**
* Get the approximate number of currently allocated objects.
*
* This operation has time complexity O(poolSize) to count the number of slots.
*
* The default implementation of this interface methods returns {@code -1}.
*
* Unlike {@link #getAllocationCount()}, this returns only the number of objects currently in the pool,
* which typically would be the same as {@link #getTargetSize()}.
*
* @return The current approximate number of allocated objects.
*/
default int getCurrentAllocatedCount() {
return -1;
}

/**
* Get the approximate number of objects currently in use.
*
* This operation has time complexity O(poolSize) to check each slot.
*
* The counting operation is "weakly consistent",
* in a similar sense to {@link ConcurrentLinkedQueue#iterator()}.
*
* The default implementation of this interface methods returns {@code -1}.
*
* @return number of objects currently in use
*/
default int getCurrentInUseCount() {
return -1;
}
}
10 changes: 10 additions & 0 deletions src/main/java/stormpot/ThreadedAllocationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,14 @@ public long getFailedAllocationCount() {
public long countLeakedObjects() {
return allocator.countLeakedObjects();
}

@Override
public int allocatedSize() {
return allocator.allocatedSize();
}

@Override
public int inUse() {
return allocator.inUse();
}
}
12 changes: 12 additions & 0 deletions src/test/java/blackbox/AbstractPoolTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,18 @@ void managedPoolMustGivePoolState() throws Exception {
assertTrue(managedPool.isShutDown());
}

@Test
void managedPoolMustGiveNumberOfAllocatedAndInUseObjects() throws Exception {
createOneObjectPool();
pool.claim(longTimeout).release(); // Ensure the single object is allocated
ManagedPool managedPool = pool.getManagedPool();
assertThat(managedPool.getCurrentAllocatedCount()).isOne();
assertThat(managedPool.getCurrentInUseCount()).isZero();
T obj = pool.claim(longTimeout);
assertThat(managedPool.getCurrentInUseCount()).isOne();
obj.release();
}

@ParameterizedTest
@EnumSource(Taps.class)
void applyMustThrowOnNullTimeout(Taps taps) {
Expand Down

0 comments on commit 95ae482

Please sign in to comment.