バインドされた統計
説明
統計バインド(7.7の新機能)は、オブジェクトで統計を追跡するための標準の方法です。これらの統計は、バインドされた統計、または単に統計と呼ばれます。
オブジェクトに統計を追加する
SimpleDataTypeを継承する任意のオブジェクトに統計を追加できます。これにはすべてのFlexSimObjects、FixedResources、TaskExecutorsが含まれます。統計を追加するには、次の手順に従います。
- オブジェクトの定義に
TreeNode*
メンバーを追加します。class MyObject : public FlexSimObject { public: TreeNode* someStat = nullptr; void bindStatistics() override; ...
bindStatistics()
メソッドをオーバーライドします。
flags引数はビットマスクで、タイプと、統計が時間加重かどうかを指定します。統計には3つのタイプがあります。void MyObject::bindStatistics() { FlexSimObject::bindStatistics(); // bind the parent class statistics bindStatistic(someStat, flags); ...
STAT_TYPE_LEVEL
- デフォルトのタイプ。統計が増減し、現在の値はキュー内のコンテンツなど、何かの値のレベルを反映していることを意味します。STAT_TYPE_INCREMENTAL
- この種類の統計は、入力や出力など、常に増加するものです。STAT_TYPE_STREAM
- この種類の統計は、フローアイテムのプロセッサでの滞在時間など、値のセットを表します。
STAT_TIME_WEIGHTED
フラグとビット単位でorすることもできますが、これは通常はSTAT_TYPE_LEVEL
統計でのみ行われます。- 統計を更新するには、3つのマクロのいずれかを使用します。
UPDATE_SDT_STAT(statNode, newValue)
- 統計を新しい値に設定します。UPDATE_SDT_STAT_DELTA(statNode, delta)
- 統計を古い値に設定し、デルタを加算します。UPDATE_SDT_STAT_INCREMENTAL(statNode)
- 統計を1だけ増やします。
void MyObject::doStuff() { // ... object logic UPDATE_SDT_STAT(someStat, value);
- オブジェクトがリセットされるとき、オブジェクトのすべての統計をアクティブにし、リセットします。
この手法は、特に親クラスのメソッドで適切に動作し、呼び出し元の子クラスの統計をすべてリセットします。ストリーム以外の統計は0に設定されることに注意してください。これは、レベルおよび増加統計の初期値は0であるためです。リセット時ロジックでオブジェクトにアイテムが追加される場合、アイテムの追加時にリセットロジックとは別に、これらの統計を更新する必要があります。ストリーム統計(滞在時間など)の場合、その値についてデータが収集されていないため、通常は初期値がありません。enumerateStatistics(destNode, true); StatisticBinding& binding = *(destNode->objectAs(StatisticBinding)); for (StatisticBindingEntry& entry : binding) { binding.select(entry.statName.getBuffer()); TrackedVariable* tv = sdt->assertStatistic(&binding)->objectAs(TrackedVariable); tv->reset(); if ((entry.flags & STAT_TYPE_MASK) != STAT_TYPE_STREAM) tv->set(0); }
各統計はTrackedVariableオブジェクトにより表されます。assertStatistic()
関数を使用すると、TrackedVariableを持つツリーノードが返されます。それによって、各統計の現在、平均、最大、最小の値を取得できます。ただし、増加統計については平均、最大、最小の値は意味を持ちません。
統計の列挙
オブジェクトで利用可能な統計を照会できます。前のセクションのステップ4が、その例です。この場合、オブジェクト自身の統計がすべて列挙されます。ただし、enumerateStatistics()
メソッドも統計データをツリーノードのテーブルとして返すことができます。この動作を行うには、2番目のパラメータをfalse
に設定します。
各統計には名前とフラグが存在します。フラグはビットマスクで、統計のタイプと、その統計が中継されるかどうかの情報が含まれています。
for (StatisticBindingEntry& statBindingEntry : listStatBinding) { if (statBindingEntry.flags & STAT_RELAYED) { /* check if a statistic is relayed */ } int numRequirements = sdt->getNumStatRequirementsFromFlags(statBindingEntry.flags); // numRequirements will be 0, 1, 2, or 3 int statType = (statBindingEntry.flags & STAT_TYPE_MASK) // statType will be equal to // 0 or STAT_TYPE_LEVEL (both are equivalent) // STAT_TYPE_INCREMENTAL // STAT_TYPE_STREAM
中継された統計
オブジェクトが管理するサブオブジェクトに、独自の統計が含まれることがあります。統計の中継により、サブオブジェクトの統計を、それを所有するオブジェクトで利用できます。たとえば、ListがPartitionsを管理し、Partitionsに統計が存在すると考えます。ListがPartitionsの統計を中継するため、これらの統計にListオブジェクトからアクセスできます。
オブジェクトが統計をサブオブジェクトに中継する場合、bindRelayedClassStatistics<>()
関数(bindStatistics()
メソッド内)を使用する必要があります。
たとえば、PartitionクラスのbindStatistics()
メソッドを次に示します。
void List::Partition::bindStatistics() { SimpleDataType::bindStatistics(); bindStatistic(content, STAT_TIME_WEIGHTED); bindStatistic(input, STAT_TYPE_INCREMENTAL); bindStatistic(output, STAT_TYPE_INCREMENTAL); bindStatistic(staytime, STAT_TYPE_STREAM); bindStatistic(backOrderContent, STAT_TIME_WEIGHTED); bindStatistic(backOrderInput, STAT_TYPE_INCREMENTAL); bindStatistic(backOrderOutput, STAT_TYPE_INCREMENTAL); bindStatistic(backOrderStaytime, STAT_TYPE_STREAM); }
ListはPartitionsを管理するので、これらの統計も中継します。
void List::bindStatistics() { ObjectDataType::bindStatistics(); bindStatistic(input, STAT_TYPE_INCREMENTAL); bindStatistic(output, STAT_TYPE_INCREMENTAL); bindStatistic(content, STAT_TIME_WEIGHTED); bindStatistic(staytime, STAT_TYPE_STREAM); bindStatistic(backOrderInput, STAT_TYPE_INCREMENTAL); bindStatistic(backOrderOutput, STAT_TYPE_INCREMENTAL); bindStatistic(backOrderContent, STAT_TIME_WEIGHTED); bindStatistic(backOrderStaytime, STAT_TYPE_STREAM); bindRelayedClassStatistics<Partition>("Partition", STAT_1_REQUIREMENT, &List::partitionResolver, &List::getPartitionPossibilities); }
bindRelayedClassStatistics<>()
関数はテンプレート関数です。テンプレートのパラメータは、統計の中継元となるクラスです。前の例では、Partitionクラスがテンプレートのパラメータになります。
bindRelayedClassStatistics<>()
関数には4つの引数があります。
- プレフィックス - 統計名に付加される文字列。Listの統計を列挙するとき、Partitionのすべての統計が含まれますが、統計の名前にプレフィックスとして「Partition」が付けられ、「PartitionContent」のような名前になります。
- 要件の数。統計が中継されるため、これは統計の取得の要件が1、2、3個のどれかに応じてSTAT_1_REQUIREMENT、STAT_2_REQUIREMENTS、STAT_3_REQUIREMENTSのいずれかにする必要があります。
- 要件リゾルバ。これは、次の形式の関数です。
使用される関数は、要件の数が1、2、3個のどれかによって異なります。いずれの場合も、関数は与えられた要件をマップし、目的のオブジェクトを持つツリーノードを返します。たとえば、List::partitionResolverはパーティションIDを取得し、そのパーティションを含むツリーノードを返します。TreeNode* resolver1(const Variant& p1) TreeNode* resolver2(const Variant& p1, const Variant& p2) TreeNode* resolver3(const Variant& p1, const Variant& p2, const Variant& p3)
- 可能性列挙子。これは、次の形式の関数です。
この関数は与えられた要件を使用して、最後の要件として使用可能なノードをすべて列挙します。p1がnullバリアントなら、この関数はリゾルバのp1の可能な値のそれぞれについて、サブノードを追加します。p1がnullではなく、p2がnullなら、この関数はリゾルバのp2の可能な値のそれぞれについて、サブノードを追加します。それぞれの可能性について、要件の可能な値をポイントするdestNodeにサブノードを追加します。int enumerator(TreeNode* destNode, const Variant& p1, const Variant& p2) {}
また、この関数はdestNodeの名前を、要件の名前に設定します。
最後に、この関数は3つの値のいずれかを返します。- STAT_ENUM_REQS_INVALID - この値は、可能性が与えられないことを示します。
- STAT_ENUM_REQS_STATIC - この値は、列挙された可能性がモデルの実行中に変化しないことを示します。
- STAT_ENUM_REQS_DYNAMIC - この値は、可能性が動的であるため列挙されないことを示します。