Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/near cache stats #1458

Merged
merged 4 commits into from
Dec 27, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions hazelcast/src/main/java/com/hazelcast/map/MapService.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.hazelcast.map.wan.MapReplicationRemove;
import com.hazelcast.map.wan.MapReplicationUpdate;
import com.hazelcast.monitor.impl.LocalMapStatsImpl;
import com.hazelcast.monitor.impl.NearCacheStatsImpl;
import com.hazelcast.nio.Address;
import com.hazelcast.nio.ClassLoaderUtil;
import com.hazelcast.nio.serialization.Data;
Expand Down Expand Up @@ -1159,6 +1160,11 @@ public LocalMapStatsImpl createLocalMapStats(String mapName) {
// add near cache heap cost.
heapCost += mapContainer.getNearCacheSizeEstimator().getSize();
localMapStats.setHeapCost(heapCost);
if(mapContainer.getMapConfig().isNearCacheEnabled())
{
NearCacheStatsImpl nearCacheStats = getNearCache(mapName).getNearCacheStats();
localMapStats.setNearCacheStats(nearCacheStats);
}

return localMapStats;
}
Expand Down
24 changes: 24 additions & 0 deletions hazelcast/src/main/java/com/hazelcast/map/NearCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.hazelcast.config.Config;
import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.config.NearCacheConfig;
import com.hazelcast.monitor.impl.NearCacheStatsImpl;
import com.hazelcast.nio.serialization.Data;
import com.hazelcast.spi.NodeEngine;
import com.hazelcast.util.Clock;
Expand Down Expand Up @@ -51,6 +52,7 @@ public class NearCache {
private final AtomicBoolean canEvict;
private final ConcurrentMap<Data, CacheRecord> cache;
private final MapContainer mapContainer;
private final NearCacheStatsImpl stats;

public NearCache(String mapName, MapService mapService) {
this.mapService = mapService;
Expand All @@ -66,6 +68,7 @@ public NearCache(String mapName, MapService mapService) {
cache = new ConcurrentHashMap<Data, CacheRecord>();
canCleanUp = new AtomicBoolean(true);
canEvict = new AtomicBoolean(true);
stats = new NearCacheStatsImpl();
lastCleanup = Clock.currentTimeMillis();
}

Expand All @@ -91,6 +94,26 @@ public void put(Data key, Data data) {
cache.put(key, record);
updateSizeEstimator(calculateCost(record));
}
public NearCacheStatsImpl getNearCacheStats()
{
return createNearCacheStats();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imho, get() should just get. you may make create() public

private NearCacheStatsImpl createNearCacheStats() {
long ownedEntryCount = 0;
long ownedEntryMemoryCost = 0;
long hits = 0;
for (CacheRecord record : cache.values())
{
ownedEntryCount++;
ownedEntryMemoryCost += record.getCost();
hits += record.hit.get();
}
stats.setOwnedEntryCount(ownedEntryCount);
stats.setOwnedEntryMemoryCost(ownedEntryMemoryCost);
stats.setHits(hits);
return stats;
}

private void fireEvictCache() {
if (canEvict.compareAndSet(true, false)) {
Expand Down Expand Up @@ -165,6 +188,7 @@ public Object get(Data key) {
}
return record.value.equals(NULL_OBJECT) ? null : record.value;
} else {
stats.incrementMisses();
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.hazelcast.monitor;

import com.hazelcast.monitor.impl.NearCacheStatsImpl;

/**
* Local map statistics. As everything is partitioned in Hazelcast,
* each member owns 1/N (N being the number of members in the cluster)
Expand Down Expand Up @@ -199,5 +201,7 @@ public interface LocalMapStats extends LocalInstanceStats {
*/
public long getHeapCost();

public NearCacheStatsImpl getNearCacheStats();


}
53 changes: 53 additions & 0 deletions hazelcast/src/main/java/com/hazelcast/monitor/NearCacheStats.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.hazelcast.monitor;

/**
* User: eminn
* Date: 03/12/13
* Time: 10:48 AM
*/
public interface NearCacheStats extends LocalInstanceStats {
/**
* Returns the creation time of this NearCache on this member
*
* @return creation time of this NearCache on this member
*/
long getCreationTime();

/**
* Returns the number of entries owned by this member.
*
* @return number of entries owned by this member.
*/
long getOwnedEntryCount();


/**
* Returns memory cost (number of bytes) of entries in this cache.
*
* @return memory cost (number of bytes) of entries in this cache.
*/
long getOwnedEntryMemoryCost();

/**
* Returns the number of hits (reads) of the locally owned entries.
*
* @return number of hits (reads).
*/
long getHits();

/**
* Returns the number of misses of the locally owned entries.
*
* @return number of misses.
*/
long getMisses();

/**
* Returns the hit/miss ratio of the locally owned entries.
*
* @return hit/miss ratio.
*/
double getRatio();


}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public class LocalMapStatsImpl implements LocalMapStats, IdentifiedDataSerializa
private long dirtyEntryCount;
private int backupCount;

private NearCacheStatsImpl nearCacheStats;

public LocalMapStatsImpl() {
creationTime = Clock.currentTimeMillis();
}
Expand Down Expand Up @@ -80,6 +82,12 @@ public void writeData(ObjectDataOutput out) throws IOException {
out.writeLong(maxPutLatency.get());
out.writeLong(maxRemoveLatency.get());
out.writeLong(heapCost);
boolean hasNearCache = nearCacheStats != null;
out.writeBoolean(hasNearCache);
if(hasNearCache)
{
nearCacheStats.writeData(out);
}
}

public void readData(ObjectDataInput in) throws IOException {
Expand All @@ -106,6 +114,12 @@ public void readData(ObjectDataInput in) throws IOException {
maxPutLatency.set(in.readLong());
maxRemoveLatency.set(in.readLong());
heapCost = in.readLong();
boolean hasNearCache = in.readBoolean();
if(hasNearCache)
{
nearCacheStats = new NearCacheStatsImpl();
nearCacheStats.readData(in);
}
}

public long getOwnedEntryCount() {
Expand Down Expand Up @@ -274,6 +288,14 @@ public long getHeapCost() {
return heapCost;
}

public NearCacheStatsImpl getNearCacheStats() {
return nearCacheStats;
}

public void setNearCacheStats(NearCacheStatsImpl nearCacheStats) {
this.nearCacheStats = nearCacheStats;
}

public String toString() {
return "LocalMapStatsImpl{" +
"lastAccessTime=" + lastAccessTime +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,11 @@ public long getHeapCost() {
return 0;
}

@Override
public NearCacheStatsImpl getNearCacheStats() {
throw new UnsupportedOperationException("Replicated map has no Near Cache!");
}

public String toString() {
return "LocalReplicatedMapStatsImpl{" +
"lastAccessTime=" + lastAccessTime +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.hazelcast.monitor.impl;

import com.hazelcast.monitor.NearCacheStats;
import com.hazelcast.nio.ObjectDataInput;
import com.hazelcast.nio.ObjectDataOutput;
import com.hazelcast.util.Clock;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;

/**
* User: eminn
* Date: 03/12/13
* Time: 10:58 AM
*/
public class NearCacheStatsImpl implements NearCacheStats {

private long ownedEntryCount;
private long ownedEntryMemoryCost;
private long creationTime;
private AtomicLong hits = new AtomicLong(0);
private AtomicLong misses = new AtomicLong(0);

public NearCacheStatsImpl() {
this.creationTime = Clock.currentTimeMillis();
}

@Override
public long getCreationTime() {
return creationTime;
}

@Override
public long getOwnedEntryCount() {
return ownedEntryCount;
}

public void setOwnedEntryCount(long ownedEntryCount) {
this.ownedEntryCount = ownedEntryCount;
}

@Override
public long getOwnedEntryMemoryCost() {
return ownedEntryMemoryCost;
}

@Override
public long getHits() {
return hits.get();
}

@Override
public long getMisses() {
return misses.get();
}

public void setHits(long hits) {
this.hits.set(hits);
}

public double getRatio() {
return (double)hits.get() / misses.get() ;
}


public void setOwnedEntryMemoryCost(long ownedEntryMemoryCost) {

this.ownedEntryMemoryCost = ownedEntryMemoryCost;
}

public void incrementMisses()
{
misses.incrementAndGet();
}

@Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeLong(ownedEntryCount);
out.writeLong(ownedEntryMemoryCost);
out.writeLong(hits.get());
out.writeLong(misses.get());
}

@Override
public void readData(ObjectDataInput in) throws IOException {
this.ownedEntryCount = in.readLong();
this.ownedEntryMemoryCost = in.readLong();
this.hits.set(in.readLong());
this.misses.set(in.readLong());
}


@Override
public String toString() {
return "NearCacheStatsImpl{" +
"ownedEntryCount=" + ownedEntryCount +
", ownedEntryMemoryCost=" + ownedEntryMemoryCost +
", creationTime=" + creationTime +
", hits=" + hits +
", misses=" + misses +
", ratio=" + getRatio() +
'}';
}
}
33 changes: 33 additions & 0 deletions hazelcast/src/test/java/com/hazelcast/map/NearCacheTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.instance.TestUtil;
import com.hazelcast.monitor.NearCacheStats;
import com.hazelcast.spi.impl.NodeEngineImpl;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
Expand Down Expand Up @@ -189,6 +190,38 @@ public void entryEvicted(EntryEvent event) {
assertNull(map3.get(i));
}
}
@Test
public void testNearCacheStats() throws Exception
{
String mapName = "NearCacheStatsTest";
Config config = new Config();
config.getMapConfig(mapName).setNearCacheConfig(new NearCacheConfig().setInvalidateOnChange(true));
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2);
HazelcastInstance[] instances = factory.newInstances(config);
IMap<Integer,Integer> map = instances[0].getMap("NearCacheStatsTest");

for (int i = 0; i < 1000; i++) {
map.put(i,i);
}
//populate near cache
for (int i = 0; i < 1000; i++) {
map.get(i);
}

NearCacheStats stats = map.getLocalMapStats().getNearCacheStats();

assertTrue("owned Entries", 400 < stats.getOwnedEntryCount());
assertTrue("misses", 1000 == stats.getMisses());
//make some hits
for (int i = 0; i < 1000; i++) {
map.get(i);
}
NearCacheStats stats2 = map.getLocalMapStats().getNearCacheStats();

assertTrue("hits", 400 < stats2.getHits());
assertTrue("misses", 400 < stats2.getMisses());
assertTrue("hits+misses", 2000 == stats2.getHits() + stats2.getMisses());
}

@Test
public void testNearCacheInvalidationByUsingMapPutAll() {
Expand Down