You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by qi...@apache.org on 2019/07/10 08:03:43 UTC
[incubator-iotdb] branch master updated: [ IOTDB-116]Performance
statistics module (#195)
This is an automated email from the ASF dual-hosted git repository.
qiaojialin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 2f5e7ff [ IOTDB-116]Performance statistics module (#195)
2f5e7ff is described below
commit 2f5e7ffe34a19bbdf79b29ce75ab16bff3bfee85
Author: suyue <23...@qq.com>
AuthorDate: Wed Jul 10 16:03:38 2019 +0800
[ IOTDB-116]Performance statistics module (#195)
* add time cost statstic
---
.../4-Performance Monitor.md | 78 ++++
.../{4-System log.md => 5-System log.md} | 0
.../{5-Data Management.md => 6-Data Management.md} | 0
...e.md => 7-Build and use IoTDB by Dockerfile.md} | 0
.../4-Performance Monitor.md | 79 ++++
.../{4-System log.md => 5-System log.md} | 0
.../{5-Data Management.md => 6-Data Management.md} | 0
...e.md => 7-Build and use IoTDB by Dockerfile.md} | 0
iotdb/iotdb/conf/iotdb-engine.properties | 12 +
iotdb/iotdb/conf/logback.xml | 20 +
.../org/apache/iotdb/db/concurrent/ThreadName.java | 3 +-
.../java/org/apache/iotdb/db/conf/IoTDBConfig.java | 38 ++
.../org/apache/iotdb/db/conf/IoTDBDescriptor.java | 10 +
.../db/cost/statistic/ConcurrentCircularArray.java | 69 ++++
.../iotdb/db/cost/statistic/Measurement.java | 428 +++++++++++++++++++++
.../iotdb/db/cost/statistic/MeasurementMBean.java | 62 +++
.../apache/iotdb/db/cost/statistic/Operation.java | 36 ++
.../org/apache/iotdb/db/qp/QueryProcessor.java | 3 +-
.../java/org/apache/iotdb/db/service/IoTDB.java | 2 +
.../org/apache/iotdb/db/service/ServiceType.java | 1 +
.../org/apache/iotdb/db/service/TSServiceImpl.java | 25 +-
.../db/cost/statistic/PerformanceStatTest.java | 71 ++++
.../java/org/apache/iotdb/jdbc/IoTDBStatement.java | 1 -
23 files changed, 928 insertions(+), 10 deletions(-)
diff --git a/docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/4-Performance Monitor.md b/docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/4-Performance Monitor.md
new file mode 100644
index 0000000..880564c
--- /dev/null
+++ b/docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/4-Performance Monitor.md
@@ -0,0 +1,78 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+# 第4章 系统部署与管理
+## 性能监控
+### 引言
+
+性能监控模块用来监控IOTDB每一个操作的耗时,以便用户更好的了解数据库的整体性能。此模块会统计每一种操作的平均耗时,以及耗时在一定时间区间内(1ms,4ms,16ms,64ms,256ms,1024ms,以上)的操作的比例。输出文件在log_measure.log中。输出样例如下:
+
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto; margin-right:auto; display:block;" src="https://user-images.githubusercontent.com/13203019/60937461-14296f80-a303-11e9-9602-a7bed624bfb3.png">
+
+### 配置参数
+
+配置文件位置:conf/iotdb-engine.properties
+
+<center>**表 -配置参数以及描述项**
+
+|参数|默认值|描述|
+|:---|:---|:---|
+|enable\_performance\_stat|false|是否开启性能监控模块|
+|performance\_stat\_display\_interval|60000|打印统计结果的时间延迟,以毫秒为单位|
+|performance_stat_memory_in_kb|20|性能监控模块使用的内存阈值,单位为KB|
+</center>
+
+### 利用JMX MBean动态调节参数
+
+通过端口31999连接jconsole,并在上方菜单项中选择‘MBean’. 展开侧边框并选择 'org.apache.iotdb.db.cost.statistic'. 将会得到如下图所示结果:
+
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto; margin-right:auto; display:block;" src="https://user-images.githubusercontent.com/13203019/60937484-30c5a780-a303-11e9-8e92-04c413df2088.png">
+
+**属性**
+
+1. EnableStat:是否开启性能监控模块,如果被设置为true,则性能监控模块会记录每个操作的耗时并打印结果。这个参数不能直接通过jconsole直接更改,但可通过下方的函数来进行动态设置。
+2. DisplayIntervalInMs:相邻两次打印结果的时间间隔。这个参数可以直接设置,但它要等性能监控模块重启才会生效。重启性能监控模块可以通过先调用 stopStatistic()然后调用startContinuousStatistics()或者直接调用 startOneTimeStatistics()实现。
+3. OperationSwitch:这个属性用来展示针对每一种操作是否开启了监控统计,map的键为操作的名字,值为是否针对这种操作开启性能监控。这个参数不能直接通过jconsole直接更改,但可通过下方的 'changeOperationSwitch()'函数来进行动态设置。
+
+**操作**
+
+1. startContinuousStatistics:开启性能监控并以‘DisplayIntervalInMs’的时间间隔打印统计结果。
+2. startOneTimeStatistics:开启性能监控并以‘DisplayIntervalInMs’的时间延迟打印一次统计结果。
+3. stopStatistic:关闭性能监控。
+4. clearStatisticalState(): 清除以统计的结果,从新开始统计。
+5. changeOperationSwitch(String operationName, Boolean operationState):设置是否针对每一种不同的操作开启监控。参数‘operationName是操作的名称,在OperationSwitch属性中展示了所有操作的名称。参数 ‘operationState’是操作的状态,打开或者关闭。如果状态设置成功则此函数会返回true,否则返回false。
+
+### 自定义操作类型监控其他区域
+
+**增加操作项**
+
+在org.apache.iotdb.db.cost.statistic.Operation类中增加一个枚举项来表示新增的操作.
+
+**在监控区域增加监控代码**
+
+在监控开始区域增加计时代码:
+
+ long t0 = System. currentTimeMillis();
+
+
+在监控结束区域增加记录代码:
+
+ Measurement.INSTANCE.addOperationLatency(Operation, t0);
diff --git a/docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/4-System log.md b/docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/5-System log.md
similarity index 100%
rename from docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/4-System log.md
rename to docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/5-System log.md
diff --git a/docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/5-Data Management.md b/docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/6-Data Management.md
similarity index 100%
rename from docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/5-Data Management.md
rename to docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/6-Data Management.md
diff --git a/docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/6-Build and use IoTDB by Dockerfile.md b/docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/7-Build and use IoTDB by Dockerfile.md
similarity index 100%
rename from docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/6-Build and use IoTDB by Dockerfile.md
rename to docs/Documentation-CHN/UserGuideV0.7.0/4-Deployment and Management/7-Build and use IoTDB by Dockerfile.md
diff --git a/docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/4-Performance Monitor.md b/docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/4-Performance Monitor.md
new file mode 100644
index 0000000..7128f05
--- /dev/null
+++ b/docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/4-Performance Monitor.md
@@ -0,0 +1,79 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+# Chapter 4: Deployment and Management
+## Performance Monitor
+### Introduction
+
+In order to grasp the performance of iotdb, we add this module to count the time-consuming of each operation. This module can statistic the avg time-consuming of each operation and the proportion of each operation fall into a time range. The output is in log_measure.log file. A output example is in below.
+
+<img style="width:100%; max-width:800px; max-height:600px; margin-left:auto; margin-right:auto; display:block;" src="https://user-images.githubusercontent.com/13203019/60937461-14296f80-a303-11e9-9602-a7bed624bfb3.png">
+
+### Configuration parameter
+
+location:conf/iotdb-engine.properties
+
+<center>**Table -parameter and description**
+
+|Parameter|Default Value|Description|
+|:---|:---|:---|
+|enable\_performance\_stat|false|Is stat performance of sub-module enable.|
+|performance\_stat\_display\_interval|60000|The interval of display statistic result in ms.|
+|performance_stat_memory_in_kb|20|The memory used for performance_stat in kb.|
+</center>
+
+### JMX MBean
+
+Connect to jconsole with port 31999,and choose ‘MBean’in menu bar. Expand the sidebar and choose 'org.apache.iotdb.db.cost.statistic'. You can Find:
+
+<img style="width:100%; max-width:600px; max-height:200px; margin-left:auto; margin-right:auto; display:block;" src="https://user-images.githubusercontent.com/13203019/60937484-30c5a780-a303-11e9-8e92-04c413df2088.png">
+
+**Attribute**
+
+1. EnableStat:Whether the statistics are enable or not, if it is true, the module records the time-consuming of each operation and prints the results; It can not be set dynamically but changed by function in below.
+
+2. DisplayIntervalInMs:The interval between print results. It can be set dynamically, but will take effect after restart.( First call stopStatistic(), then call startContinuousStatistics() or startOneTimeStatistics())
+3. OperationSwitch:It's a map to indicate whether stat the operation, the key is operation name and the value is stat state. This parameter cannot be changed directly, it's change by operation 'changeOperationSwitch()'.
+
+**Operation**
+
+1. startContinuousStatistics: Start the statistics and output at interval of ‘DisplayIntervalInMs’.
+2. startOneTimeStatistics:Start the statistics and output in delay of ‘DisplayIntervalInMs’.
+3. stopStatistic:Stop the statistics.
+4. clearStatisticalState(): clear current stat result, reset statistical result.
+5. changeOperationSwitch(String operationName, Boolean operationState):set whether to monitor operation status. The param 'operationName' is the name of operation, defined in attribute operationSwitch. The param operationState is the state of operation. If state-switch successful the function will return true, else return false.
+
+### Adding Custom Monitoring Items for developer of IOTDB
+
+**Add Operation**
+
+Add an enumeration in org.apache.iotdb.db.cost.statistic.Operation.
+
+**Add Timing Code in Monitoring Area**
+
+Add timing code in the monitoring start area:
+
+ long t0 = System. currentTimeMillis();
+
+
+Add timing code in the monitoring stop area:
+
+ Measurement.INSTANCE.addOperationLatency(Operation, t0);
diff --git a/docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/4-System log.md b/docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/5-System log.md
similarity index 100%
rename from docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/4-System log.md
rename to docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/5-System log.md
diff --git a/docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/5-Data Management.md b/docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/6-Data Management.md
similarity index 100%
rename from docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/5-Data Management.md
rename to docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/6-Data Management.md
diff --git a/docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/6-Build and use IoTDB by Dockerfile.md b/docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/7-Build and use IoTDB by Dockerfile.md
similarity index 100%
rename from docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/6-Build and use IoTDB by Dockerfile.md
rename to docs/Documentation/UserGuideV0.7.0/4-Deployment and Management/7-Build and use IoTDB by Dockerfile.md
diff --git a/iotdb/iotdb/conf/iotdb-engine.properties b/iotdb/iotdb/conf/iotdb-engine.properties
index 0466025..aa7ef8e 100644
--- a/iotdb/iotdb/conf/iotdb-engine.properties
+++ b/iotdb/iotdb/conf/iotdb-engine.properties
@@ -181,3 +181,15 @@ ip_white_list=0.0.0.0/0
# 2. If the sync data accounts for less than 50% of the update of the historical data (compared with the latest timestamp of the local storage group data),then it is recommended to select strategy 2.
# Setting the parameter to false, which has little impact on the insert performance of IoTDB system and takes up a large amount of CPU power.
update_historical_data_possibility=false
+
+
+####################
+### performance statistic configuration
+####################
+
+# Is stat performance of sub-module enable
+enable_performance_stat=false
+# The interval of display statistic result in ms.
+performance_stat_display_interval=60000
+# The memory used for performance_stat in kb.
+performance_stat_memory_in_kb=20
diff --git a/iotdb/iotdb/conf/logback.xml b/iotdb/iotdb/conf/logback.xml
index 2629723..ff7c459 100644
--- a/iotdb/iotdb/conf/logback.xml
+++ b/iotdb/iotdb/conf/logback.xml
@@ -129,6 +129,23 @@
<level>INFO</level>
</filter>
</appender>
+ <appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILE_COST_MEASURE">
+ <file>${IOTDB_HOME}/logs/log_measure.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${IOTDB_HOME}/logs/log-measure-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>200MB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ </rollingPolicy>
+ <append>true</append>
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <pattern>%d [%t] %-5p %C:%L - %m %n</pattern>
+ <charset>utf-8</charset>
+ </encoder>
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>INFO</level>
+ </filter>
+ </appender>
<root level="info">
<appender-ref ref="FILEDEBUG"/>
<appender-ref ref="FILEWARN"/>
@@ -136,4 +153,7 @@
<appender-ref ref="FILEALL"/>
<appender-ref ref="stdout"/>
</root>
+ <logger level="info" name="org.apache.iotdb.db.cost.statistic">
+ <appender-ref ref="FILE_COST_MEASURE"/>
+ </logger>
</configuration>
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/concurrent/ThreadName.java b/iotdb/src/main/java/org/apache/iotdb/db/concurrent/ThreadName.java
index 132df0d..64b89d1 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/concurrent/ThreadName.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/concurrent/ThreadName.java
@@ -38,7 +38,8 @@ public enum ThreadName {
INDEX_SERVICE("Index-ServerServiceImpl"),
SYNC_CLIENT("Sync-Client"),
SYNC_SERVER("Sync-Server"),
- SYNC_MONITOR("Sync-Monitor");
+ SYNC_MONITOR("Sync-Monitor"),
+ TIME_COST_STATSTIC("TIME_COST_STATSTIC");
private String name;
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java b/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
index e7543b0..fa402d3 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
@@ -176,6 +176,20 @@ public class IoTDBConfig {
private String rpcImplClassName = TSServiceImpl.class.getName();
/**
+ * Is stat performance of sub-module enable.
+ */
+ private boolean enablePerformanceStat = false;
+
+ /**
+ * The display of stat performance interval in ms.
+ */
+ private long performanceStatDisplayInterval = 60000;
+
+ /**
+ * The memory used for stat performance.
+ */
+ private int performance_stat_memory_in_kb = 20;
+ /**
* whether use chunkBufferPool.
*/
private boolean chunkBufferPoolEnable = false;
@@ -487,4 +501,28 @@ public class IoTDBConfig {
void setChunkBufferPoolEnable(boolean chunkBufferPoolEnable) {
this.chunkBufferPoolEnable = chunkBufferPoolEnable;
}
+
+ public boolean isEnablePerformanceStat() {
+ return enablePerformanceStat;
+ }
+
+ public void setEnablePerformanceStat(boolean enablePerformanceStat) {
+ this.enablePerformanceStat = enablePerformanceStat;
+ }
+
+ public long getPerformanceStatDisplayInterval() {
+ return performanceStatDisplayInterval;
+ }
+
+ public void setPerformanceStatDisplayInterval(long performanceStatDisplayInterval) {
+ this.performanceStatDisplayInterval = performanceStatDisplayInterval;
+ }
+
+ public int getPerformance_stat_memory_in_kb() {
+ return performance_stat_memory_in_kb;
+ }
+
+ public void setPerformance_stat_memory_in_kb(int performance_stat_memory_in_kb) {
+ this.performance_stat_memory_in_kb = performance_stat_memory_in_kb;
+ }
}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java b/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
index 57e941e..4f7e208 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
@@ -200,6 +200,16 @@ public class IoTDBDescriptor {
conf.setZoneID(ZoneId.of(tmpTimeZone.trim()));
logger.info("Time zone has been set to {}", conf.getZoneID());
+ conf.setEnablePerformanceStat(Boolean
+ .parseBoolean(properties.getProperty("enable_performance_stat",
+ Boolean.toString(conf.isEnablePerformanceStat())).trim()));
+
+ conf.setPerformanceStatDisplayInterval(Long
+ .parseLong(properties.getProperty("performance_stat_display_interval",
+ Long.toString(conf.getPerformanceStatDisplayInterval())).trim()));
+ conf.setPerformance_stat_memory_in_kb(Integer
+ .parseInt(properties.getProperty("performance_stat_memory_in_kb",
+ Integer.toString(conf.getPerformance_stat_memory_in_kb())).trim()));
} catch (IOException e) {
logger.warn("Cannot load config file because, use default configuration", e);
} catch (Exception e) {
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/ConcurrentCircularArray.java b/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/ConcurrentCircularArray.java
new file mode 100644
index 0000000..535916c
--- /dev/null
+++ b/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/ConcurrentCircularArray.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.cost.statistic;
+
+public class ConcurrentCircularArray {
+
+ long[] data;
+ int tail;
+ int head;
+
+ public ConcurrentCircularArray(int size) {
+ this.data = new long[size];
+ tail = head = 0;
+ }
+
+ /**
+ * @param d the data
+ * @return true if successfully; false if there is no space.
+ */
+ public synchronized boolean put(long d) {
+ if ((tail + 1) % data.length == head) {
+ return false;
+ }
+ data[tail++] = d;
+ tail = tail % data.length;
+ return true;
+ }
+
+ public synchronized boolean hasData() {
+ return tail != head;
+ }
+
+ /**
+ * @return -1 if there is no data.(However, you should call hasData() frist to avoid returning -1)
+ */
+ public synchronized long take() {
+ if (tail != head) {
+ long result = data[head++];
+ head = head % data.length;
+ return result;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * drop all of the elements in array.
+ */
+ public synchronized void clear(){
+ tail = head = 0;
+ }
+}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/Measurement.java b/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/Measurement.java
new file mode 100644
index 0000000..83c2cdf
--- /dev/null
+++ b/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/Measurement.java
@@ -0,0 +1,428 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.cost.statistic;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+import org.apache.iotdb.db.concurrent.IoTDBThreadPoolFactory;
+import org.apache.iotdb.db.concurrent.ThreadName;
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBConstant;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.exception.StartupException;
+import org.apache.iotdb.db.service.IService;
+import org.apache.iotdb.db.service.JMXService;
+import org.apache.iotdb.db.service.ServiceType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <p>
+ * Measurement is used to record execution time of operations defined in enum class Operation. It
+ * can display average time of each operation, and proportion of operation whose execution time fall
+ * into time range defined in BUCKET_IN_MS. If you want to change abscissa of histogram, just change
+ * the BUCKET_IN_MS array. For recording a operation, you should:
+ * 1) add a item in enum class Operation.
+ * 2) call <code>startTimeInNano = System.nanoTime()</code> to recode startTime of that operation.
+ * 3) call <code>Measurement.INSTANCE.addOperationLatency(operation, startTimeInNano)</code>
+ * at the end of that operation;
+ *
+ * @see Operation
+ */
+public class Measurement implements MeasurementMBean, IService {
+
+ /**
+ * queue for async store time latencies.
+ */
+ private ConcurrentCircularArray[] operationLatenciesQueue;
+
+ /**
+ * size of each queue, this is calculated by memory.
+ */
+ private final int queueSize;
+
+ /**
+ * latencies sum of each operation.
+ */
+ private long[] operationLatencies;
+
+ /**
+ * the num of each operation.
+ */
+ private long[] operationCnt;
+
+ /**
+ * abscissa of histogram.
+ */
+ private static final int[] BUCKET_IN_MS = {1, 4, 16, 64, 256, 1024, Integer.MAX_VALUE};
+
+ /**
+ * length of BUCKET_IN_MS.
+ */
+ private static final int BUCKET_SIZE = BUCKET_IN_MS.length;
+
+ /**
+ * the num of operation that execution time falls into time range of BUCKET_IN_MS. The outer array
+ * is each operation, the inner array is each time range in BUCKET_IN_MS.
+ */
+ private long[][] operationHistogram;
+
+ /**
+ * display thread and queue consumer thread.
+ */
+ private ScheduledExecutorService service;
+
+ /**
+ * future task of display thread and queue consumer thread.
+ */
+ private List<Future<?>> futureList;
+
+ /**
+ * lock for change state: start() and stopStatistic().
+ */
+ private ReentrantLock stateChangeLock = new ReentrantLock();
+
+ public static final Measurement INSTANCE = AsyncMeasurementHolder.MEASUREMENT;
+
+ private boolean isEnableStat;
+ private long displayIntervalInMs;
+ private Map<String, Boolean> operationSwitch;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Measurement.class);
+ private final String mbeanName = String
+ .format("%s:%s=%s", "org.apache.iotdb.db.cost.statistic", IoTDBConstant.JMX_TYPE,
+ getID().getJmxName());
+
+ private Measurement() {
+ IoTDBConfig tdbConfig = IoTDBDescriptor.getInstance().getConfig();
+ isEnableStat = tdbConfig.isEnablePerformanceStat();
+ displayIntervalInMs = tdbConfig.getPerformanceStatDisplayInterval();
+ int memoryInKb = tdbConfig.getPerformance_stat_memory_in_kb();
+
+ queueSize = memoryInKb * 1000 / Operation.values().length / 8;
+ operationLatenciesQueue = new ConcurrentCircularArray[Operation.values().length];
+ operationLatencies = new long[Operation.values().length];
+ operationCnt = new long[Operation.values().length];
+ operationSwitch = new HashMap<>(Operation.values().length);
+ for (Operation op : Operation.values()) {
+ operationLatenciesQueue[op.ordinal()] = new ConcurrentCircularArray(queueSize);
+ operationCnt[op.ordinal()] = 0;
+ operationLatencies[op.ordinal()] = 0;
+ operationSwitch.put(op.getName(), true);
+ }
+ operationHistogram = new long[Operation.values().length][BUCKET_SIZE];
+ for (Operation operation : Operation.values()) {
+ for (int i = 0; i < BUCKET_SIZE; i++) {
+ operationHistogram[operation.ordinal()][i] = 0;
+ }
+ }
+
+ service = IoTDBThreadPoolFactory.newScheduledThreadPool(
+ 2, ThreadName.TIME_COST_STATSTIC.getName());
+ futureList = new ArrayList<>();
+ }
+
+ public boolean addOperationLatency(Operation op, long startTime) {
+ if (isEnableStat && operationSwitch.get(op.getName())) {
+ return operationLatenciesQueue[op.ordinal()].put((System.currentTimeMillis() - startTime));
+ }
+ return false;
+ }
+
+ @Override
+ public void startContinuousStatistics() {
+ stateChangeLock.lock();
+ try {
+ if (isEnableStat) {
+ return;
+ }
+ isEnableStat = true;
+ futureList.clear();
+ Future future = service.scheduleWithFixedDelay(
+ new Measurement.DisplayRunnable(), 20, displayIntervalInMs, TimeUnit.MILLISECONDS);
+ futureList.add(future);
+ futureList.add(service.schedule(new QueueConsumerThread(), 0, TimeUnit.MILLISECONDS));
+
+
+ } catch (Exception e) {
+ LOGGER.error("Find error when start performance statistic thread, because {}", e);
+ } finally {
+ stateChangeLock.unlock();
+ }
+ }
+
+ @Override
+ public void startOneTimeStatistics() {
+ stateChangeLock.lock();
+ try {
+ if (isEnableStat) {
+ return;
+ }
+ isEnableStat = true;
+ futureList.clear();
+ futureList.add(service.schedule(new QueueConsumerThread(), 10, TimeUnit.MILLISECONDS));
+ Future future = service.schedule(() -> {
+ showMeasurements();
+ stopStatistic();
+ }, displayIntervalInMs, TimeUnit.MILLISECONDS);
+ futureList.add(future);
+ } catch (Exception e) {
+ LOGGER.error("Find error when start performance statistic thread, because {}", e);
+ } finally {
+ stateChangeLock.unlock();
+ }
+ }
+
+ @Override
+ public void stopStatistic() {
+ stateChangeLock.lock();
+ try {
+ if (!isEnableStat) {
+ return;
+ }
+ isEnableStat = false;
+ for (Future future : futureList) {
+ if (future != null) {
+ future.cancel(true);
+
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error("Find error when stopStatistic time cost statstic thread, because {}", e);
+ } finally {
+ stateChangeLock.unlock();
+ }
+ }
+
+ @Override
+ public void clearStatisticalState() {
+ for (Operation op : Operation.values()) {
+ operationLatenciesQueue[op.ordinal()].clear();
+ operationCnt[op.ordinal()] = 0;
+ operationLatencies[op.ordinal()] = 0;
+ for (int i = 0; i < BUCKET_SIZE; i++) {
+ operationHistogram[op.ordinal()][i] = 0;
+ }
+ }
+ }
+
+ @Override
+ public boolean changeOperationSwitch(String operationName, Boolean operationState) {
+ if (operationSwitch.containsKey(operationName)) {
+ operationSwitch.put(operationName, operationState);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * start service.
+ */
+ @Override
+ public void start() throws StartupException {
+ // start display thread and consumer threads.
+ if (isEnableStat) {
+ Future future = service.scheduleWithFixedDelay(
+ new Measurement.DisplayRunnable(), 20, displayIntervalInMs, TimeUnit.MILLISECONDS);
+ futureList.add(future);
+ futureList.add(service.schedule(new QueueConsumerThread(), 10, TimeUnit.MILLISECONDS));
+
+ }
+ try {
+ JMXService.registerMBean(INSTANCE, mbeanName);
+ } catch (Exception e) {
+ String errorMessage = String
+ .format("Failed to start %s because of %s", this.getID().getName(),
+ e.getMessage());
+ throw new StartupException(errorMessage, e);
+ }
+ }
+
+ /**
+ * stop service.
+ */
+ @Override
+ public void stop() {
+ JMXService.deregisterMBean(mbeanName);
+ if (service == null || service.isShutdown()) {
+ return;
+ }
+ stopStatistic();
+ futureList.clear();
+ service.shutdownNow();
+ try {
+ service.awaitTermination(5, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ LOGGER.error("Performance statistic service could not be shutdown, {}", e.getMessage());
+ // Restore interrupted state...
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ @Override
+ public ServiceType getID() {
+ return ServiceType.PERFORMANCE_STATISTIC_SERVICE;
+ }
+
+ @Override
+ public boolean isEnableStat() {
+ return isEnableStat;
+ }
+
+ @Override
+ public long getDisplayIntervalInMs() {
+ return displayIntervalInMs;
+ }
+
+ @Override
+ public void setDisplayIntervalInMs(long displayIntervalInMs) {
+ this.displayIntervalInMs = displayIntervalInMs;
+ }
+
+ @Override
+ public Map<String, Boolean> getOperationSwitch() {
+ return operationSwitch;
+ }
+
+ private static class AsyncMeasurementHolder {
+
+ private static final Measurement MEASUREMENT = new Measurement();
+
+ private AsyncMeasurementHolder() {
+ }
+ }
+
+ private void showMeasurements() {
+ Date date = new Date();
+ LOGGER.info(
+ "====================================={} Measurement (ms)======================================",
+ date);
+ String head = String
+ .format("%-45s%-25s%-25s%-25s", "OPERATION", "COUNT", "TOTAL_TIME", "AVG_TIME");
+ LOGGER.info(head);
+ for (Operation operation : Operation.values()) {
+ if (!operationSwitch.get(operation.getName())) {
+ continue;
+ }
+ long cnt = operationCnt[operation.ordinal()];
+ long totalInMs = operationLatencies[operation.ordinal()];
+ String avg = String.format("%.4f", (totalInMs / (cnt + 1e-9)));
+ String item = String
+ .format("%-45s%-25s%-25s%-25s", operation.name, cnt + "", totalInMs + "", avg);
+ LOGGER.info(item);
+ }
+ LOGGER.info(
+ "==========================================OPERATION HISTOGRAM====================================================");
+ StringBuilder histogramHead = new StringBuilder(String.format("%-45s", "OPERATION"));
+ for (int i = 0; i < BUCKET_SIZE; i++) {
+ histogramHead.append(String.format("%-8s", BUCKET_IN_MS[i] + "ms"));
+ }
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(histogramHead.toString());
+ }
+ for (Operation operation : Operation.values()) {
+ if (!operationSwitch.get(operation.getName())) {
+ continue;
+ }
+ StringBuilder item = new StringBuilder(String.format("%-45s", operation.getName()));
+ long cnt = operationCnt[operation.ordinal()];
+ for (int i = 0; i < BUCKET_SIZE; i++) {
+ String avg = String
+ .format("%.2f", (operationHistogram[operation.ordinal()][i] / (cnt + 1e-9) * 100));
+ item.append(String.format("%-8s", avg + "%"));
+ }
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(item.toString());
+ }
+ }
+
+ LOGGER.info(
+ "=================================================================================================================");
+ }
+
+ class DisplayRunnable implements Runnable {
+
+ @Override
+ public void run() {
+ showMeasurements();
+ }
+ }
+
+ class QueueConsumerThread implements Runnable {
+
+ @Override
+ public void run() {
+ consumer();
+ }
+
+ private void consumer() {
+ boolean allEmpty;
+ while (isEnableStat) {
+ allEmpty = true;
+ for (Operation op : Operation.values()) {
+ if (!operationSwitch.get(op.getName())) {
+ continue;
+ }
+ int idx = op.ordinal();
+ ConcurrentCircularArray queue = operationLatenciesQueue[idx];
+ if (queue.hasData()) {
+ long time = queue.take();
+ operationLatencies[idx] += time;
+ operationCnt[idx]++;
+ operationHistogram[idx][calIndex(time)]++;
+ allEmpty = false;
+ }
+ }
+ if (allEmpty) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ break;
+ }
+ }
+ }
+ }
+
+ private int calIndex(long x) {
+ for (int i = 0; i < BUCKET_SIZE; i++) {
+ if (BUCKET_IN_MS[i] >= x) {
+ return i;
+ }
+ }
+ return BUCKET_SIZE - 1;
+ }
+ }
+
+ public long[] getOperationLatencies() {
+ return operationLatencies;
+ }
+
+ public long[] getOperationCnt() {
+ return operationCnt;
+ }
+}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/MeasurementMBean.java b/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/MeasurementMBean.java
new file mode 100644
index 0000000..224956f
--- /dev/null
+++ b/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/MeasurementMBean.java
@@ -0,0 +1,62 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.cost.statistic;
+
+import java.util.Map;
+
+public interface MeasurementMBean {
+
+ /**
+ * start display performance statistic every interval of displayIntervalInMs.
+ */
+ void startContinuousStatistics();
+
+ /**
+ * start display performance statistic after interval of displayIntervalInMs.
+ */
+ void startOneTimeStatistics();
+
+ /**
+ * stop display performance statistic.
+ */
+ void stopStatistic();
+
+ /**
+ * clear current stat result, reset statistical state.
+ */
+ void clearStatisticalState();
+
+ /**
+ * set whether to monitor operation status.
+ *
+ * @param operationName the name of operation, defined in attribute operationSwitch.
+ * @param operationState state of operation.
+ * @return true if successful, false if fail.
+ */
+ boolean changeOperationSwitch(String operationName, Boolean operationState);
+
+ boolean isEnableStat();
+
+ long getDisplayIntervalInMs();
+
+ void setDisplayIntervalInMs(long displayIntervalInMs);
+
+ Map<String, Boolean> getOperationSwitch();
+}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/Operation.java b/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/Operation.java
new file mode 100644
index 0000000..6f862ba
--- /dev/null
+++ b/iotdb/src/main/java/org/apache/iotdb/db/cost/statistic/Operation.java
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.cost.statistic;
+
+public enum Operation {
+ EXECUTE_BATCH("EXECUTE_BATCH"),
+ EXECUTE_ONE_SQL_IN_BATCH("EXECUTE_ONE_SQL_IN_BATCH"),
+ EXECUTE_QUERY("EXECUTE_QUERY");
+
+ public String getName() {
+ return name;
+ }
+
+ String name;
+
+ Operation(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/qp/QueryProcessor.java b/iotdb/src/main/java/org/apache/iotdb/db/qp/QueryProcessor.java
index 70ec551..4f2baee 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/qp/QueryProcessor.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/qp/QueryProcessor.java
@@ -73,7 +73,8 @@ public class QueryProcessor {
Operator operator = parseASTToOperator(astNode, zoneId);
operator = logicalOptimize(operator, executor);
PhysicalGenerator physicalGenerator = new PhysicalGenerator(executor);
- return physicalGenerator.transformToPhysicalPlan(operator);
+ PhysicalPlan qp = physicalGenerator.transformToPhysicalPlan(operator);
+ return qp;
}
/**
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/service/IoTDB.java b/iotdb/src/main/java/org/apache/iotdb/db/service/IoTDB.java
index ba80791..4139d8e 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/service/IoTDB.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/service/IoTDB.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.service;
import org.apache.iotdb.db.concurrent.IoTDBDefaultThreadExceptionHandler;
import org.apache.iotdb.db.conf.IoTDBConstant;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.cost.statistic.Measurement;
import org.apache.iotdb.db.engine.StorageEngine;
import org.apache.iotdb.db.exception.StartupException;
import org.apache.iotdb.db.exception.builder.ExceptionBuilder;
@@ -91,6 +92,7 @@ public class IoTDB implements IoTDBMBean {
registerManager.register(JDBCService.getInstance());
registerManager.register(Monitor.getInstance());
registerManager.register(StatMonitor.getInstance());
+ registerManager.register(Measurement.INSTANCE);
registerManager.register(SyncServerManager.getInstance());
registerManager.register(TVListAllocator.getInstance());
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/service/ServiceType.java b/iotdb/src/main/java/org/apache/iotdb/db/service/ServiceType.java
index 10302b6..4f872fd 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/service/ServiceType.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/service/ServiceType.java
@@ -31,6 +31,7 @@ public enum ServiceType {
AUTHORIZATION_SERVICE("Authorization ServerService", ""),
FILE_READER_MANAGER_SERVICE("File reader manager ServerService", ""),
SYNC_SERVICE("SYNC ServerService", ""),
+ PERFORMANCE_STATISTIC_SERVICE("PERFORMANCE_STATISTIC_SERVICE","PERFORMANCE_STATISTIC_SERVICE"),
TVLIST_ALLOCATOR_SERVICE("TVList Allocator", "");
private String name;
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java b/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
index 243b3a6..282f8be 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
@@ -42,6 +42,8 @@ import org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.apache.iotdb.db.conf.IoTDBConstant;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.cost.statistic.Measurement;
+import org.apache.iotdb.db.cost.statistic.Operation;
import org.apache.iotdb.db.engine.StorageEngine;
import org.apache.iotdb.db.exception.ArgsErrorException;
import org.apache.iotdb.db.exception.MetadataErrorException;
@@ -345,7 +347,7 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
case "privilege":
return TSDataType.TEXT;
default:
- // do nothing
+ // do nothing
}
if (path.contains("(") && !path.startsWith("(") && path.endsWith(")")) {
@@ -399,7 +401,7 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
StorageEngine.getInstance().syncCloseAllProcessor();
return true;
case "merge":
- // TODO change to merge!!!
+ // TODO change to merge!!!
throw new UnsupportedOperationException("merge not implemented");
default:
return false;
@@ -409,6 +411,7 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
@Override
public TSExecuteBatchStatementResp executeBatchStatement(TSExecuteBatchStatementReq req)
throws TException {
+ long t1 = System.currentTimeMillis();
String currStmt = null;
List<Integer> result = new ArrayList<>();
try {
@@ -422,14 +425,19 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
StringBuilder batchErrorMessage = new StringBuilder();
for (String statement : statements) {
+ long t2 = System.currentTimeMillis();
currStmt = statement;
- isAllSuccessful = isAllSuccessful && executeStatementInBatch(statement, batchErrorMessage, result);
+ isAllSuccessful =
+ isAllSuccessful && executeStatementInBatch(statement, batchErrorMessage, result);
+ Measurement.INSTANCE.addOperationLatency(Operation.EXECUTE_ONE_SQL_IN_BATCH, t2);
}
+
if (isAllSuccessful) {
return getTSBathExecuteStatementResp(TS_StatusCode.SUCCESS_STATUS,
"Execute batch statements successfully", result);
} else {
- return getTSBathExecuteStatementResp(TS_StatusCode.ERROR_STATUS, batchErrorMessage.toString(),
+ return getTSBathExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
+ batchErrorMessage.toString(),
result);
}
} catch (QueryInBatchStmtException e) {
@@ -438,6 +446,8 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
} catch (Exception e) {
logger.error("{}: error occurs when executing statements", IoTDBConstant.GLOBAL_DB_NAME, e);
return getTSBathExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage(), null);
+ } finally {
+ Measurement.INSTANCE.addOperationLatency(Operation.EXECUTE_BATCH, t1);
}
}
@@ -472,7 +482,6 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
}
-
@Override
public TSExecuteStatementResp executeStatement(TSExecuteStatementReq req) throws TException {
try {
@@ -526,7 +535,7 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
@Override
public TSExecuteStatementResp executeQueryStatement(TSExecuteStatementReq req) throws TException {
-
+ long t1 = System.currentTimeMillis();
try {
if (!checkLogin()) {
logger.info(INFO_NOT_LOGIN, IoTDBConstant.GLOBAL_DB_NAME);
@@ -557,6 +566,8 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
} catch (Exception e) {
logger.error("{}: Internal server error: ", IoTDBConstant.GLOBAL_DB_NAME, e);
return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ } finally {
+ Measurement.INSTANCE.addOperationLatency(Operation.EXECUTE_QUERY, t1);
}
}
@@ -727,7 +738,6 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
private TSExecuteStatementResp executeUpdateStatement(PhysicalPlan plan) {
List<Path> paths = plan.getPaths();
-
try {
if (!checkAuthorization(paths, plan)) {
return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
@@ -748,6 +758,7 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
logger.debug("meet error while processing non-query. ", e);
return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
}
+
TS_StatusCode statusCode = execRet ? TS_StatusCode.SUCCESS_STATUS : TS_StatusCode.ERROR_STATUS;
String msg = execRet ? "Execute successfully" : "Execute statement error.";
TSExecuteStatementResp resp = getTSExecuteStatementResp(statusCode, msg);
diff --git a/iotdb/src/test/java/org/apache/iotdb/db/cost/statistic/PerformanceStatTest.java b/iotdb/src/test/java/org/apache/iotdb/db/cost/statistic/PerformanceStatTest.java
new file mode 100644
index 0000000..6764ffc
--- /dev/null
+++ b/iotdb/src/test/java/org/apache/iotdb/db/cost/statistic/PerformanceStatTest.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.cost.statistic;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PerformanceStatTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PerformanceStatTest.class);
+
+ @Test
+ public void test() {
+ Measurement measurement = Measurement.INSTANCE;
+ Operation operation = Operation.EXECUTE_BATCH;
+ measurement.addOperationLatency(operation, System.currentTimeMillis());
+ measurement.addOperationLatency(operation,
+ System.currentTimeMillis() - 8000000);
+
+ long batchOpCnt = measurement.getOperationCnt()[operation.ordinal()];
+ Assert.assertEquals(0L, batchOpCnt);
+ try {
+ measurement.start();
+ measurement.startContinuousStatistics();
+ measurement.addOperationLatency(operation, System.currentTimeMillis());
+ measurement
+ .addOperationLatency(operation, System.currentTimeMillis() - 8000000);
+ Thread.currentThread().sleep(1000);
+ batchOpCnt = measurement.getOperationCnt()[operation.ordinal()];
+ Assert.assertEquals(2L, batchOpCnt);
+ measurement.stopStatistic();
+ measurement.stopStatistic();
+ measurement.stopStatistic();
+ LOGGER.info("After stopStatistic!");
+ Thread.currentThread().sleep(1000);
+ measurement.clearStatisticalState();
+ batchOpCnt = measurement.getOperationCnt()[operation.ordinal()];
+ Assert.assertEquals(0L, batchOpCnt);
+ measurement.startContinuousStatistics();
+ LOGGER.info("ReStart!");
+ Thread.currentThread().sleep(1000);
+ measurement.startContinuousStatistics();
+ LOGGER.info("ReStart2!");
+ Thread.currentThread().sleep(1000);
+ measurement.stopStatistic();
+ LOGGER.info("After stopStatistic2!");
+ } catch (Exception e) {
+ LOGGER.error("find error in stat performance, the message is {}", e.getMessage());
+ } finally {
+ measurement.stop();
+ }
+ }
+}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
index 66aa7f2..e9340ba 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
@@ -48,7 +48,6 @@ import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
public class IoTDBStatement implements Statement {
private static final String SHOW_TIMESERIES_COMMAND_LOWERCASE = "show timeseries";