diff --git a/CHANGELOG.md b/CHANGELOG.md index 04cc063f..ac0e9240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - cpu metrics hot reload [#228](https://github.com/tarantool/metrics/issues/228) - cartridge metrics role fails to start without http [#225](https://github.com/tarantool/metrics/issues/225) +- quantile overflow after `fiber.yield()` [#235](https://github.com/tarantool/metrics/issues/235) ## [0.8.0] - 2021-04-13 ### Added diff --git a/metrics/quantile.lua b/metrics/quantile.lua index cce24e59..5b79354b 100644 --- a/metrics/quantile.lua +++ b/metrics/quantile.lua @@ -1,11 +1,12 @@ -local fiber = require('fiber') local ffi = require('ffi') local quantile = {} -ffi.cdef[[ - typedef struct {int Delta, Width; double Value; } sample; -]] +if not pcall(ffi.typeof, "sample") then + ffi.cdef[[ + typedef struct sample {int Delta, Width; double Value; } sample; + ]] +end local sample_constructor = ffi.typeof('sample') @@ -134,9 +135,6 @@ function stream:merge(samples, len) local i = 1 local r = 0 for z = 1, len do - if i % 1000 == 0 then - fiber.yield() - end local sample = samples[z-1] for j = i, s.l_len do local c = s.l[j] @@ -165,9 +163,6 @@ function stream:query(q) local p = s.l[0] local r = 0 for i = 1, s.l_len do - if i % 500 == 0 then - fiber.yield() - end local c = s.l[i] if r + c.Width + c.Delta > t then return p.Value @@ -189,9 +184,6 @@ function stream:compress() local r = s.n - x.Width for i = s.l_len - 1, 1, -1 do - if i % 1000 == 0 then - fiber.yield() - end local c = make_sample(0) sample_copy(c, s.l[i]) if c.Width + x.Width + x.Delta <= s.f(s, r) then diff --git a/test/quantile_test.lua b/test/quantile_test.lua index 96cdef07..04654d72 100644 --- a/test/quantile_test.lua +++ b/test/quantile_test.lua @@ -1,4 +1,5 @@ local quantile = require('metrics.quantile') +local fiber = require('fiber') local ffi = require('ffi') local t = require('luatest') local g = t.group('quantile') @@ -104,3 +105,21 @@ g.test_package_reload = function() local ok, quantile_package = pcall(require, 'metrics.quantile') t.assert(ok, quantile_package) end + +g.test_fiber_yield = function() + local q1 = quantile.NewTargeted({[0.5]=0.01, [0.9]=0.01, [0.99]=0.01}, 1000) + + for _=1,10 do + fiber.create(function() + for _=1,1e2 do + t.assert(q1.b_len < q1.__max_samples) + quantile.Insert(q1, math.random(1000)) + end + end) + end + + for _=1,10 do + t.assert(q1.b_len < q1.__max_samples) + quantile.Insert(q1, math.random(1)) + end +end