Skip to content

Commit 9e491ce

Browse files
authored
Merge pull request #17 from robbinspg/bckets
Improve bucket implementation
2 parents 9664504 + 84729e3 commit 9e491ce

File tree

6 files changed

+137
-18
lines changed

6 files changed

+137
-18
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*******************************************************************************
2+
* Copyright 2017 IBM Corp.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
******************************************************************************/
16+
package com.ibm.javametrics.agent;
17+
18+
import java.util.ArrayList;
19+
20+
public class ArrayDataBucket implements Bucket {
21+
22+
private ArrayList<String> bucket;
23+
int size = 0;
24+
int cursor = 0;
25+
private int maxBucketSize;
26+
27+
public ArrayDataBucket(int maxBucketSize) {
28+
this.maxBucketSize = maxBucketSize;
29+
bucket = new ArrayList<>(100);
30+
}
31+
32+
@Override
33+
public int getSize() {
34+
return size;
35+
}
36+
37+
@Override
38+
public void empty() {
39+
synchronized (bucket) {
40+
bucket.clear();
41+
cursor = 0;
42+
size = 0;
43+
}
44+
}
45+
46+
@Override
47+
public boolean addData(String data) {
48+
synchronized (bucket) {
49+
50+
int newSize = size + data.length();
51+
/*
52+
* Spill data if necessary
53+
*/
54+
while (newSize > maxBucketSize && cursor > 0) {
55+
String removed = bucket.remove(0);
56+
cursor--;
57+
newSize -= removed.length();
58+
}
59+
60+
if (newSize > maxBucketSize) {
61+
return false;
62+
}
63+
64+
bucket.add(data);
65+
size = newSize;
66+
return true;
67+
}
68+
}
69+
70+
@Override
71+
public String getNext() {
72+
String data = null;
73+
synchronized (bucket) {
74+
if (cursor < bucket.size()) {
75+
data = bucket.get(cursor);
76+
cursor++;
77+
}
78+
}
79+
return data;
80+
}
81+
}

java/src/com/ibm/javametrics/agent/Bucket.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
package com.ibm.javametrics.agent;
1717

1818
public interface Bucket {
19-
public void pushData(String data);
19+
public boolean addData(String data);
2020

21-
public String empty();
21+
public String getNext();
22+
23+
public void empty();
2224

2325
public int getSize();
2426

java/src/com/ibm/javametrics/agent/JavaAgent.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
public class JavaAgent implements Agent {
2929

30-
private static final int MAX_BUCKET_SIZE = 1024 * 1024;
30+
private static final int MAX_BUCKET_SIZE = 2 * 1024 * 1024;
3131
private Map<String, Bucket> buckets = new HashMap<String, Bucket>();
3232
private Set<Receiver> receivers = new HashSet<Receiver>();
3333
private int collectionInterval = 2;
@@ -44,33 +44,52 @@ public JavaAgent() {
4444

4545
private void init() {
4646
exec = Executors.newSingleThreadScheduledExecutor();
47-
exec.scheduleAtFixedRate(this::empty, collectionInterval, collectionInterval, TimeUnit.SECONDS);
47+
exec.scheduleAtFixedRate(this::drain, collectionInterval, collectionInterval, TimeUnit.SECONDS);
4848
}
4949

5050
public void pushData(String type, String data) {
5151
synchronized (buckets) {
5252
Bucket bucket = buckets.get(type);
5353
if (bucket == null) {
54-
bucket = new StringDataBucket();
54+
bucket = new StringDataBucket(MAX_BUCKET_SIZE);
5555
buckets.put(type, bucket);
5656
}
57-
58-
if ((bucket.getSize() + data.length()) > MAX_BUCKET_SIZE) {
59-
emit(type, bucket.empty());
57+
if (!bucket.addData(data)) {
58+
// System.err.println("Javametrics: data dropped. Bucket size="
59+
// + bucket.getSize());
6060
}
61-
62-
bucket.pushData(data);
6361
}
6462
}
6563

66-
private void empty() {
64+
private void drain() {
6765
synchronized (buckets) {
6866
buckets.forEach((name, bucket) -> {
69-
emit(name, bucket.empty());
67+
drainBatched(name, bucket);
7068
});
7169
}
7270
}
7371

72+
@SuppressWarnings("unused")
73+
private void drain(String type, Bucket bucket) {
74+
String data = bucket.getNext();
75+
while (data != null) {
76+
emit(type, data);
77+
data = bucket.getNext();
78+
}
79+
}
80+
81+
private void drainBatched(String type, Bucket bucket) {
82+
StringBuffer sb = new StringBuffer();
83+
String data = bucket.getNext();
84+
while (data != null) {
85+
sb.append(data);
86+
data = bucket.getNext();
87+
}
88+
if (sb.length() > 0) {
89+
emit(type, sb.toString());
90+
}
91+
}
92+
7493
private void emit(String type, String data) {
7594
if (data != null) {
7695
receivers.forEach((receiver) -> {

java/src/com/ibm/javametrics/agent/StringDataBucket.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,38 @@ public class StringDataBucket implements Bucket {
2020
private static final int INITIAL_BUCKET_SIZE = 4 * 1024;
2121
private StringBuffer bucket = new StringBuffer(INITIAL_BUCKET_SIZE);
2222

23+
private int maxBucketSize;
24+
25+
public StringDataBucket(int maxBucketSize) {
26+
this.maxBucketSize = maxBucketSize;
27+
}
28+
2329
@Override
2430
public int getSize() {
2531
return bucket.length();
2632
}
2733

2834
@Override
29-
public String empty() {
30-
String data = bucket.toString();
35+
public void empty() {
3136
bucket = new StringBuffer(INITIAL_BUCKET_SIZE);
32-
return data;
3337
}
3438

3539
@Override
36-
public void pushData(String data) {
40+
public boolean addData(String data) {
41+
if ((getSize() + data.length()) > maxBucketSize) {
42+
return false;
43+
}
3744
bucket.append(data);
45+
return true;
46+
}
47+
48+
@Override
49+
public String getNext() {
50+
String data = null;
51+
if (bucket.length() > 0) {
52+
data = bucket.toString();
53+
bucket = new StringBuffer(INITIAL_BUCKET_SIZE);
54+
}
55+
return data;
3856
}
3957
}

java/src/com/ibm/javametrics/impl/JavametricsImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public JavametricsImpl() {
5151

5252
private void initializeProviders() {
5353
/*
54-
* Start the mbean data providers
54+
* Start the data providers
5555
*/
5656
providerManager = new DataProviderManager(COLLECTION_INTERVAL);
5757
}

web/src/com/ibm/javametrics/web/DataHandler.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import java.io.StringReader;
1919
import java.util.ArrayList;
20-
import java.util.HashMap;
2120
import java.util.HashSet;
2221
import java.util.Iterator;
2322
import java.util.List;

0 commit comments

Comments
 (0)