From d03b059107a6228acde1fa631c8eeaa9d9ab364c Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Fri, 7 Apr 2017 13:18:05 +0300 Subject: [PATCH] Cache length of buffered data If a complete response is delivered in many buffers, then calling gwbuf_length() whenever you need the complete size starts to hurt. By caching the length of the data received sofar and by updating the length in clientReply(), gwbuf_length() will be called exactly once for each buffer(chain) delivered to routeQuery(). --- .../filter/cache/cachefiltersession.cc | 21 ++++++++++++------- .../filter/cache/cachefiltersession.hh | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/server/modules/filter/cache/cachefiltersession.cc b/server/modules/filter/cache/cachefiltersession.cc index 279ace633..f537b7abe 100644 --- a/server/modules/filter/cache/cachefiltersession.cc +++ b/server/modules/filter/cache/cachefiltersession.cc @@ -386,21 +386,23 @@ int CacheFilterSession::clientReply(GWBUF* pData) if (m_res.pData) { gwbuf_append(m_res.pData, pData); + m_res.length += gwbuf_length(pData); // pData may be a chain, so not GWBUF_LENGTH(). } else { m_res.pData = pData; + m_res.length = gwbuf_length(pData); } if (m_state != CACHE_IGNORING_RESPONSE) { - if (cache_max_resultset_size_exceeded(m_pCache->config(), gwbuf_length(m_res.pData))) + if (cache_max_resultset_size_exceeded(m_pCache->config(), m_res.length)) { if (log_decisions()) { - MXS_NOTICE("Current size %uB of resultset, at least as much " + MXS_NOTICE("Current size %luB of resultset, at least as much " "as maximum allowed size %luKiB. Not caching.", - gwbuf_length(m_res.pData), + m_res.length, m_pCache->config().max_resultset_size / 1024); } @@ -466,7 +468,8 @@ int CacheFilterSession::handle_expecting_fields() bool insufficient = false; - size_t buflen = gwbuf_length(m_res.pData); + size_t buflen = m_res.length; + ss_dassert(m_res.length == gwbuf_length(m_res.pData)); while (!insufficient && (buflen - m_res.offset >= MYSQL_HEADER_LEN)) { @@ -528,7 +531,8 @@ int CacheFilterSession::handle_expecting_response() int rv = 1; - size_t buflen = gwbuf_length(m_res.pData); + size_t buflen = m_res.length; + ss_dassert(m_res.length == gwbuf_length(m_res.pData)); if (buflen >= MYSQL_HEADER_LEN + 1) // We need the command byte. { @@ -601,7 +605,8 @@ int CacheFilterSession::handle_expecting_rows() bool insufficient = false; - size_t buflen = gwbuf_length(m_res.pData); + size_t buflen = m_res.length; + ss_dassert(m_res.length == gwbuf_length(m_res.pData)); while (!insufficient && (buflen - m_res.offset >= MYSQL_HEADER_LEN)) { @@ -661,7 +666,8 @@ int CacheFilterSession::handle_expecting_use_response() int rv = 1; - size_t buflen = gwbuf_length(m_res.pData); + size_t buflen = m_res.length; + ss_dassert(m_res.length == gwbuf_length(m_res.pData)); if (buflen >= MYSQL_HEADER_LEN + 1) // We need the command byte. { @@ -733,6 +739,7 @@ int CacheFilterSession::send_upstream() void CacheFilterSession::reset_response_state() { m_res.pData = NULL; + m_res.length = 0; m_res.nTotalFields = 0; m_res.nFields = 0; m_res.nRows = 0; diff --git a/server/modules/filter/cache/cachefiltersession.hh b/server/modules/filter/cache/cachefiltersession.hh index 29631a00c..a2ea2e083 100644 --- a/server/modules/filter/cache/cachefiltersession.hh +++ b/server/modules/filter/cache/cachefiltersession.hh @@ -35,6 +35,7 @@ public: struct CACHE_RESPONSE_STATE { GWBUF* pData; /**< Response data, possibly incomplete. */ + size_t length; /**< Length of pData. */ size_t nTotalFields; /**< The number of fields a resultset contains. */ size_t nFields; /**< How many fields we have received, <= n_totalfields. */ size_t nRows; /**< How many rows we have received. */