Skip to content

Commit 144022e

Browse files
Eliminate wlocks when updating existing histograms, gauges (#116)
apcu_add always takes a wlock in the current version 5.1.22, which leads to lots of lock contention in high concurrency scenarios. Since the most common operation ought to be updating an already existing key, wrap apcu_add in an apcu_exists that only takes a rlock. Signed-off-by: Tobias Bengtsson <[email protected]> Co-authored-by: Lukas Kämmerling <[email protected]>
1 parent bf7d43e commit 144022e

File tree

2 files changed

+27
-13
lines changed

2 files changed

+27
-13
lines changed

src/Prometheus/Storage/APC.php

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,13 @@ public function updateHistogram(array $data): void
5656
{
5757
// Initialize the sum
5858
$sumKey = $this->histogramBucketValueKey($data, 'sum');
59-
$new = apcu_add($sumKey, $this->toBinaryRepresentationAsInteger(0));
59+
if (!apcu_exists($sumKey)) {
60+
$new = apcu_add($sumKey, $this->toBinaryRepresentationAsInteger(0));
6061

61-
// If sum does not exist, assume a new histogram and store the metadata
62-
if ($new) {
63-
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
62+
// If sum does not exist, assume a new histogram and store the metadata
63+
if ($new) {
64+
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
65+
}
6466
}
6567

6668
// Atomically increment the sum
@@ -83,8 +85,11 @@ public function updateHistogram(array $data): void
8385
}
8486

8587
// Initialize and increment the bucket
86-
apcu_add($this->histogramBucketValueKey($data, $bucketToIncrease), 0);
87-
apcu_inc($this->histogramBucketValueKey($data, $bucketToIncrease));
88+
$bucketKey = $this->histogramBucketValueKey($data, $bucketToIncrease);
89+
if (!apcu_exists($bucketKey)) {
90+
apcu_add($bucketKey, 0);
91+
}
92+
apcu_inc($bucketKey);
8893
}
8994

9095
/**
@@ -94,11 +99,15 @@ public function updateSummary(array $data): void
9499
{
95100
// store meta
96101
$metaKey = $this->metaKey($data);
97-
apcu_add($metaKey, $this->metaData($data));
102+
if (!apcu_exists($metaKey)) {
103+
apcu_add($metaKey, $this->metaData($data));
104+
}
98105

99106
// store value key
100107
$valueKey = $this->valueKey($data);
101-
apcu_add($valueKey, $this->encodeLabelValues($data['labelValues']));
108+
if (!apcu_exists($valueKey)) {
109+
apcu_add($valueKey, $this->encodeLabelValues($data['labelValues']));
110+
}
102111

103112
// trick to handle uniqid collision
104113
$done = false;
@@ -118,9 +127,11 @@ public function updateGauge(array $data): void
118127
apcu_store($valueKey, $this->toBinaryRepresentationAsInteger($data['value']));
119128
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
120129
} else {
121-
$new = apcu_add($valueKey, $this->toBinaryRepresentationAsInteger(0));
122-
if ($new) {
123-
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
130+
if (!apcu_exists($valueKey)) {
131+
$new = apcu_add($valueKey, $this->toBinaryRepresentationAsInteger(0));
132+
if ($new) {
133+
apcu_store($this->metaKey($data), json_encode($this->metaData($data)));
134+
}
124135
}
125136
// Taken from https://github.com/prometheus/client_golang/blob/66058aac3a83021948e5fb12f1f408ff556b9037/prometheus/value.go#L91
126137
$done = false;

src/Prometheus/Storage/APCng.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,11 @@ public function updateHistogram(array $data): void
113113
}
114114

115115
// Initialize and increment the bucket
116-
apcu_add($this->histogramBucketValueKey($data, $bucketToIncrease), 0);
117-
apcu_inc($this->histogramBucketValueKey($data, $bucketToIncrease));
116+
$bucketKey = $this->histogramBucketValueKey($data, $bucketToIncrease);
117+
if (!apcu_exists($bucketKey)) {
118+
apcu_add($bucketKey, 0);
119+
}
120+
apcu_inc($bucketKey);
118121
}
119122

120123
/**

0 commit comments

Comments
 (0)