Merge branch 'release-6.2' into merge-release-6.2-into-release-6.3

# Conflicts:
#	cmake/ConfigureCompiler.cmake
#	documentation/sphinx/source/downloads.rst
#	fdbrpc/FlowTransport.actor.cpp
#	fdbrpc/fdbrpc.vcxproj
#	fdbserver/DataDistributionQueue.actor.cpp
#	fdbserver/Knobs.cpp
#	fdbserver/Knobs.h
#	fdbserver/LogSystemPeekCursor.actor.cpp
#	fdbserver/MasterProxyServer.actor.cpp
#	fdbserver/Status.actor.cpp
#	fdbserver/storageserver.actor.cpp
#	flow/flow.vcxproj
This commit is contained in:
A.J. Beamon 2020-07-10 15:06:34 -07:00
commit b09dddc07e
41 changed files with 504 additions and 119 deletions

View File

@ -4,6 +4,7 @@ env_set(USE_GPERFTOOLS OFF BOOL "Use gperfools for profiling")
env_set(USE_DTRACE ON BOOL "Enable dtrace probes on supported platforms") env_set(USE_DTRACE ON BOOL "Enable dtrace probes on supported platforms")
env_set(USE_VALGRIND OFF BOOL "Compile for valgrind usage") env_set(USE_VALGRIND OFF BOOL "Compile for valgrind usage")
env_set(USE_VALGRIND_FOR_CTEST ${USE_VALGRIND} BOOL "Use valgrind for ctest") env_set(USE_VALGRIND_FOR_CTEST ${USE_VALGRIND} BOOL "Use valgrind for ctest")
env_set(VALGRIND_ARENA OFF BOOL "Inform valgrind about arena-allocated memory. Makes valgrind slower but more precise.")
env_set(ALLOC_INSTRUMENTATION OFF BOOL "Instrument alloc") env_set(ALLOC_INSTRUMENTATION OFF BOOL "Instrument alloc")
env_set(WITH_UNDODB OFF BOOL "Use rr or undodb") env_set(WITH_UNDODB OFF BOOL "Use rr or undodb")
env_set(USE_ASAN OFF BOOL "Compile with address sanitizer") env_set(USE_ASAN OFF BOOL "Compile with address sanitizer")
@ -210,7 +211,10 @@ else()
# -msse4.2) # -msse4.2)
if (USE_VALGRIND) if (USE_VALGRIND)
add_compile_options(-DVALGRIND -DUSE_VALGRIND) add_compile_options(-DVALGRIND=1 -DUSE_VALGRIND=1)
endif()
if (VALGRIND_ARENA)
add_compile_options(-DVALGRIND_ARENA=1)
endif() endif()
if (CLANG) if (CLANG)
add_compile_options() add_compile_options()
@ -241,7 +245,10 @@ else()
-Wno-delete-non-virtual-dtor -Wno-delete-non-virtual-dtor
-Wno-undefined-var-template -Wno-undefined-var-template
-Wno-tautological-pointer-compare -Wno-tautological-pointer-compare
-Wno-format) -Wno-format
-Wredundant-move
-Wpessimizing-move
)
if (USE_CCACHE) if (USE_CCACHE)
add_compile_options( add_compile_options(
-Wno-register -Wno-register
@ -305,3 +312,4 @@ else()
endif() endif()
endif() endif()
endif() endif()

View File

@ -1158,7 +1158,7 @@ the most part, this also implies that ``T == fdb.tuple.unpack(fdb.tuple.pack(T))
.. method:: has_incomplete_versionstamp(tuple) .. method:: has_incomplete_versionstamp(tuple)
Returns ``True`` if there is at least one element contained within the tuple that is a Returns ``True`` if there is at least one element contained within the tuple that is a
:class`Versionstamp` instance that is incomplete. If there are multiple incomplete :class:`Versionstamp` instance that is incomplete. If there are multiple incomplete
:class:`Versionstamp` instances, this method will return ``True``, but trying to pack it into a :class:`Versionstamp` instances, this method will return ``True``, but trying to pack it into a
byte string will result in an error. byte string will result in an error.

View File

@ -113,6 +113,44 @@
"counter":0, "counter":0,
"roughness":0.0 "roughness":0.0
}, },
"grv_latency_statistics":{
"default":{
"count":0,
"min":0.0,
"max":0.0,
"median":0.0,
"mean":0.0,
"p25":0.0,
"p90":0.0,
"p95":0.0,
"p99":0.0,
"p99.9":0.0
}
},
"read_latency_statistics":{
"count":0,
"min":0.0,
"max":0.0,
"median":0.0,
"mean":0.0,
"p25":0.0,
"p90":0.0,
"p95":0.0,
"p99":0.0,
"p99.9":0.0
},
"commit_latency_statistics":{
"count":0,
"min":0.0,
"max":0.0,
"median":0.0,
"mean":0.0,
"p25":0.0,
"p90":0.0,
"p95":0.0,
"p99":0.0,
"p99.9":0.0
},
"grv_latency_bands":{ // How many GRV requests belong to the latency (in seconds) band (e.g., How many requests belong to [0.01,0.1] latency band). The key is the upper bound of the band and the lower bound is the next smallest band (or 0, if none). Example: {0.01: 27, 0.1: 18, 1: 1, inf: 98,filtered: 10}, we have 18 requests in [0.01, 0.1) band. "grv_latency_bands":{ // How many GRV requests belong to the latency (in seconds) band (e.g., How many requests belong to [0.01,0.1] latency band). The key is the upper bound of the band and the lower bound is the next smallest band (or 0, if none). Example: {0.01: 27, 0.1: 18, 1: 1, inf: 98,filtered: 10}, we have 18 requests in [0.01, 0.1) band.
"$map_key=upperBoundOfBand": 1 "$map_key=upperBoundOfBand": 1
}, },

View File

@ -5,9 +5,17 @@ Release Notes
6.2.23 6.2.23
====== ======
Fixes
-----
* When configured with ``usable_regions=2`` data distribution could temporarily lower the replication of a shard when moving it. `(PR #3487) <https://github.com/apple/foundationdb/pull/3487>`_
* Prevent data distribution from running out of memory by fetching the source servers for too many shards in parallel. `(PR #3487) <https://github.com/apple/foundationdb/pull/3487>`_
* Reset network connections between log routers and satellite tlogs if the latencies are larger than 500ms. `(PR #3487) <https://github.com/apple/foundationdb/pull/3487>`_
Status Status
------ ------
* Added per-process server request latency statistics reported in the role section of relevant processes. These are named ``grv_latency_statistics`` and ``commit_latency_statistics`` on proxy roles and ``read_latency_statistics`` on storage roles. `(PR #3480) <https://github.com/apple/foundationdb/pull/3480>`_
* Added ``cluster.active_primary_dc`` that indicates which datacenter is serving as the primary datacenter in multi-region setups. `(PR #3320) <https://github.com/apple/foundationdb/pull/3320>`_ * Added ``cluster.active_primary_dc`` that indicates which datacenter is serving as the primary datacenter in multi-region setups. `(PR #3320) <https://github.com/apple/foundationdb/pull/3320>`_
6.2.22 6.2.22

View File

@ -32,7 +32,7 @@
#include "fdbserver/RatekeeperInterface.h" #include "fdbserver/RatekeeperInterface.h"
#include "fdbclient/TagThrottle.h" #include "fdbclient/TagThrottle.h"
#include "flow/Stats.h" #include "fdbrpc/Stats.h"
#include "fdbrpc/TimedRequest.h" #include "fdbrpc/TimedRequest.h"
struct MasterProxyInterface { struct MasterProxyInterface {

View File

@ -30,10 +30,10 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include "flow/Stats.h"
#include "flow/flow.h" #include "flow/flow.h"
#include "fdbrpc/fdbrpc.h" #include "fdbrpc/fdbrpc.h"
#include "fdbrpc/Locality.h" #include "fdbrpc/Locality.h"
#include "fdbrpc/Stats.h"
#include "fdbclient/FDBTypes.h" #include "fdbclient/FDBTypes.h"
#include "fdbclient/CommitTransaction.h" #include "fdbclient/CommitTransaction.h"
#include "fdbserver/CoordinationInterface.h" #include "fdbserver/CoordinationInterface.h"

View File

@ -136,6 +136,44 @@ const KeyRef JSONSchemas::statusSchema = LiteralStringRef(R"statusSchema(
"counter":0, "counter":0,
"roughness":0.0 "roughness":0.0
}, },
"grv_latency_statistics":{
"default":{
"count":0,
"min":0.0,
"max":0.0,
"median":0.0,
"mean":0.0,
"p25":0.0,
"p90":0.0,
"p95":0.0,
"p99":0.0,
"p99.9":0.0
}
},
"read_latency_statistics":{
"count":0,
"min":0.0,
"max":0.0,
"median":0.0,
"mean":0.0,
"p25":0.0,
"p90":0.0,
"p95":0.0,
"p99":0.0,
"p99.9":0.0
},
"commit_latency_statistics":{
"count":0,
"min":0.0,
"max":0.0,
"median":0.0,
"mean":0.0,
"p25":0.0,
"p90":0.0,
"p95":0.0,
"p99":0.0,
"p99.9":0.0
},
"grv_latency_bands":{ "grv_latency_bands":{
"$map": 1 "$map": 1
}, },

View File

@ -27,7 +27,7 @@
#include "fdbrpc/QueueModel.h" #include "fdbrpc/QueueModel.h"
#include "fdbrpc/fdbrpc.h" #include "fdbrpc/fdbrpc.h"
#include "fdbrpc/LoadBalance.actor.h" #include "fdbrpc/LoadBalance.actor.h"
#include "flow/Stats.h" #include "fdbrpc/Stats.h"
#include "fdbrpc/TimedRequest.h" #include "fdbrpc/TimedRequest.h"
#include "fdbclient/TagThrottle.h" #include "fdbclient/TagThrottle.h"

View File

@ -23,6 +23,8 @@ set(FDBRPC_SRCS
ReplicationPolicy.cpp ReplicationPolicy.cpp
ReplicationTypes.cpp ReplicationTypes.cpp
ReplicationUtils.cpp ReplicationUtils.cpp
Stats.actor.cpp
Stats.h
sim2.actor.cpp sim2.actor.cpp
sim_validation.cpp sim_validation.cpp
TimedRequest.h TimedRequest.h

View File

@ -50,7 +50,7 @@ public:
return *this; return *this;
} }
double mean() { double mean() const {
if (!samples.size()) return 0; if (!samples.size()) return 0;
T sum = 0; T sum = 0;
for( int c = 0; c < samples.size(); c++ ) for( int c = 0; c < samples.size(); c++ )
@ -70,8 +70,8 @@ public:
return samples[ idx ]; return samples[ idx ];
} }
T min() { return _min; } T min() const { return _min; }
T max() { return _max; } T max() const { return _max; }
void clear() { void clear() {
samples.clear(); samples.clear();
@ -80,6 +80,10 @@ public:
_min = _max = 0; // Doesn't work for all T _min = _max = 0; // Doesn't work for all T
} }
uint64_t getPopulationSize() const {
return populationSize;
}
private: private:
int sampleSize; int sampleSize;
uint64_t populationSize; uint64_t populationSize;

View File

@ -563,7 +563,9 @@ ACTOR Future<Void> connectionKeeper( Reference<Peer> self,
self->transport->countConnEstablished++; self->transport->countConnEstablished++;
if (!delayedHealthUpdateF.isValid()) if (!delayedHealthUpdateF.isValid())
delayedHealthUpdateF = delayedHealthUpdate(self->destination); delayedHealthUpdateF = delayedHealthUpdate(self->destination);
wait(connectionWriter(self, conn) || reader || connectionMonitor(self)); wait(connectionWriter(self, conn) || reader || connectionMonitor(self) || self->resetConnection.onTrigger());
TraceEvent("ConnectionReset", conn ? conn->getDebugID() : UID()).suppressFor(1.0).detail("PeerAddr", self->destination);
throw connection_failed();
} catch (Error& e) { } catch (Error& e) {
if (e.code() == error_code_connection_failed || e.code() == error_code_actor_cancelled || if (e.code() == error_code_connection_failed || e.code() == error_code_actor_cancelled ||
e.code() == error_code_connection_unreferenced || e.code() == error_code_connection_unreferenced ||
@ -574,8 +576,6 @@ ACTOR Future<Void> connectionKeeper( Reference<Peer> self,
throw e; throw e;
} }
ASSERT( false );
} catch (Error& e) { } catch (Error& e) {
delayedHealthUpdateF.cancel(); delayedHealthUpdateF.cancel();
if(now() - self->lastConnectTime > FLOW_KNOBS->RECONNECTION_RESET_TIME) { if(now() - self->lastConnectTime > FLOW_KNOBS->RECONNECTION_RESET_TIME) {
@ -1439,6 +1439,13 @@ Reference<AsyncVar<bool>> FlowTransport::getDegraded() {
return self->degraded; return self->degraded;
} }
void FlowTransport::resetConnection( NetworkAddress address ) {
auto peer = self->getPeer(address);
if(peer) {
peer->resetConnection.trigger();
}
}
bool FlowTransport::incompatibleOutgoingConnectionsPresent() { bool FlowTransport::incompatibleOutgoingConnectionsPresent() {
return self->numIncompatibleConnections > 0; return self->numIncompatibleConnections > 0;
} }

View File

@ -132,6 +132,7 @@ struct Peer : public ReferenceCounted<Peer> {
AsyncTrigger dataToSend; // Triggered when unsent.empty() becomes false AsyncTrigger dataToSend; // Triggered when unsent.empty() becomes false
Future<Void> connect; Future<Void> connect;
AsyncTrigger resetPing; AsyncTrigger resetPing;
AsyncTrigger resetConnection;
bool compatible; bool compatible;
bool outgoingConnectionIdle; // We don't actually have a connection open and aren't trying to open one because we don't have anything to send bool outgoingConnectionIdle; // We don't actually have a connection open and aren't trying to open one because we don't have anything to send
double lastConnectTime; double lastConnectTime;
@ -213,6 +214,9 @@ public:
Reference<AsyncVar<bool>> getDegraded(); Reference<AsyncVar<bool>> getDegraded();
// This async var will be set to true when the process cannot connect to a public network address that the failure monitor thinks is healthy. // This async var will be set to true when the process cannot connect to a public network address that the failure monitor thinks is healthy.
void resetConnection( NetworkAddress address );
// Forces the connection with this address to be reset
Reference<Peer> sendUnreliable( ISerializeSource const& what, const Endpoint& destination, bool openConnection );// { cancelReliable(sendReliable(what,destination)); } Reference<Peer> sendUnreliable( ISerializeSource const& what, const Endpoint& destination, bool openConnection );// { cancelReliable(sendReliable(what,destination)); }
bool incompatibleOutgoingConnectionsPresent(); bool incompatibleOutgoingConnectionsPresent();

View File

@ -18,7 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include "flow/Stats.h" #include "fdbrpc/Stats.h"
#include "flow/actorcompiler.h" // has to be last include #include "flow/actorcompiler.h" // has to be last include
Counter::Counter(std::string const& name, CounterCollection& collection) Counter::Counter(std::string const& name, CounterCollection& collection)

View File

@ -18,8 +18,8 @@
* limitations under the License. * limitations under the License.
*/ */
#ifndef FLOW_STATS_H #ifndef FDBRPC_STATS_H
#define FLOW_STATS_H #define FDBRPC_STATS_H
#pragma once #pragma once
// Yet another performance statistics interface // Yet another performance statistics interface
@ -37,6 +37,7 @@ MyCounters() : foo("foo", cc), bar("bar", cc), baz("baz", cc) {}
#include <cstddef> #include <cstddef>
#include "flow/flow.h" #include "flow/flow.h"
#include "flow/TDMetric.actor.h" #include "flow/TDMetric.actor.h"
#include "fdbrpc/ContinuousSample.h"
struct ICounter { struct ICounter {
// All counters have a name and value // All counters have a name and value
@ -211,4 +212,43 @@ private:
bands.insert(std::make_pair(value, new Counter(format("Band%f", value), *cc))); bands.insert(std::make_pair(value, new Counter(format("Band%f", value), *cc)));
} }
}; };
class LatencySample {
public:
LatencySample(std::string name, UID id, double loggingInterval, int sampleSize) : name(name), id(id), sample(sampleSize), sampleStart(now()) {
logger = recurring([this](){ logSample(); }, loggingInterval);
}
void addMeasurement(double measurement) {
sample.addSample(measurement);
}
private:
std::string name;
UID id;
double sampleStart;
ContinuousSample<double> sample;
Future<Void> logger;
void logSample() {
TraceEvent(name.c_str(), id)
.detail("Count", sample.getPopulationSize())
.detail("Elapsed", now() - sampleStart)
.detail("Min", sample.min())
.detail("Max", sample.max())
.detail("Mean", sample.mean())
.detail("Median", sample.median())
.detail("P25", sample.percentile(0.25))
.detail("P90", sample.percentile(0.9))
.detail("P95", sample.percentile(0.95))
.detail("P99", sample.percentile(0.99))
.detail("P99.9", sample.percentile(0.999))
.trackLatest(id.toString() + "/" + name);
sample.clear();
sampleStart = now();
}
};
#endif #endif

View File

@ -27,8 +27,8 @@
#elif !defined(FLOW_BATCHER_ACTOR_H) #elif !defined(FLOW_BATCHER_ACTOR_H)
#define FLOW_BATCHER_ACTOR_H #define FLOW_BATCHER_ACTOR_H
#include "fdbrpc/Stats.h"
#include "flow/flow.h" #include "flow/flow.h"
#include "flow/Stats.h"
#include "flow/actorcompiler.h" // This must be the last #include. #include "flow/actorcompiler.h" // This must be the last #include.
template <class X> template <class X>

View File

@ -768,6 +768,14 @@ struct DDTeamCollection : ReferenceCounted<DDTeamCollection> {
} }
} }
bool foundSrc = false;
for( int i = 0; i < req.src.size(); i++ ) {
if( self->server_info.count( req.src[i] ) ) {
foundSrc = true;
break;
}
}
// Select the best team // Select the best team
// Currently the metric is minimum used disk space (adjusted for data in flight) // Currently the metric is minimum used disk space (adjusted for data in flight)
// Only healthy teams may be selected. The team has to be healthy at the moment we update // Only healthy teams may be selected. The team has to be healthy at the moment we update
@ -778,7 +786,7 @@ struct DDTeamCollection : ReferenceCounted<DDTeamCollection> {
// self->teams.size() can be 0 under the ConfigureTest.txt test when we change configurations // self->teams.size() can be 0 under the ConfigureTest.txt test when we change configurations
// The situation happens rarely. We may want to eliminate this situation someday // The situation happens rarely. We may want to eliminate this situation someday
if( !self->teams.size() ) { if( !self->teams.size() ) {
req.reply.send( Optional<Reference<IDataDistributionTeam>>() ); req.reply.send( std::make_pair(Optional<Reference<IDataDistributionTeam>>(), foundSrc) );
return Void(); return Void();
} }
@ -804,7 +812,8 @@ struct DDTeamCollection : ReferenceCounted<DDTeamCollection> {
} }
} }
if(found && teamList[j]->isHealthy()) { if(found && teamList[j]->isHealthy()) {
req.reply.send( teamList[j] ); bestOption = teamList[j];
req.reply.send( std::make_pair(bestOption, foundSrc) );
return Void(); return Void();
} }
} }
@ -895,7 +904,8 @@ struct DDTeamCollection : ReferenceCounted<DDTeamCollection> {
} }
} }
if(found) { if(found) {
req.reply.send( teamList[j] ); bestOption = teamList[j];
req.reply.send( std::make_pair(bestOption, foundSrc) );
return Void(); return Void();
} }
} }
@ -906,7 +916,7 @@ struct DDTeamCollection : ReferenceCounted<DDTeamCollection> {
// self->traceAllInfo(true); // self->traceAllInfo(true);
// } // }
req.reply.send( bestOption ); req.reply.send( std::make_pair(bestOption, foundSrc) );
return Void(); return Void();
} catch( Error &e ) { } catch( Error &e ) {

View File

@ -77,7 +77,8 @@ struct GetTeamRequest {
bool teamMustHaveShards; bool teamMustHaveShards;
double inflightPenalty; double inflightPenalty;
std::vector<UID> completeSources; std::vector<UID> completeSources;
Promise< Optional< Reference<IDataDistributionTeam> > > reply; std::vector<UID> src;
Promise< std::pair<Optional<Reference<IDataDistributionTeam>>,bool> > reply;
GetTeamRequest() {} GetTeamRequest() {}
GetTeamRequest( bool wantsNewServers, bool wantsTrueBest, bool preferLowerUtilization, bool teamMustHaveShards, double inflightPenalty = 1.0 ) GetTeamRequest( bool wantsNewServers, bool wantsTrueBest, bool preferLowerUtilization, bool teamMustHaveShards, double inflightPenalty = 1.0 )

View File

@ -358,6 +358,7 @@ struct DDQueueData {
FlowLock startMoveKeysParallelismLock; FlowLock startMoveKeysParallelismLock;
FlowLock finishMoveKeysParallelismLock; FlowLock finishMoveKeysParallelismLock;
Reference<FlowLock> fetchSourceLock;
int activeRelocations; int activeRelocations;
int queuedRelocations; int queuedRelocations;
@ -425,7 +426,7 @@ struct DDQueueData {
activeRelocations( 0 ), queuedRelocations( 0 ), bytesWritten ( 0 ), teamCollections( teamCollections ), activeRelocations( 0 ), queuedRelocations( 0 ), bytesWritten ( 0 ), teamCollections( teamCollections ),
shardsAffectedByTeamFailure( sABTF ), getAverageShardBytes( getAverageShardBytes ), distributorId( mid ), lock( lock ), shardsAffectedByTeamFailure( sABTF ), getAverageShardBytes( getAverageShardBytes ), distributorId( mid ), lock( lock ),
cx( cx ), teamSize( teamSize ), singleRegionTeamSize( singleRegionTeamSize ), output( output ), input( input ), getShardMetrics( getShardMetrics ), startMoveKeysParallelismLock( SERVER_KNOBS->DD_MOVE_KEYS_PARALLELISM ), cx( cx ), teamSize( teamSize ), singleRegionTeamSize( singleRegionTeamSize ), output( output ), input( input ), getShardMetrics( getShardMetrics ), startMoveKeysParallelismLock( SERVER_KNOBS->DD_MOVE_KEYS_PARALLELISM ),
finishMoveKeysParallelismLock( SERVER_KNOBS->DD_MOVE_KEYS_PARALLELISM ), lastLimited(lastLimited), finishMoveKeysParallelismLock( SERVER_KNOBS->DD_MOVE_KEYS_PARALLELISM ), fetchSourceLock( new FlowLock(SERVER_KNOBS->DD_FETCH_SOURCE_PARALLELISM) ), lastLimited(lastLimited),
suppressIntervals(0), lastInterval(0), unhealthyRelocations(0), rawProcessingUnhealthy( new AsyncVar<bool>(false) ) {} suppressIntervals(0), lastInterval(0), unhealthyRelocations(0), rawProcessingUnhealthy( new AsyncVar<bool>(false) ) {}
void validate() { void validate() {
@ -531,7 +532,7 @@ struct DDQueueData {
} }
} }
ACTOR Future<Void> getSourceServersForRange( Database cx, RelocateData input, PromiseStream<RelocateData> output ) { ACTOR Future<Void> getSourceServersForRange( Database cx, RelocateData input, PromiseStream<RelocateData> output, Reference<FlowLock> fetchLock ) {
state std::set<UID> servers; state std::set<UID> servers;
state Transaction tr(cx); state Transaction tr(cx);
@ -542,6 +543,9 @@ struct DDQueueData {
wait( delay( 0.0001, TaskPriority::DataDistributionLaunch ) ); wait( delay( 0.0001, TaskPriority::DataDistributionLaunch ) );
} }
wait( fetchLock->take( TaskPriority::DataDistributionLaunch ) );
state FlowLock::Releaser releaser( *fetchLock );
loop { loop {
servers.clear(); servers.clear();
tr.setOption( FDBTransactionOptions::PRIORITY_SYSTEM_IMMEDIATE ); tr.setOption( FDBTransactionOptions::PRIORITY_SYSTEM_IMMEDIATE );
@ -683,7 +687,7 @@ struct DDQueueData {
startRelocation(rrs.priority, rrs.healthPriority); startRelocation(rrs.priority, rrs.healthPriority);
fetchingSourcesQueue.insert( rrs ); fetchingSourcesQueue.insert( rrs );
getSourceActors.insert( rrs.keys, getSourceServersForRange( cx, rrs, fetchSourceServersComplete ) ); getSourceActors.insert( rrs.keys, getSourceServersForRange( cx, rrs, fetchSourceServersComplete, fetchSourceLock ) );
} else { } else {
RelocateData newData( rrs ); RelocateData newData( rrs );
newData.keys = affectedQueuedItems[r]; newData.keys = affectedQueuedItems[r];
@ -944,30 +948,26 @@ ACTOR Future<Void> dataDistributionRelocator( DDQueueData *self, RelocateData rd
if(rd.healthPriority == SERVER_KNOBS->PRIORITY_POPULATE_REGION || rd.healthPriority == SERVER_KNOBS->PRIORITY_TEAM_1_LEFT || rd.healthPriority == SERVER_KNOBS->PRIORITY_TEAM_0_LEFT) inflightPenalty = SERVER_KNOBS->INFLIGHT_PENALTY_ONE_LEFT; if(rd.healthPriority == SERVER_KNOBS->PRIORITY_POPULATE_REGION || rd.healthPriority == SERVER_KNOBS->PRIORITY_TEAM_1_LEFT || rd.healthPriority == SERVER_KNOBS->PRIORITY_TEAM_0_LEFT) inflightPenalty = SERVER_KNOBS->INFLIGHT_PENALTY_ONE_LEFT;
auto req = GetTeamRequest(rd.wantsNewServers, rd.priority == SERVER_KNOBS->PRIORITY_REBALANCE_UNDERUTILIZED_TEAM, true, false, inflightPenalty); auto req = GetTeamRequest(rd.wantsNewServers, rd.priority == SERVER_KNOBS->PRIORITY_REBALANCE_UNDERUTILIZED_TEAM, true, false, inflightPenalty);
req.src = rd.src;
req.completeSources = rd.completeSources; req.completeSources = rd.completeSources;
Optional<Reference<IDataDistributionTeam>> bestTeam = wait(brokenPromiseToNever(self->teamCollections[tciIndex].getTeam.getReply(req))); std::pair<Optional<Reference<IDataDistributionTeam>>,bool> bestTeam = wait(brokenPromiseToNever(self->teamCollections[tciIndex].getTeam.getReply(req)));
// If a DC has no healthy team, we stop checking the other DCs until // If a DC has no healthy team, we stop checking the other DCs until
// the unhealthy DC is healthy again or is excluded. // the unhealthy DC is healthy again or is excluded.
if(!bestTeam.present()) { if(!bestTeam.first.present()) {
foundTeams = false; foundTeams = false;
break; break;
} }
if(!bestTeam.get()->isHealthy()) { if(!bestTeam.first.get()->isHealthy()) {
allHealthy = false; allHealthy = false;
} else { } else {
anyHealthy = true; anyHealthy = true;
} }
bool foundSource = false;
if(!rd.wantsNewServers && self->teamCollections.size() > 1) { if(bestTeam.second) {
for(auto& it : bestTeam.get()->getServerIDs()) { anyWithSource = true;
if(std::find(rd.src.begin(), rd.src.end(), it) != rd.src.end()) {
foundSource = true;
anyWithSource = true;
break;
}
}
} }
bestTeams.push_back(std::make_pair(bestTeam.get(), foundSource));
bestTeams.push_back(std::make_pair(bestTeam.first.get(), bestTeam.second));
tciIndex++; tciIndex++;
} }
if (foundTeams && anyHealthy) { if (foundTeams && anyHealthy) {
@ -1223,7 +1223,7 @@ ACTOR Future<Void> BgDDMountainChopper( DDQueueData* self, int teamCollectionInd
state double lastRead = 0; state double lastRead = 0;
state bool skipCurrentLoop = false; state bool skipCurrentLoop = false;
loop { loop {
state Optional<Reference<IDataDistributionTeam>> randomTeam; state std::pair<Optional<Reference<IDataDistributionTeam>>, bool> randomTeam;
state bool moved = false; state bool moved = false;
state TraceEvent traceEvent("BgDDMountainChopper", self->distributorId); state TraceEvent traceEvent("BgDDMountainChopper", self->distributorId);
traceEvent.suppressFor(5.0) traceEvent.suppressFor(5.0)
@ -1259,26 +1259,26 @@ ACTOR Future<Void> BgDDMountainChopper( DDQueueData* self, int teamCollectionInd
traceEvent.detail("QueuedRelocations", self->priority_relocations[SERVER_KNOBS->PRIORITY_REBALANCE_OVERUTILIZED_TEAM]); traceEvent.detail("QueuedRelocations", self->priority_relocations[SERVER_KNOBS->PRIORITY_REBALANCE_OVERUTILIZED_TEAM]);
if (self->priority_relocations[SERVER_KNOBS->PRIORITY_REBALANCE_OVERUTILIZED_TEAM] < if (self->priority_relocations[SERVER_KNOBS->PRIORITY_REBALANCE_OVERUTILIZED_TEAM] <
SERVER_KNOBS->DD_REBALANCE_PARALLELISM) { SERVER_KNOBS->DD_REBALANCE_PARALLELISM) {
Optional<Reference<IDataDistributionTeam>> _randomTeam = wait(brokenPromiseToNever( std::pair<Optional<Reference<IDataDistributionTeam>>,bool> _randomTeam = wait(brokenPromiseToNever(
self->teamCollections[teamCollectionIndex].getTeam.getReply(GetTeamRequest(true, false, true, false)))); self->teamCollections[teamCollectionIndex].getTeam.getReply(GetTeamRequest(true, false, true, false))));
randomTeam = _randomTeam; randomTeam = _randomTeam;
traceEvent.detail("DestTeam", printable(randomTeam.map<std::string>([](const Reference<IDataDistributionTeam>& team){ traceEvent.detail("DestTeam", printable(randomTeam.first.map<std::string>([](const Reference<IDataDistributionTeam>& team){
return team->getDesc(); return team->getDesc();
}))); })));
if (randomTeam.present()) { if (randomTeam.first.present()) {
Optional<Reference<IDataDistributionTeam>> loadedTeam = std::pair<Optional<Reference<IDataDistributionTeam>>,bool> loadedTeam =
wait(brokenPromiseToNever(self->teamCollections[teamCollectionIndex].getTeam.getReply( wait(brokenPromiseToNever(self->teamCollections[teamCollectionIndex].getTeam.getReply(
GetTeamRequest(true, true, false, true)))); GetTeamRequest(true, true, false, true))));
traceEvent.detail("SourceTeam", printable(loadedTeam.map<std::string>([](const Reference<IDataDistributionTeam>& team){ traceEvent.detail("SourceTeam", printable(loadedTeam.first.map<std::string>([](const Reference<IDataDistributionTeam>& team){
return team->getDesc(); return team->getDesc();
}))); })));
if (loadedTeam.present()) { if (loadedTeam.first.present()) {
bool _moved = bool _moved =
wait(rebalanceTeams(self, SERVER_KNOBS->PRIORITY_REBALANCE_OVERUTILIZED_TEAM, loadedTeam.get(), wait(rebalanceTeams(self, SERVER_KNOBS->PRIORITY_REBALANCE_OVERUTILIZED_TEAM, loadedTeam.first.get(),
randomTeam.get(), teamCollectionIndex == 0, &traceEvent)); randomTeam.first.get(), teamCollectionIndex == 0, &traceEvent));
moved = _moved; moved = _moved;
if (moved) { if (moved) {
resetCount = 0; resetCount = 0;
@ -1323,7 +1323,7 @@ ACTOR Future<Void> BgDDValleyFiller( DDQueueData* self, int teamCollectionIndex)
state bool skipCurrentLoop = false; state bool skipCurrentLoop = false;
loop { loop {
state Optional<Reference<IDataDistributionTeam>> randomTeam; state std::pair<Optional<Reference<IDataDistributionTeam>>, bool> randomTeam;
state bool moved = false; state bool moved = false;
state TraceEvent traceEvent("BgDDValleyFiller", self->distributorId); state TraceEvent traceEvent("BgDDValleyFiller", self->distributorId);
traceEvent.suppressFor(5.0) traceEvent.suppressFor(5.0)
@ -1359,25 +1359,25 @@ ACTOR Future<Void> BgDDValleyFiller( DDQueueData* self, int teamCollectionIndex)
traceEvent.detail("QueuedRelocations", self->priority_relocations[SERVER_KNOBS->PRIORITY_REBALANCE_UNDERUTILIZED_TEAM]); traceEvent.detail("QueuedRelocations", self->priority_relocations[SERVER_KNOBS->PRIORITY_REBALANCE_UNDERUTILIZED_TEAM]);
if (self->priority_relocations[SERVER_KNOBS->PRIORITY_REBALANCE_UNDERUTILIZED_TEAM] < if (self->priority_relocations[SERVER_KNOBS->PRIORITY_REBALANCE_UNDERUTILIZED_TEAM] <
SERVER_KNOBS->DD_REBALANCE_PARALLELISM) { SERVER_KNOBS->DD_REBALANCE_PARALLELISM) {
Optional<Reference<IDataDistributionTeam>> _randomTeam = wait(brokenPromiseToNever( std::pair<Optional<Reference<IDataDistributionTeam>>,bool> _randomTeam = wait(brokenPromiseToNever(
self->teamCollections[teamCollectionIndex].getTeam.getReply(GetTeamRequest(true, false, false, true)))); self->teamCollections[teamCollectionIndex].getTeam.getReply(GetTeamRequest(true, false, false, true))));
randomTeam = _randomTeam; randomTeam = _randomTeam;
traceEvent.detail("SourceTeam", printable(randomTeam.map<std::string>([](const Reference<IDataDistributionTeam>& team){ traceEvent.detail("SourceTeam", printable(randomTeam.first.map<std::string>([](const Reference<IDataDistributionTeam>& team){
return team->getDesc(); return team->getDesc();
}))); })));
if (randomTeam.present()) { if (randomTeam.first.present()) {
Optional<Reference<IDataDistributionTeam>> unloadedTeam = wait(brokenPromiseToNever( std::pair<Optional<Reference<IDataDistributionTeam>>,bool> unloadedTeam = wait(brokenPromiseToNever(
self->teamCollections[teamCollectionIndex].getTeam.getReply(GetTeamRequest(true, true, true, false)))); self->teamCollections[teamCollectionIndex].getTeam.getReply(GetTeamRequest(true, true, true, false))));
traceEvent.detail("DestTeam", printable(unloadedTeam.map<std::string>([](const Reference<IDataDistributionTeam>& team){ traceEvent.detail("DestTeam", printable(unloadedTeam.first.map<std::string>([](const Reference<IDataDistributionTeam>& team){
return team->getDesc(); return team->getDesc();
}))); })));
if (unloadedTeam.present()) { if (unloadedTeam.first.present()) {
bool _moved = bool _moved =
wait(rebalanceTeams(self, SERVER_KNOBS->PRIORITY_REBALANCE_UNDERUTILIZED_TEAM, randomTeam.get(), wait(rebalanceTeams(self, SERVER_KNOBS->PRIORITY_REBALANCE_UNDERUTILIZED_TEAM, randomTeam.first.get(),
unloadedTeam.get(), teamCollectionIndex == 0, &traceEvent)); unloadedTeam.first.get(), teamCollectionIndex == 0, &traceEvent));
moved = _moved; moved = _moved;
if (moved) { if (moved) {
resetCount = 0; resetCount = 0;

View File

@ -90,6 +90,12 @@ void ServerKnobs::initialize(bool randomize, ClientKnobs* clientKnobs, bool isSi
init( TLOG_MAX_CREATE_DURATION, 10.0 ); init( TLOG_MAX_CREATE_DURATION, 10.0 );
init( PEEK_LOGGING_AMOUNT, 5 ); init( PEEK_LOGGING_AMOUNT, 5 );
init( PEEK_LOGGING_DELAY, 5.0 ); init( PEEK_LOGGING_DELAY, 5.0 );
init( PEEK_RESET_INTERVAL, 300.0 ); if ( randomize && BUGGIFY ) PEEK_RESET_INTERVAL = 20.0;
init( PEEK_MAX_LATENCY, 0.5 ); if ( randomize && BUGGIFY ) PEEK_MAX_LATENCY = 0.0;
init( PEEK_COUNT_SMALL_MESSAGES, false ); if ( randomize && BUGGIFY ) PEEK_COUNT_SMALL_MESSAGES = true;
init( PEEK_STATS_INTERVAL, 10.0 );
init( PEEK_STATS_SLOW_AMOUNT, 0 );
init( PEEK_STATS_SLOW_RATIO, 0.5 );
// disk snapshot max timeout, to be put in TLog, storage and coordinator nodes // disk snapshot max timeout, to be put in TLog, storage and coordinator nodes
init( SNAP_CREATE_MAX_TIMEOUT, 300.0 ); init( SNAP_CREATE_MAX_TIMEOUT, 300.0 );
@ -216,6 +222,7 @@ void ServerKnobs::initialize(bool randomize, ClientKnobs* clientKnobs, bool isSi
init( DD_SHARD_SIZE_GRANULARITY, 5000000 ); init( DD_SHARD_SIZE_GRANULARITY, 5000000 );
init( DD_SHARD_SIZE_GRANULARITY_SIM, 500000 ); if( randomize && BUGGIFY ) DD_SHARD_SIZE_GRANULARITY_SIM = 0; init( DD_SHARD_SIZE_GRANULARITY_SIM, 500000 ); if( randomize && BUGGIFY ) DD_SHARD_SIZE_GRANULARITY_SIM = 0;
init( DD_MOVE_KEYS_PARALLELISM, 15 ); if( randomize && BUGGIFY ) DD_MOVE_KEYS_PARALLELISM = 1; init( DD_MOVE_KEYS_PARALLELISM, 15 ); if( randomize && BUGGIFY ) DD_MOVE_KEYS_PARALLELISM = 1;
init( DD_FETCH_SOURCE_PARALLELISM, 1000 ); if( randomize && BUGGIFY ) DD_FETCH_SOURCE_PARALLELISM = 1;
init( DD_MERGE_LIMIT, 2000 ); if( randomize && BUGGIFY ) DD_MERGE_LIMIT = 2; init( DD_MERGE_LIMIT, 2000 ); if( randomize && BUGGIFY ) DD_MERGE_LIMIT = 2;
init( DD_SHARD_METRICS_TIMEOUT, 60.0 ); if( randomize && BUGGIFY ) DD_SHARD_METRICS_TIMEOUT = 0.1; init( DD_SHARD_METRICS_TIMEOUT, 60.0 ); if( randomize && BUGGIFY ) DD_SHARD_METRICS_TIMEOUT = 0.1;
init( DD_LOCATION_CACHE_SIZE, 2000000 ); if( randomize && BUGGIFY ) DD_LOCATION_CACHE_SIZE = 3; init( DD_LOCATION_CACHE_SIZE, 2000000 ); if( randomize && BUGGIFY ) DD_LOCATION_CACHE_SIZE = 3;
@ -639,6 +646,10 @@ void ServerKnobs::initialize(bool randomize, ClientKnobs* clientKnobs, bool isSi
init( REDWOOD_REMAP_CLEANUP_VERSION_LAG_MIN, 4 ); init( REDWOOD_REMAP_CLEANUP_VERSION_LAG_MIN, 4 );
init( REDWOOD_REMAP_CLEANUP_VERSION_LAG_MAX, 15 ); init( REDWOOD_REMAP_CLEANUP_VERSION_LAG_MAX, 15 );
init( REDWOOD_LOGGING_INTERVAL, 5.0 ); init( REDWOOD_LOGGING_INTERVAL, 5.0 );
// Server request latency measurement
init( LATENCY_SAMPLE_SIZE, 100000 );
init( LATENCY_METRICS_LOGGING_INTERVAL, 60.0 );
// clang-format on // clang-format on

View File

@ -88,6 +88,12 @@ public:
double TLOG_MAX_CREATE_DURATION; double TLOG_MAX_CREATE_DURATION;
int PEEK_LOGGING_AMOUNT; int PEEK_LOGGING_AMOUNT;
double PEEK_LOGGING_DELAY; double PEEK_LOGGING_DELAY;
double PEEK_RESET_INTERVAL;
double PEEK_MAX_LATENCY;
bool PEEK_COUNT_SMALL_MESSAGES;
double PEEK_STATS_INTERVAL;
double PEEK_STATS_SLOW_AMOUNT;
double PEEK_STATS_SLOW_RATIO;
// Data distribution queue // Data distribution queue
double HEALTH_POLL_TIME; double HEALTH_POLL_TIME;
@ -165,6 +171,7 @@ public:
int64_t DD_SHARD_SIZE_GRANULARITY; int64_t DD_SHARD_SIZE_GRANULARITY;
int64_t DD_SHARD_SIZE_GRANULARITY_SIM; int64_t DD_SHARD_SIZE_GRANULARITY_SIM;
int DD_MOVE_KEYS_PARALLELISM; int DD_MOVE_KEYS_PARALLELISM;
int DD_FETCH_SOURCE_PARALLELISM;
int DD_MERGE_LIMIT; int DD_MERGE_LIMIT;
double DD_SHARD_METRICS_TIMEOUT; double DD_SHARD_METRICS_TIMEOUT;
int64_t DD_LOCATION_CACHE_SIZE; int64_t DD_LOCATION_CACHE_SIZE;
@ -571,6 +578,10 @@ public:
int REDWOOD_REMAP_CLEANUP_VERSION_LAG_MIN; // Number of versions between head of remap queue and oldest retained version before remap cleanup starts int REDWOOD_REMAP_CLEANUP_VERSION_LAG_MIN; // Number of versions between head of remap queue and oldest retained version before remap cleanup starts
int REDWOOD_REMAP_CLEANUP_VERSION_LAG_MAX; // Number of versions between head of remap queue and oldest retained version before remap cleanup may stop int REDWOOD_REMAP_CLEANUP_VERSION_LAG_MAX; // Number of versions between head of remap queue and oldest retained version before remap cleanup may stop
double REDWOOD_LOGGING_INTERVAL; double REDWOOD_LOGGING_INTERVAL;
// Server request latency measurement
int LATENCY_SAMPLE_SIZE;
double LATENCY_METRICS_LOGGING_INTERVAL;
ServerKnobs(); ServerKnobs();
void initialize(bool randomize = false, ClientKnobs* clientKnobs = NULL, bool isSimulated = false); void initialize(bool randomize = false, ClientKnobs* clientKnobs = NULL, bool isSimulated = false);

View File

@ -20,6 +20,7 @@
#include "flow/ActorCollection.h" #include "flow/ActorCollection.h"
#include "fdbclient/NativeAPI.actor.h" #include "fdbclient/NativeAPI.actor.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/WorkerInterface.actor.h" #include "fdbserver/WorkerInterface.actor.h"
#include "fdbserver/WaitFailure.h" #include "fdbserver/WaitFailure.h"
#include "fdbserver/Knobs.h" #include "fdbserver/Knobs.h"
@ -30,7 +31,6 @@
#include "fdbserver/RecoveryState.h" #include "fdbserver/RecoveryState.h"
#include "fdbclient/Atomic.h" #include "fdbclient/Atomic.h"
#include "flow/TDMetric.actor.h" #include "flow/TDMetric.actor.h"
#include "flow/Stats.h"
#include "flow/actorcompiler.h" // This must be the last #include. #include "flow/actorcompiler.h" // This must be the last #include.
struct LogRouterData { struct LogRouterData {

View File

@ -406,6 +406,12 @@ struct ILogSystem {
Deque<Future<TLogPeekReply>> futureResults; Deque<Future<TLogPeekReply>> futureResults;
Future<Void> interfaceChanged; Future<Void> interfaceChanged;
double lastReset;
Future<Void> resetCheck;
int slowReplies;
int fastReplies;
int unknownReplies;
ServerPeekCursor( Reference<AsyncVar<OptionalInterface<TLogInterface>>> const& interf, Tag tag, Version begin, Version end, bool returnIfBlocked, bool parallelGetMore ); ServerPeekCursor( Reference<AsyncVar<OptionalInterface<TLogInterface>>> const& interf, Tag tag, Version begin, Version end, bool returnIfBlocked, bool parallelGetMore );
ServerPeekCursor( TLogPeekReply const& results, LogMessageVersion const& messageVersion, LogMessageVersion const& end, TagsAndMessage const& message, bool hasMsg, Version poppedVersion, Tag tag ); ServerPeekCursor( TLogPeekReply const& results, LogMessageVersion const& messageVersion, LogMessageVersion const& end, TagsAndMessage const& message, bool hasMsg, Version poppedVersion, Tag tag );

View File

@ -25,14 +25,17 @@
#include "flow/actorcompiler.h" // has to be last include #include "flow/actorcompiler.h" // has to be last include
ILogSystem::ServerPeekCursor::ServerPeekCursor( Reference<AsyncVar<OptionalInterface<TLogInterface>>> const& interf, Tag tag, Version begin, Version end, bool returnIfBlocked, bool parallelGetMore ) ILogSystem::ServerPeekCursor::ServerPeekCursor( Reference<AsyncVar<OptionalInterface<TLogInterface>>> const& interf, Tag tag, Version begin, Version end, bool returnIfBlocked, bool parallelGetMore )
: interf(interf), tag(tag), messageVersion(begin), end(end), hasMsg(false), rd(results.arena, results.messages, Unversioned()), randomID(deterministicRandom()->randomUniqueID()), poppedVersion(0), returnIfBlocked(returnIfBlocked), sequence(0), onlySpilled(false), parallelGetMore(parallelGetMore) { : interf(interf), tag(tag), messageVersion(begin), end(end), hasMsg(false), rd(results.arena, results.messages, Unversioned()), randomID(deterministicRandom()->randomUniqueID()), poppedVersion(0),
returnIfBlocked(returnIfBlocked), sequence(0), onlySpilled(false), parallelGetMore(parallelGetMore), lastReset(0), slowReplies(0), fastReplies(0), unknownReplies(0), resetCheck(Void())
{
this->results.maxKnownVersion = 0; this->results.maxKnownVersion = 0;
this->results.minKnownCommittedVersion = 0; this->results.minKnownCommittedVersion = 0;
//TraceEvent("SPC_Starting", randomID).detail("Tag", tag.toString()).detail("Begin", begin).detail("End", end).backtrace(); //TraceEvent("SPC_Starting", randomID).detail("Tag", tag.toString()).detail("Begin", begin).detail("End", end).backtrace();
} }
ILogSystem::ServerPeekCursor::ServerPeekCursor( TLogPeekReply const& results, LogMessageVersion const& messageVersion, LogMessageVersion const& end, TagsAndMessage const& message, bool hasMsg, Version poppedVersion, Tag tag ) ILogSystem::ServerPeekCursor::ServerPeekCursor( TLogPeekReply const& results, LogMessageVersion const& messageVersion, LogMessageVersion const& end, TagsAndMessage const& message, bool hasMsg, Version poppedVersion, Tag tag )
: results(results), tag(tag), rd(results.arena, results.messages, Unversioned()), messageVersion(messageVersion), end(end), messageAndTags(message), hasMsg(hasMsg), randomID(deterministicRandom()->randomUniqueID()), poppedVersion(poppedVersion), returnIfBlocked(false), sequence(0), onlySpilled(false), parallelGetMore(false) : results(results), tag(tag), rd(results.arena, results.messages, Unversioned()), messageVersion(messageVersion), end(end), messageAndTags(message), hasMsg(hasMsg),
randomID(deterministicRandom()->randomUniqueID()), poppedVersion(poppedVersion), returnIfBlocked(false), sequence(0), onlySpilled(false), parallelGetMore(false), lastReset(0), slowReplies(0), fastReplies(0), unknownReplies(0), resetCheck(Void())
{ {
//TraceEvent("SPC_Clone", randomID); //TraceEvent("SPC_Clone", randomID);
this->results.maxKnownVersion = 0; this->results.maxKnownVersion = 0;
@ -131,6 +134,46 @@ void ILogSystem::ServerPeekCursor::advanceTo(LogMessageVersion n) {
} }
} }
ACTOR Future<Void> resetChecker( ILogSystem::ServerPeekCursor* self, NetworkAddress addr ) {
self->slowReplies = 0;
self->unknownReplies = 0;
self->fastReplies = 0;
wait(delay(SERVER_KNOBS->PEEK_STATS_INTERVAL));
TraceEvent("SlowPeekStats").detail("SlowReplies", self->slowReplies).detail("FastReplies", self->fastReplies).detail("UnknownReplies", self->unknownReplies);
if(self->slowReplies >= SERVER_KNOBS->PEEK_STATS_SLOW_AMOUNT && self->slowReplies/double(self->slowReplies+self->fastReplies) >= SERVER_KNOBS->PEEK_STATS_SLOW_RATIO) {
FlowTransport::transport().resetConnection(addr);
self->lastReset = now();
}
return Void();
}
ACTOR Future<TLogPeekReply> recordRequestMetrics( ILogSystem::ServerPeekCursor* self, NetworkAddress addr, Future<TLogPeekReply> in ) {
try {
state double startTime = now();
TLogPeekReply t = wait(in);
if(now()-self->lastReset > SERVER_KNOBS->PEEK_RESET_INTERVAL) {
if(now()-startTime > SERVER_KNOBS->PEEK_MAX_LATENCY) {
if(t.messages.size() >= SERVER_KNOBS->DESIRED_TOTAL_BYTES || SERVER_KNOBS->PEEK_COUNT_SMALL_MESSAGES) {
if(self->resetCheck.isReady()) {
self->resetCheck = resetChecker(self, addr);
}
self->slowReplies++;
} else {
self->unknownReplies++;
}
} else {
self->fastReplies++;
}
}
return t;
} catch (Error& e) {
if (e.code() != error_code_broken_promise)
throw;
wait(Never()); // never return
throw internal_error(); // does not happen
}
}
ACTOR Future<Void> serverPeekParallelGetMore( ILogSystem::ServerPeekCursor* self, TaskPriority taskID ) { ACTOR Future<Void> serverPeekParallelGetMore( ILogSystem::ServerPeekCursor* self, TaskPriority taskID ) {
if( !self->interf || self->messageVersion >= self->end ) { if( !self->interf || self->messageVersion >= self->end ) {
if( self->hasMessage() ) if( self->hasMessage() )
@ -148,7 +191,7 @@ ACTOR Future<Void> serverPeekParallelGetMore( ILogSystem::ServerPeekCursor* self
try { try {
if (self->parallelGetMore || self->onlySpilled) { if (self->parallelGetMore || self->onlySpilled) {
while(self->futureResults.size() < SERVER_KNOBS->PARALLEL_GET_MORE_REQUESTS && self->interf->get().present()) { while(self->futureResults.size() < SERVER_KNOBS->PARALLEL_GET_MORE_REQUESTS && self->interf->get().present()) {
self->futureResults.push_back( brokenPromiseToNever( self->interf->get().interf().peekMessages.getReply(TLogPeekRequest(self->messageVersion.version,self->tag,self->returnIfBlocked, self->onlySpilled, std::make_pair(self->randomID, self->sequence++)), taskID) ) ); self->futureResults.push_back( recordRequestMetrics( self, self->interf->get().interf().peekMessages.getEndpoint().getPrimaryAddress(), self->interf->get().interf().peekMessages.getReply(TLogPeekRequest(self->messageVersion.version,self->tag,self->returnIfBlocked, self->onlySpilled, std::make_pair(self->randomID, self->sequence++)), taskID) ) );
} }
if (self->sequence == std::numeric_limits<decltype(self->sequence)>::max()) { if (self->sequence == std::numeric_limits<decltype(self->sequence)>::max()) {
throw operation_obsolete(); throw operation_obsolete();

View File

@ -28,6 +28,7 @@
#include "fdbclient/Notified.h" #include "fdbclient/Notified.h"
#include "fdbclient/SystemData.h" #include "fdbclient/SystemData.h"
#include "fdbrpc/sim_validation.h" #include "fdbrpc/sim_validation.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/ApplyMetadataMutation.h" #include "fdbserver/ApplyMetadataMutation.h"
#include "fdbserver/ConflictSet.h" #include "fdbserver/ConflictSet.h"
#include "fdbserver/DataDistributorInterface.h" #include "fdbserver/DataDistributorInterface.h"
@ -44,7 +45,6 @@
#include "fdbserver/WorkerInterface.actor.h" #include "fdbserver/WorkerInterface.actor.h"
#include "flow/ActorCollection.h" #include "flow/ActorCollection.h"
#include "flow/Knobs.h" #include "flow/Knobs.h"
#include "flow/Stats.h"
#include "flow/TDMetric.actor.h" #include "flow/TDMetric.actor.h"
#include "flow/actorcompiler.h" // This must be the last #include. #include "flow/actorcompiler.h" // This must be the last #include.
@ -88,6 +88,9 @@ struct ProxyStats {
Counter keyServerLocationIn, keyServerLocationOut, keyServerLocationErrors; Counter keyServerLocationIn, keyServerLocationOut, keyServerLocationErrors;
Version lastCommitVersionAssigned; Version lastCommitVersionAssigned;
LatencySample commitLatencySample;
LatencySample grvLatencySample;
LatencyBands commitLatencyBands; LatencyBands commitLatencyBands;
LatencyBands grvLatencyBands; LatencyBands grvLatencyBands;
@ -136,6 +139,8 @@ struct ProxyStats {
conflictRanges("ConflictRanges", cc), keyServerLocationIn("KeyServerLocationIn", cc), conflictRanges("ConflictRanges", cc), keyServerLocationIn("KeyServerLocationIn", cc),
keyServerLocationOut("KeyServerLocationOut", cc), keyServerLocationErrors("KeyServerLocationErrors", cc), keyServerLocationOut("KeyServerLocationOut", cc), keyServerLocationErrors("KeyServerLocationErrors", cc),
lastCommitVersionAssigned(0), lastCommitVersionAssigned(0),
commitLatencySample("CommitLatencyMetrics", id, SERVER_KNOBS->LATENCY_METRICS_LOGGING_INTERVAL, SERVER_KNOBS->LATENCY_SAMPLE_SIZE),
grvLatencySample("GRVLatencyMetrics", id, SERVER_KNOBS->LATENCY_METRICS_LOGGING_INTERVAL, SERVER_KNOBS->LATENCY_SAMPLE_SIZE),
commitLatencyBands("CommitLatencyMetrics", id, SERVER_KNOBS->STORAGE_LOGGING_DELAY), commitLatencyBands("CommitLatencyMetrics", id, SERVER_KNOBS->STORAGE_LOGGING_DELAY),
grvLatencyBands("GRVLatencyMetrics", id, SERVER_KNOBS->STORAGE_LOGGING_DELAY) { grvLatencyBands("GRVLatencyMetrics", id, SERVER_KNOBS->STORAGE_LOGGING_DELAY) {
specialCounter(cc, "LastAssignedCommitVersion", [this](){return this->lastCommitVersionAssigned;}); specialCounter(cc, "LastAssignedCommitVersion", [this](){return this->lastCommitVersionAssigned;});
@ -1331,9 +1336,11 @@ ACTOR Future<Void> commitBatch(
for (int resolverInd : transactionResolverMap[t]) nextTr[resolverInd]++; for (int resolverInd : transactionResolverMap[t]) nextTr[resolverInd]++;
// TODO: filter if pipelined with large commit // TODO: filter if pipelined with large commit
double duration = endTime - trs[t].requestTime();
self->stats.commitLatencySample.addMeasurement(duration);
if(self->latencyBandConfig.present()) { if(self->latencyBandConfig.present()) {
bool filter = maxTransactionBytes > self->latencyBandConfig.get().commitConfig.maxCommitBytes.orDefault(std::numeric_limits<int>::max()); bool filter = maxTransactionBytes > self->latencyBandConfig.get().commitConfig.maxCommitBytes.orDefault(std::numeric_limits<int>::max());
self->stats.commitLatencyBands.addMeasurement(endTime - trs[t].requestTime(), filter); self->stats.commitLatencyBands.addMeasurement(duration, filter);
} }
} }
@ -1439,8 +1446,12 @@ ACTOR Future<Void> sendGrvReplies(Future<GetReadVersionReply> replyFuture, std::
double end = g_network->timer(); double end = g_network->timer();
for(GetReadVersionRequest const& request : requests) { for(GetReadVersionRequest const& request : requests) {
double duration = end - request.requestTime();
if(request.priority == TransactionPriority::DEFAULT) {
stats->grvLatencySample.addMeasurement(duration);
}
if(request.priority >= TransactionPriority::DEFAULT) { if(request.priority >= TransactionPriority::DEFAULT) {
stats->grvLatencyBands.addMeasurement(end - request.requestTime()); stats->grvLatencyBands.addMeasurement(duration);
} }
if (request.flags & GetReadVersionRequest::FLAG_USE_MIN_KNOWN_COMMITTED_VERSION) { if (request.flags & GetReadVersionRequest::FLAG_USE_MIN_KNOWN_COMMITTED_VERSION) {

View File

@ -19,7 +19,6 @@
*/ */
#include "flow/Hash3.h" #include "flow/Hash3.h"
#include "flow/Stats.h"
#include "flow/UnitTest.h" #include "flow/UnitTest.h"
#include "fdbclient/NativeAPI.actor.h" #include "fdbclient/NativeAPI.actor.h"
#include "fdbclient/Notified.h" #include "fdbclient/Notified.h"
@ -33,6 +32,7 @@
#include "fdbrpc/FailureMonitor.h" #include "fdbrpc/FailureMonitor.h"
#include "fdbserver/IDiskQueue.h" #include "fdbserver/IDiskQueue.h"
#include "fdbrpc/sim_validation.h" #include "fdbrpc/sim_validation.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/ServerDBInfo.h" #include "fdbserver/ServerDBInfo.h"
#include "fdbserver/LogSystem.h" #include "fdbserver/LogSystem.h"
#include "fdbserver/WaitFailure.h" #include "fdbserver/WaitFailure.h"

View File

@ -19,7 +19,6 @@
*/ */
#include "flow/Hash3.h" #include "flow/Hash3.h"
#include "flow/Stats.h"
#include "flow/UnitTest.h" #include "flow/UnitTest.h"
#include "fdbclient/NativeAPI.actor.h" #include "fdbclient/NativeAPI.actor.h"
#include "fdbclient/Notified.h" #include "fdbclient/Notified.h"
@ -35,6 +34,7 @@
#include "fdbserver/IDiskQueue.h" #include "fdbserver/IDiskQueue.h"
#include "fdbrpc/sim_validation.h" #include "fdbrpc/sim_validation.h"
#include "fdbrpc/simulator.h" #include "fdbrpc/simulator.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/ServerDBInfo.h" #include "fdbserver/ServerDBInfo.h"
#include "fdbserver/LogSystem.h" #include "fdbserver/LogSystem.h"
#include "fdbserver/WaitFailure.h" #include "fdbserver/WaitFailure.h"

View File

@ -20,7 +20,6 @@
*/ */
#include "flow/Hash3.h" #include "flow/Hash3.h"
#include "flow/Stats.h"
#include "flow/UnitTest.h" #include "flow/UnitTest.h"
#include "fdbclient/NativeAPI.actor.h" #include "fdbclient/NativeAPI.actor.h"
#include "fdbclient/Notified.h" #include "fdbclient/Notified.h"
@ -36,6 +35,7 @@
#include "fdbserver/IDiskQueue.h" #include "fdbserver/IDiskQueue.h"
#include "fdbrpc/sim_validation.h" #include "fdbrpc/sim_validation.h"
#include "fdbrpc/simulator.h" #include "fdbrpc/simulator.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/ServerDBInfo.h" #include "fdbserver/ServerDBInfo.h"
#include "fdbserver/LogSystem.h" #include "fdbserver/LogSystem.h"
#include "fdbserver/WaitFailure.h" #include "fdbserver/WaitFailure.h"

View File

@ -28,12 +28,12 @@
#define FDBSERVER_RESTORE_APPLIER_H #define FDBSERVER_RESTORE_APPLIER_H
#include <sstream> #include <sstream>
#include "flow/Stats.h"
#include "fdbclient/Atomic.h" #include "fdbclient/Atomic.h"
#include "fdbclient/FDBTypes.h" #include "fdbclient/FDBTypes.h"
#include "fdbclient/CommitTransaction.h" #include "fdbclient/CommitTransaction.h"
#include "fdbrpc/fdbrpc.h" #include "fdbrpc/fdbrpc.h"
#include "fdbrpc/Locality.h" #include "fdbrpc/Locality.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/CoordinationInterface.h" #include "fdbserver/CoordinationInterface.h"
#include "fdbclient/RestoreWorkerInterface.actor.h" #include "fdbclient/RestoreWorkerInterface.actor.h"
#include "fdbserver/RestoreUtil.h" #include "fdbserver/RestoreUtil.h"

View File

@ -28,10 +28,10 @@
#define FDBSERVER_RESTORE_LOADER_H #define FDBSERVER_RESTORE_LOADER_H
#include <sstream> #include <sstream>
#include "flow/Stats.h"
#include "fdbclient/FDBTypes.h" #include "fdbclient/FDBTypes.h"
#include "fdbclient/CommitTransaction.h" #include "fdbclient/CommitTransaction.h"
#include "fdbrpc/fdbrpc.h" #include "fdbrpc/fdbrpc.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/CoordinationInterface.h" #include "fdbserver/CoordinationInterface.h"
#include "fdbrpc/Locality.h" #include "fdbrpc/Locality.h"
#include "fdbclient/RestoreWorkerInterface.actor.h" #include "fdbclient/RestoreWorkerInterface.actor.h"

View File

@ -28,12 +28,12 @@
#define FDBSERVER_RESTORE_MASTER_H #define FDBSERVER_RESTORE_MASTER_H
#include <sstream> #include <sstream>
#include "flow/Stats.h"
#include "flow/Platform.h" #include "flow/Platform.h"
#include "fdbclient/FDBTypes.h" #include "fdbclient/FDBTypes.h"
#include "fdbclient/CommitTransaction.h" #include "fdbclient/CommitTransaction.h"
#include "fdbrpc/fdbrpc.h" #include "fdbrpc/fdbrpc.h"
#include "fdbrpc/Locality.h" #include "fdbrpc/Locality.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/CoordinationInterface.h" #include "fdbserver/CoordinationInterface.h"
#include "fdbserver/RestoreUtil.h" #include "fdbserver/RestoreUtil.h"
#include "fdbserver/RestoreRoleCommon.actor.h" #include "fdbserver/RestoreRoleCommon.actor.h"

View File

@ -29,13 +29,13 @@
#define FDBSERVER_RestoreRoleCommon_H #define FDBSERVER_RestoreRoleCommon_H
#include <sstream> #include <sstream>
#include "flow/Stats.h"
#include "flow/SystemMonitor.h" #include "flow/SystemMonitor.h"
#include "fdbclient/FDBTypes.h" #include "fdbclient/FDBTypes.h"
#include "fdbclient/CommitTransaction.h" #include "fdbclient/CommitTransaction.h"
#include "fdbclient/Notified.h" #include "fdbclient/Notified.h"
#include "fdbrpc/fdbrpc.h" #include "fdbrpc/fdbrpc.h"
#include "fdbrpc/Locality.h" #include "fdbrpc/Locality.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/CoordinationInterface.h" #include "fdbserver/CoordinationInterface.h"
#include "fdbclient/RestoreWorkerInterface.actor.h" #include "fdbclient/RestoreWorkerInterface.actor.h"
#include "fdbserver/RestoreUtil.h" #include "fdbserver/RestoreUtil.h"

View File

@ -29,10 +29,10 @@
#include "fdbclient/Tuple.h" #include "fdbclient/Tuple.h"
#include "fdbclient/CommitTransaction.h" #include "fdbclient/CommitTransaction.h"
#include "flow/flow.h" #include "flow/flow.h"
#include "flow/Stats.h"
#include "fdbrpc/TimedRequest.h" #include "fdbrpc/TimedRequest.h"
#include "fdbrpc/fdbrpc.h" #include "fdbrpc/fdbrpc.h"
#include "fdbrpc/IAsyncFile.h" #include "fdbrpc/IAsyncFile.h"
#include "fdbrpc/Stats.h"
#include <cstdint> #include <cstdint>
#include <cstdarg> #include <cstdarg>

View File

@ -28,9 +28,9 @@
#include "fdbclient/Tuple.h" #include "fdbclient/Tuple.h"
#include "flow/flow.h" #include "flow/flow.h"
#include "flow/Stats.h"
#include "fdbrpc/fdbrpc.h" #include "fdbrpc/fdbrpc.h"
#include "fdbrpc/IAsyncFile.h" #include "fdbrpc/IAsyncFile.h"
#include "fdbrpc/Stats.h"
#include <cstdint> #include <cstdint>
#include <cstdarg> #include <cstdarg>

View File

@ -388,8 +388,24 @@ struct MachineMemoryInfo {
struct RolesInfo { struct RolesInfo {
std::multimap<NetworkAddress, JsonBuilderObject> roles; std::multimap<NetworkAddress, JsonBuilderObject> roles;
JsonBuilderObject addLatencyStatistics(TraceEventFields const& metrics) {
JsonBuilderObject latencyStats;
latencyStats.setKeyRawNumber("count", metrics.getValue("Count"));
latencyStats.setKeyRawNumber("min", metrics.getValue("Min"));
latencyStats.setKeyRawNumber("max", metrics.getValue("Max"));
latencyStats.setKeyRawNumber("median", metrics.getValue("Median"));
latencyStats.setKeyRawNumber("mean", metrics.getValue("Mean"));
latencyStats.setKeyRawNumber("p25", metrics.getValue("P25"));
latencyStats.setKeyRawNumber("p90", metrics.getValue("P90"));
latencyStats.setKeyRawNumber("p95", metrics.getValue("P95"));
latencyStats.setKeyRawNumber("p99", metrics.getValue("P99"));
latencyStats.setKeyRawNumber("p99.9", metrics.getValue("P99.9"));
return latencyStats;
}
JsonBuilderObject addLatencyBandInfo(TraceEventFields const& metrics) { JsonBuilderObject addLatencyBandInfo(TraceEventFields const& metrics) {
JsonBuilderObject latency; JsonBuilderObject latencyBands;
std::map<std::string, JsonBuilderObject> bands; std::map<std::string, JsonBuilderObject> bands;
for(auto itr = metrics.begin(); itr != metrics.end(); ++itr) { for(auto itr = metrics.begin(); itr != metrics.end(); ++itr) {
@ -404,10 +420,10 @@ struct RolesInfo {
continue; continue;
} }
latency[band] = StatusCounter(itr->second).getCounter(); latencyBands[band] = StatusCounter(itr->second).getCounter();
} }
return latency; return latencyBands;
} }
JsonBuilderObject& addRole( NetworkAddress address, std::string const& role, UID id) { JsonBuilderObject& addRole( NetworkAddress address, std::string const& role, UID id) {
@ -461,7 +477,12 @@ struct RolesInfo {
TraceEventFields const& readLatencyMetrics = metrics.at("ReadLatencyMetrics"); TraceEventFields const& readLatencyMetrics = metrics.at("ReadLatencyMetrics");
if(readLatencyMetrics.size()) { if(readLatencyMetrics.size()) {
obj["read_latency_bands"] = addLatencyBandInfo(readLatencyMetrics); obj["read_latency_statistics"] = addLatencyStatistics(readLatencyMetrics);
}
TraceEventFields const& readLatencyBands = metrics.at("ReadLatencyBands");
if(readLatencyBands.size()) {
obj["read_latency_bands"] = addLatencyBandInfo(readLatencyBands);
} }
obj["data_lag"] = getLagObject(versionLag); obj["data_lag"] = getLagObject(versionLag);
@ -536,12 +557,25 @@ struct RolesInfo {
try { try {
TraceEventFields const& grvLatencyMetrics = metrics.at("GRVLatencyMetrics"); TraceEventFields const& grvLatencyMetrics = metrics.at("GRVLatencyMetrics");
if(grvLatencyMetrics.size()) { if(grvLatencyMetrics.size()) {
obj["grv_latency_bands"] = addLatencyBandInfo(grvLatencyMetrics); JsonBuilderObject priorityStats;
// We only report default priority now, but this allows us to add other priorities if we want them
priorityStats["default"] = addLatencyStatistics(grvLatencyMetrics);
obj["grv_latency_statistics"] = priorityStats;
}
TraceEventFields const& grvLatencyBands = metrics.at("GRVLatencyBands");
if(grvLatencyBands.size()) {
obj["grv_latency_bands"] = addLatencyBandInfo(grvLatencyBands);
} }
TraceEventFields const& commitLatencyMetrics = metrics.at("CommitLatencyMetrics"); TraceEventFields const& commitLatencyMetrics = metrics.at("CommitLatencyMetrics");
if(commitLatencyMetrics.size()) { if(commitLatencyMetrics.size()) {
obj["commit_latency_bands"] = addLatencyBandInfo(commitLatencyMetrics); obj["commit_latency_statistics"] = addLatencyStatistics(commitLatencyMetrics);
}
TraceEventFields const& commitLatencyBands = metrics.at("CommitLatencyBands");
if(commitLatencyBands.size()) {
obj["commit_latency_bands"] = addLatencyBandInfo(commitLatencyBands);
} }
} catch (Error &e) { } catch (Error &e) {
if(e.code() != error_code_attribute_not_found) { if(e.code() != error_code_attribute_not_found) {
@ -1552,7 +1586,7 @@ static Future<vector<std::pair<iface, EventMap>>> getServerMetrics(vector<iface>
ACTOR static Future<vector<std::pair<StorageServerInterface, EventMap>>> getStorageServersAndMetrics(Database cx, std::unordered_map<NetworkAddress, WorkerInterface> address_workers) { ACTOR static Future<vector<std::pair<StorageServerInterface, EventMap>>> getStorageServersAndMetrics(Database cx, std::unordered_map<NetworkAddress, WorkerInterface> address_workers) {
vector<StorageServerInterface> servers = wait(timeoutError(getStorageServers(cx, true), 5.0)); vector<StorageServerInterface> servers = wait(timeoutError(getStorageServers(cx, true), 5.0));
vector<std::pair<StorageServerInterface, EventMap>> results = wait( vector<std::pair<StorageServerInterface, EventMap>> results = wait(
getServerMetrics(servers, address_workers, std::vector<std::string>{ "StorageMetrics", "ReadLatencyMetrics", "BusiestReadTag" })); getServerMetrics(servers, address_workers, std::vector<std::string>{ "StorageMetrics", "ReadLatencyMetrics", "ReadLatencyBands", "BusiestReadTag" }));
return results; return results;
} }
@ -1567,7 +1601,7 @@ ACTOR static Future<vector<std::pair<TLogInterface, EventMap>>> getTLogsAndMetri
ACTOR static Future<vector<std::pair<MasterProxyInterface, EventMap>>> getProxiesAndMetrics(Reference<AsyncVar<ServerDBInfo>> db, std::unordered_map<NetworkAddress, WorkerInterface> address_workers) { ACTOR static Future<vector<std::pair<MasterProxyInterface, EventMap>>> getProxiesAndMetrics(Reference<AsyncVar<ServerDBInfo>> db, std::unordered_map<NetworkAddress, WorkerInterface> address_workers) {
vector<std::pair<MasterProxyInterface, EventMap>> results = wait(getServerMetrics( vector<std::pair<MasterProxyInterface, EventMap>> results = wait(getServerMetrics(
db->get().client.proxies, address_workers, std::vector<std::string>{ "GRVLatencyMetrics", "CommitLatencyMetrics" })); db->get().client.proxies, address_workers, std::vector<std::string>{ "GRVLatencyMetrics", "CommitLatencyMetrics", "GRVLatencyBands", "CommitLatencyBands" }));
return results; return results;
} }

View File

@ -19,7 +19,6 @@
*/ */
#include "flow/Hash3.h" #include "flow/Hash3.h"
#include "flow/Stats.h"
#include "flow/UnitTest.h" #include "flow/UnitTest.h"
#include "fdbclient/NativeAPI.actor.h" #include "fdbclient/NativeAPI.actor.h"
#include "fdbclient/Notified.h" #include "fdbclient/Notified.h"
@ -36,6 +35,7 @@
#include "fdbserver/IDiskQueue.h" #include "fdbserver/IDiskQueue.h"
#include "fdbrpc/sim_validation.h" #include "fdbrpc/sim_validation.h"
#include "fdbrpc/simulator.h" #include "fdbrpc/simulator.h"
#include "fdbrpc/Stats.h"
#include "fdbserver/ServerDBInfo.h" #include "fdbserver/ServerDBInfo.h"
#include "fdbserver/LogSystem.h" #include "fdbserver/LogSystem.h"
#include "fdbserver/WaitFailure.h" #include "fdbserver/WaitFailure.h"

View File

@ -50,7 +50,7 @@
#include "fdbserver/WorkerInterface.actor.h" #include "fdbserver/WorkerInterface.actor.h"
#include "fdbrpc/sim_validation.h" #include "fdbrpc/sim_validation.h"
#include "fdbrpc/Smoother.h" #include "fdbrpc/Smoother.h"
#include "flow/Stats.h" #include "fdbrpc/Stats.h"
#include "flow/TDMetric.actor.h" #include "flow/TDMetric.actor.h"
#include <type_traits> #include <type_traits>
#include "flow/actorcompiler.h" // This must be the last #include. #include "flow/actorcompiler.h" // This must be the last #include.
@ -534,6 +534,7 @@ public:
Counter fetchWaitingMS, fetchWaitingCount, fetchExecutingMS, fetchExecutingCount; Counter fetchWaitingMS, fetchWaitingCount, fetchExecutingMS, fetchExecutingCount;
Counter readsRejected; Counter readsRejected;
LatencySample readLatencySample;
LatencyBands readLatencyBands; LatencyBands readLatencyBands;
Counters(StorageServer* self) Counters(StorageServer* self)
@ -564,7 +565,8 @@ public:
fetchExecutingMS("FetchExecutingMS", cc), fetchExecutingMS("FetchExecutingMS", cc),
fetchExecutingCount("FetchExecutingCount", cc), fetchExecutingCount("FetchExecutingCount", cc),
readsRejected("ReadsRejected", cc), readsRejected("ReadsRejected", cc),
readLatencyBands("ReadLatencyMetrics", self->thisServerID, SERVER_KNOBS->STORAGE_LOGGING_DELAY) readLatencySample("ReadLatencyMetrics", self->thisServerID, SERVER_KNOBS->LATENCY_METRICS_LOGGING_INTERVAL, SERVER_KNOBS->LATENCY_SAMPLE_SIZE),
readLatencyBands("ReadLatencyBands", self->thisServerID, SERVER_KNOBS->STORAGE_LOGGING_DELAY)
{ {
specialCounter(cc, "LastTLogVersion", [self](){ return self->lastTLogVersion; }); specialCounter(cc, "LastTLogVersion", [self](){ return self->lastTLogVersion; });
specialCounter(cc, "Version", [self](){ return self->version.get(); }); specialCounter(cc, "Version", [self](){ return self->version.get(); });
@ -994,9 +996,12 @@ ACTOR Future<Void> getValueQ( StorageServer* data, GetValueRequest req ) {
++data->counters.finishedQueries; ++data->counters.finishedQueries;
--data->readQueueSizeMetric; --data->readQueueSizeMetric;
double duration = timer() - req.requestTime();
data->counters.readLatencySample.addMeasurement(duration);
if(data->latencyBandConfig.present()) { if(data->latencyBandConfig.present()) {
int maxReadBytes = data->latencyBandConfig.get().readConfig.maxReadBytes.orDefault(std::numeric_limits<int>::max()); int maxReadBytes = data->latencyBandConfig.get().readConfig.maxReadBytes.orDefault(std::numeric_limits<int>::max());
data->counters.readLatencyBands.addMeasurement(timer() - req.requestTime(), resultSize > maxReadBytes); data->counters.readLatencyBands.addMeasurement(duration, resultSize > maxReadBytes);
} }
return Void(); return Void();
@ -1585,11 +1590,13 @@ ACTOR Future<Void> getKeyValuesQ( StorageServer* data, GetKeyValuesRequest req )
++data->counters.finishedQueries; ++data->counters.finishedQueries;
--data->readQueueSizeMetric; --data->readQueueSizeMetric;
double duration = timer() - req.requestTime();
data->counters.readLatencySample.addMeasurement(duration);
if(data->latencyBandConfig.present()) { if(data->latencyBandConfig.present()) {
int maxReadBytes = data->latencyBandConfig.get().readConfig.maxReadBytes.orDefault(std::numeric_limits<int>::max()); int maxReadBytes = data->latencyBandConfig.get().readConfig.maxReadBytes.orDefault(std::numeric_limits<int>::max());
int maxSelectorOffset = data->latencyBandConfig.get().readConfig.maxKeySelectorOffset.orDefault(std::numeric_limits<int>::max()); int maxSelectorOffset = data->latencyBandConfig.get().readConfig.maxKeySelectorOffset.orDefault(std::numeric_limits<int>::max());
data->counters.readLatencyBands.addMeasurement( data->counters.readLatencyBands.addMeasurement(
timer() - req.requestTime(), resultSize > maxReadBytes || abs(req.begin.offset) > maxSelectorOffset || duration, resultSize > maxReadBytes || abs(req.begin.offset) > maxSelectorOffset ||
abs(req.end.offset) > maxSelectorOffset); abs(req.end.offset) > maxSelectorOffset);
} }
@ -1648,11 +1655,14 @@ ACTOR Future<Void> getKeyQ( StorageServer* data, GetKeyRequest req ) {
++data->counters.finishedQueries; ++data->counters.finishedQueries;
--data->readQueueSizeMetric; --data->readQueueSizeMetric;
double duration = timer() - req.requestTime();
data->counters.readLatencySample.addMeasurement(duration);
if(data->latencyBandConfig.present()) { if(data->latencyBandConfig.present()) {
int maxReadBytes = data->latencyBandConfig.get().readConfig.maxReadBytes.orDefault(std::numeric_limits<int>::max()); int maxReadBytes = data->latencyBandConfig.get().readConfig.maxReadBytes.orDefault(std::numeric_limits<int>::max());
int maxSelectorOffset = data->latencyBandConfig.get().readConfig.maxKeySelectorOffset.orDefault(std::numeric_limits<int>::max()); int maxSelectorOffset = data->latencyBandConfig.get().readConfig.maxKeySelectorOffset.orDefault(std::numeric_limits<int>::max());
data->counters.readLatencyBands.addMeasurement( data->counters.readLatencyBands.addMeasurement(
timer() - req.requestTime(), resultSize > maxReadBytes || abs(req.sel.offset) > maxSelectorOffset); duration, resultSize > maxReadBytes || abs(req.sel.offset) > maxSelectorOffset);
} }
return Void(); return Void();

View File

@ -20,8 +20,98 @@
#include "Arena.h" #include "Arena.h"
// See https://dox.ipxe.org/memcheck_8h_source.html and https://dox.ipxe.org/valgrind_8h_source.html for an explanation
// of valgrind client requests
#ifdef VALGRIND_ARENA
#include <memcheck.h>
#else
// Since VALGRIND_ARENA is not set, we don't want to pay the performance penalty for precise tracking of arenas. We'll
// make these macros noops just for this translation unit.
#undef VALGRIND_MAKE_MEM_NOACCESS
#undef VALGRIND_MAKE_MEM_DEFINED
#undef VALGRIND_MAKE_MEM_UNDEFINED
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size) ((void)(addr), (void)(size))
#define VALGRIND_MAKE_MEM_DEFINED(addr, size) ((void)(addr), (void)(size))
#define VALGRIND_MAKE_MEM_UNDEFINED(addr, size) ((void)(addr), (void)(size))
#endif
// For each use of arena-internal memory (e.g. ArenaBlock::getSize()), unpoison the memory before use and
// poison it when done.
// When creating a new ArenaBlock, poison the memory that will be later allocated to users.
// When allocating memory to a user, mark that memory as undefined.
namespace {
void allow_access(ArenaBlock* b) {
if (b) {
VALGRIND_MAKE_MEM_DEFINED(b, ArenaBlock::TINY_HEADER);
int headerSize = b->isTiny() ? ArenaBlock::TINY_HEADER : sizeof(ArenaBlock);
VALGRIND_MAKE_MEM_DEFINED(b, headerSize);
}
}
void disallow_access(ArenaBlock* b) {
if (b) {
int headerSize = b->isTiny() ? ArenaBlock::TINY_HEADER : sizeof(ArenaBlock);
VALGRIND_MAKE_MEM_NOACCESS(b, headerSize);
}
}
} // namespace
Arena::Arena() : impl(NULL) {}
Arena::Arena(size_t reservedSize) : impl(0) {
UNSTOPPABLE_ASSERT(reservedSize < std::numeric_limits<int>::max());
if (reservedSize) {
allow_access(impl.getPtr());
ArenaBlock::create((int)reservedSize, impl);
disallow_access(impl.getPtr());
}
}
Arena::Arena(const Arena& r) = default;
Arena::Arena(Arena&& r) noexcept = default;
Arena& Arena::operator=(const Arena& r) = default;
Arena& Arena::operator=(Arena&& r) noexcept = default;
void Arena::dependsOn(const Arena& p) {
if (p.impl) {
allow_access(impl.getPtr());
allow_access(p.impl.getPtr());
ArenaBlock::dependOn(impl, p.impl.getPtr());
disallow_access(p.impl.getPtr());
if (p.impl.getPtr() != impl.getPtr()) {
disallow_access(impl.getPtr());
}
}
}
size_t Arena::getSize() const {
if (impl) {
allow_access(impl.getPtr());
auto result = impl->totalSize();
disallow_access(impl.getPtr());
return result;
}
return 0;
}
bool Arena::hasFree(size_t size, const void* address) {
if (impl) {
allow_access(impl.getPtr());
auto result = impl->unused() >= size && impl->getNextData() == address;
disallow_access(impl.getPtr());
return result;
}
return false;
}
void ArenaBlock::addref() {
VALGRIND_MAKE_MEM_DEFINED(this, sizeof(ThreadSafeReferenceCounted<ArenaBlock>));
ThreadSafeReferenceCounted<ArenaBlock>::addref();
VALGRIND_MAKE_MEM_NOACCESS(this, sizeof(ThreadSafeReferenceCounted<ArenaBlock>));
}
void ArenaBlock::delref() { void ArenaBlock::delref() {
if (delref_no_destroy()) destroy(); VALGRIND_MAKE_MEM_DEFINED(this, sizeof(ThreadSafeReferenceCounted<ArenaBlock>));
if (delref_no_destroy()) {
destroy();
} else {
VALGRIND_MAKE_MEM_NOACCESS(this, sizeof(ThreadSafeReferenceCounted<ArenaBlock>));
}
} }
bool ArenaBlock::isTiny() const { bool ArenaBlock::isTiny() const {
@ -52,14 +142,20 @@ const void* ArenaBlock::getNextData() const {
return (const uint8_t*)getData() + used(); return (const uint8_t*)getData() + used();
} }
size_t ArenaBlock::totalSize() { size_t ArenaBlock::totalSize() {
if (isTiny()) return size(); if (isTiny()) {
return size();
}
size_t s = size(); size_t s = size();
int o = nextBlockOffset; int o = nextBlockOffset;
while (o) { while (o) {
ArenaBlockRef* r = (ArenaBlockRef*)((char*)getData() + o); ArenaBlockRef* r = (ArenaBlockRef*)((char*)getData() + o);
VALGRIND_MAKE_MEM_DEFINED(r, sizeof(ArenaBlockRef));
allow_access(r->next);
s += r->next->totalSize(); s += r->next->totalSize();
disallow_access(r->next);
o = r->nextBlockOffset; o = r->nextBlockOffset;
VALGRIND_MAKE_MEM_NOACCESS(r, sizeof(ArenaBlockRef));
} }
return s; return s;
} }
@ -71,8 +167,10 @@ void ArenaBlock::getUniqueBlocks(std::set<ArenaBlock*>& a) {
int o = nextBlockOffset; int o = nextBlockOffset;
while (o) { while (o) {
ArenaBlockRef* r = (ArenaBlockRef*)((char*)getData() + o); ArenaBlockRef* r = (ArenaBlockRef*)((char*)getData() + o);
VALGRIND_MAKE_MEM_DEFINED(r, sizeof(ArenaBlockRef));
r->next->getUniqueBlocks(a); r->next->getUniqueBlocks(a);
o = r->nextBlockOffset; o = r->nextBlockOffset;
VALGRIND_MAKE_MEM_NOACCESS(r, sizeof(ArenaBlockRef));
} }
return; return;
} }
@ -91,8 +189,10 @@ int ArenaBlock::addUsed(int bytes) {
void ArenaBlock::makeReference(ArenaBlock* next) { void ArenaBlock::makeReference(ArenaBlock* next) {
ArenaBlockRef* r = (ArenaBlockRef*)((char*)getData() + bigUsed); ArenaBlockRef* r = (ArenaBlockRef*)((char*)getData() + bigUsed);
VALGRIND_MAKE_MEM_DEFINED(r, sizeof(ArenaBlockRef));
r->next = next; r->next = next;
r->nextBlockOffset = nextBlockOffset; r->nextBlockOffset = nextBlockOffset;
VALGRIND_MAKE_MEM_NOACCESS(r, sizeof(ArenaBlockRef));
nextBlockOffset = bigUsed; nextBlockOffset = bigUsed;
bigUsed += sizeof(ArenaBlockRef); bigUsed += sizeof(ArenaBlockRef);
} }
@ -107,9 +207,17 @@ void ArenaBlock::dependOn(Reference<ArenaBlock>& self, ArenaBlock* other) {
void* ArenaBlock::allocate(Reference<ArenaBlock>& self, int bytes) { void* ArenaBlock::allocate(Reference<ArenaBlock>& self, int bytes) {
ArenaBlock* b = self.getPtr(); ArenaBlock* b = self.getPtr();
if (!self || self->unused() < bytes) b = create(bytes, self); allow_access(b);
if (!self || self->unused() < bytes) {
auto* tmp = b;
b = create(bytes, self);
disallow_access(tmp);
}
return (char*)b->getData() + b->addUsed(bytes); void* result = (char*)b->getData() + b->addUsed(bytes);
disallow_access(b);
VALGRIND_MAKE_MEM_UNDEFINED(result, bytes);
return result;
} }
// Return an appropriately-sized ArenaBlock to store the given data // Return an appropriately-sized ArenaBlock to store the given data
@ -205,6 +313,7 @@ ArenaBlock* ArenaBlock::create(int dataSize, Reference<ArenaBlock>& next) {
} }
b->setrefCountUnsafe(1); b->setrefCountUnsafe(1);
next.setPtrUnsafe(b); next.setPtrUnsafe(b);
VALGRIND_MAKE_MEM_NOACCESS(reinterpret_cast<uint8_t*>(b) + b->used(), b->unused());
return b; return b;
} }
@ -212,18 +321,23 @@ void ArenaBlock::destroy() {
// If the stack never contains more than one item, nothing will be allocated from stackArena. // If the stack never contains more than one item, nothing will be allocated from stackArena.
// If stackArena is used, it will always be a linked list, so destroying *it* will not create another arena // If stackArena is used, it will always be a linked list, so destroying *it* will not create another arena
ArenaBlock* tinyStack = this; ArenaBlock* tinyStack = this;
allow_access(this);
Arena stackArena; Arena stackArena;
VectorRef<ArenaBlock*> stack(&tinyStack, 1); VectorRef<ArenaBlock*> stack(&tinyStack, 1);
while (stack.size()) { while (stack.size()) {
ArenaBlock* b = stack.end()[-1]; ArenaBlock* b = stack.end()[-1];
stack.pop_back(); stack.pop_back();
allow_access(b);
if (!b->isTiny()) { if (!b->isTiny()) {
int o = b->nextBlockOffset; int o = b->nextBlockOffset;
while (o) { while (o) {
ArenaBlockRef* br = (ArenaBlockRef*)((char*)b->getData() + o); ArenaBlockRef* br = (ArenaBlockRef*)((char*)b->getData() + o);
VALGRIND_MAKE_MEM_DEFINED(br, sizeof(ArenaBlockRef));
allow_access(br->next);
if (br->next->delref_no_destroy()) stack.push_back(stackArena, br->next); if (br->next->delref_no_destroy()) stack.push_back(stackArena, br->next);
disallow_access(br->next);
o = br->nextBlockOffset; o = br->nextBlockOffset;
} }
} }

View File

@ -90,23 +90,28 @@ class NonCopyable
NonCopyable & operator = (const NonCopyable &); NonCopyable & operator = (const NonCopyable &);
}; };
// An Arena is a custom allocator that consists of a set of ArenaBlocks. Allocation is performed by bumping a pointer
// on the most recent ArenaBlock until the block is unable to service the next allocation request. When the current
// ArenaBlock is full, a new (larger) one is added to the Arena. Deallocation is not directly supported. Instead,
// memory is freed by deleting the entire Arena at once. See flow/README.md for details on using Arenas.
class Arena { class Arena {
public: public:
inline Arena(); Arena();
inline explicit Arena( size_t reservedSize ); explicit Arena(size_t reservedSize);
//~Arena(); //~Arena();
Arena(const Arena&); Arena(const Arena&);
Arena(Arena && r) BOOST_NOEXCEPT; Arena(Arena && r) BOOST_NOEXCEPT;
Arena& operator=(const Arena&); Arena& operator=(const Arena&);
Arena& operator=(Arena&&) BOOST_NOEXCEPT; Arena& operator=(Arena&&) BOOST_NOEXCEPT;
inline void dependsOn( const Arena& p ); void dependsOn(const Arena& p);
inline size_t getSize() const; size_t getSize() const;
inline bool hasFree( size_t size, const void *address ); bool hasFree(size_t size, const void* address);
friend void* operator new ( size_t size, Arena& p ); friend void* operator new ( size_t size, Arena& p );
friend void* operator new[] ( size_t size, Arena& p ); friend void* operator new[] ( size_t size, Arena& p );
//private: //private:
Reference<struct ArenaBlock> impl; Reference<struct ArenaBlock> impl;
}; };
@ -144,6 +149,7 @@ struct ArenaBlock : NonCopyable, ThreadSafeReferenceCounted<ArenaBlock>
uint32_t bigSize, bigUsed; // include block header uint32_t bigSize, bigUsed; // include block header
uint32_t nextBlockOffset; uint32_t nextBlockOffset;
void addref();
void delref(); void delref();
bool isTiny() const; bool isTiny() const;
int size() const; int size() const;
@ -167,28 +173,6 @@ private:
static void* operator new(size_t s); // not implemented static void* operator new(size_t s); // not implemented
}; };
inline Arena::Arena() : impl( NULL ) {}
inline Arena::Arena(size_t reservedSize) : impl( 0 ) {
UNSTOPPABLE_ASSERT( reservedSize < std::numeric_limits<int>::max() );
if (reservedSize)
ArenaBlock::create((int)reservedSize,impl);
}
inline Arena::Arena( const Arena& r ) : impl( r.impl ) {}
inline Arena::Arena(Arena && r) BOOST_NOEXCEPT : impl(std::move(r.impl)) {}
inline Arena& Arena::operator=(const Arena& r) {
impl = r.impl;
return *this;
}
inline Arena& Arena::operator=(Arena&& r) BOOST_NOEXCEPT {
impl = std::move(r.impl);
return *this;
}
inline void Arena::dependsOn( const Arena& p ) {
if (p.impl)
ArenaBlock::dependOn( impl, p.impl.getPtr() );
}
inline size_t Arena::getSize() const { return impl ? impl->totalSize() : 0; }
inline bool Arena::hasFree( size_t size, const void *address ) { return impl && impl->unused() >= size && impl->getNextData() == address; }
inline void* operator new ( size_t size, Arena& p ) { inline void* operator new ( size_t size, Arena& p ) {
UNSTOPPABLE_ASSERT( size < std::numeric_limits<int>::max() ); UNSTOPPABLE_ASSERT( size < std::numeric_limits<int>::max() );
return ArenaBlock::allocate( p.impl, (int)size ); return ArenaBlock::allocate( p.impl, (int)size );

View File

@ -46,8 +46,6 @@ set(FLOW_SRCS
SignalSafeUnwind.cpp SignalSafeUnwind.cpp
SignalSafeUnwind.h SignalSafeUnwind.h
SimpleOpt.h SimpleOpt.h
Stats.actor.cpp
Stats.h
SystemMonitor.cpp SystemMonitor.cpp
SystemMonitor.h SystemMonitor.h
TDMetric.actor.h TDMetric.actor.h

View File

@ -333,6 +333,9 @@ void FastAllocator<Size>::release(void *ptr) {
ASSERT(!thr.freelist == (thr.count == 0)); // freelist is empty if and only if count is 0 ASSERT(!thr.freelist == (thr.count == 0)); // freelist is empty if and only if count is 0
#if VALGRIND
VALGRIND_MAKE_MEM_DEFINED(ptr, sizeof(void*));
#endif
++thr.count; ++thr.count;
*(void**)ptr = thr.freelist; *(void**)ptr = thr.freelist;
//check(ptr, false); //check(ptr, false);

View File

@ -615,7 +615,7 @@ namespace actorcompiler
{ {
LineNumber(cx.target, stmt.FirstSourceLine); LineNumber(cx.target, stmt.FirstSourceLine);
if (stmt.decl.initializerConstructorSyntax || stmt.decl.initializer=="") if (stmt.decl.initializerConstructorSyntax || stmt.decl.initializer=="")
cx.target.WriteLine("{0} = std::move( {1}({2}) );", stmt.decl.name, stmt.decl.type, stmt.decl.initializer); cx.target.WriteLine("{0} = {1}({2});", stmt.decl.name, stmt.decl.type, stmt.decl.initializer);
else else
cx.target.WriteLine("{0} = {1};", stmt.decl.name, stmt.decl.initializer); cx.target.WriteLine("{0} = {1};", stmt.decl.name, stmt.decl.initializer);
} }