[NO ISSUE] IOCounter improvements

- cache results for short period
- split iostat, proc fs impls

Change-Id: I7789171db6b6d7eea3561c24467af63f065f5dc6
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2515
Reviewed-by: Murtadha Hubail <mhub...@apache.org>
Tested-by: Murtadha Hubail <mhub...@apache.org>
Sonar-Qube: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/94b6da6a
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/94b6da6a
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/94b6da6a

Branch: refs/heads/release-0.9.4-pre-rc
Commit: 94b6da6ae33749dfdee35e35f32c165693015e3d
Parents: 2587f1d
Author: Michael Blow <mb...@apache.org>
Authored: Thu Mar 22 20:15:37 2018 -0400
Committer: Michael Blow <mb...@apache.org>
Committed: Thu Mar 22 22:11:31 2018 -0700

----------------------------------------------------------------------
 .../control/nc/io/profiling/IIOCounter.java     |   8 +-
 .../control/nc/io/profiling/IOCounterCache.java |  41 ++++++
 .../nc/io/profiling/IOCounterDefault.java       |   6 +-
 .../nc/io/profiling/IOCounterFactory.java       |   9 +-
 .../nc/io/profiling/IOCounterIoStat.java        | 101 +++++++++++++++
 .../control/nc/io/profiling/IOCounterLinux.java | 128 -------------------
 .../control/nc/io/profiling/IOCounterOSX.java   |   6 +-
 .../control/nc/io/profiling/IOCounterProc.java  |  71 ++++++++++
 8 files changed, 231 insertions(+), 139 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/94b6da6a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IIOCounter.java
----------------------------------------------------------------------
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IIOCounter.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IIOCounter.java
index 3612d8f..a85ca2c 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IIOCounter.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IIOCounter.java
@@ -22,12 +22,12 @@ package org.apache.hyracks.control.nc.io.profiling;
 public interface IIOCounter {
 
     /**
-     * @return the number of block reads from the very beginning
+     * @return the number of block reads from the very beginning, or -1 if not 
available on this platform
      */
-    public long getReads();
+    long getReads();
 
     /**
-     * @return the number of block writes from the very beginning
+     * @return the number of block writes from the very beginning, or -1 if 
not available on this platform
      */
-    public long getWrites();
+    long getWrites();
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/94b6da6a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterCache.java
----------------------------------------------------------------------
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterCache.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterCache.java
new file mode 100644
index 0000000..842d82b
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterCache.java
@@ -0,0 +1,41 @@
+/*
+ * 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.hyracks.control.nc.io.profiling;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hyracks.util.Span;
+
+abstract class IOCounterCache<T> implements IIOCounter {
+    private static final long TTL_NANOS = TimeUnit.MILLISECONDS.toNanos(500);
+    private Span span;
+    private T info;
+
+    protected synchronized T getInfo() throws IOException {
+        if (info == null || span.elapsed()) {
+            span = Span.start(TTL_NANOS, TimeUnit.NANOSECONDS);
+            info = calculateInfo();
+        }
+        return info;
+    }
+
+    protected abstract T calculateInfo() throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/94b6da6a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterDefault.java
----------------------------------------------------------------------
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterDefault.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterDefault.java
index 1f8669d..d5ec9a0 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterDefault.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterDefault.java
@@ -21,14 +21,16 @@ package org.apache.hyracks.control.nc.io.profiling;
 
 public class IOCounterDefault implements IIOCounter {
 
+    public static final long IO_COUNTER_UNAVAILABLE = -1;
+
     @Override
     public long getReads() {
-        return 0;
+        return IO_COUNTER_UNAVAILABLE;
     }
 
     @Override
     public long getWrites() {
-        return 0;
+        return IO_COUNTER_UNAVAILABLE;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/94b6da6a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterFactory.java
----------------------------------------------------------------------
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterFactory.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterFactory.java
index 2301ae6..36b310d 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterFactory.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterFactory.java
@@ -33,9 +33,12 @@ public class IOCounterFactory {
      */
     public IIOCounter getIOCounter() {
         String osName = System.getProperty("os.name").toLowerCase();
-        if (osName.indexOf("nix") >= 0 || osName.indexOf("nux") >= 0 || 
osName.indexOf("aix") >= 0) {
-            return new IOCounterLinux();
-        } else if (osName.indexOf("mac") >= 0) {
+        if (osName.contains("nix") || osName.contains("nux") || 
osName.contains("aix")) {
+            if (IOCounterProc.STATFILE.exists()) {
+                return new IOCounterProc();
+            }
+            return new IOCounterIoStat();
+        } else if (osName.contains("mac")) {
             return new IOCounterOSX();
         } else {
             return new IOCounterDefault();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/94b6da6a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterIoStat.java
----------------------------------------------------------------------
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterIoStat.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterIoStat.java
new file mode 100644
index 0000000..560035b
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterIoStat.java
@@ -0,0 +1,101 @@
+/*
+ * 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.hyracks.control.nc.io.profiling;
+
+import static 
org.apache.hyracks.control.nc.io.profiling.IOCounterDefault.IO_COUNTER_UNAVAILABLE;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class IOCounterIoStat extends IOCounterCache<List<String>> {
+    private static final Logger LOGGER = LogManager.getLogger();
+    private static final String COMMAND = "iostat";
+    private static final int PAGE_SIZE = 512;
+    private long failureCount;
+
+    private long baseReads;
+    private long baseWrites;
+
+    IOCounterIoStat() {
+        baseReads = getReads();
+        baseWrites = getWrites();
+    }
+
+    @Override
+    public long getReads() {
+        try {
+            long reads = extractColumn(4) * PAGE_SIZE;
+            return reads == 0 ? IO_COUNTER_UNAVAILABLE : reads - baseReads;
+        } catch (Exception e) {
+            LOGGER.log(failureCount++ > 0 ? Level.DEBUG : Level.WARN, "Failure 
getting reads", e);
+            return IO_COUNTER_UNAVAILABLE;
+        }
+    }
+
+    @Override
+    public long getWrites() {
+        try {
+            long writes = extractColumn(5) * PAGE_SIZE;
+            return writes == 0 ? IO_COUNTER_UNAVAILABLE : writes - baseWrites;
+        } catch (Exception e) {
+            LOGGER.log(failureCount++ > 0 ? Level.DEBUG : Level.WARN, "Failure 
getting writes", e);
+            return IO_COUNTER_UNAVAILABLE;
+        }
+    }
+
+    private long extractColumn(int columnIndex) throws IOException {
+        boolean device = false;
+        long ios = 0;
+        for (String line : getInfo()) {
+            if (line.contains("Blk_read")) {
+                device = true;
+                continue;
+            }
+            if (device) {
+                StringTokenizer tokenizer = new StringTokenizer(line);
+                int i = 0;
+                while (tokenizer.hasMoreTokens()) {
+                    String column = tokenizer.nextToken();
+                    if (i == columnIndex) {
+                        ios += Long.parseLong(column);
+                        break;
+                    }
+                    i++;
+                }
+            }
+        }
+        return ios;
+    }
+
+    @Override
+    protected List<String> calculateInfo() throws IOException {
+        try (InputStream inputStream = 
Runtime.getRuntime().exec(COMMAND).getInputStream()) {
+            return IOUtils.readLines(inputStream, Charset.defaultCharset());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/94b6da6a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterLinux.java
----------------------------------------------------------------------
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterLinux.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterLinux.java
deleted file mode 100644
index 3db4c8c..0000000
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterLinux.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.hyracks.control.nc.io.profiling;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.StringTokenizer;
-
-public class IOCounterLinux implements IIOCounter {
-    public static final String COMMAND = "iostat";
-    public static final String STATFILE = "/proc/self/io";
-    public static final int PAGE_SIZE = 4096;
-
-    private long baseReads = 0;
-    private long baseWrites = 0;
-
-    public IOCounterLinux() {
-        baseReads = getReads();
-        baseWrites = getWrites();
-    }
-
-    @Override
-    public long getReads() {
-        try {
-            long reads = extractRow(4);
-            return reads;
-        } catch (IOException e) {
-            try {
-                long reads = extractColumn(4) * PAGE_SIZE;
-                return reads - baseReads;
-            } catch (IOException e2) {
-                return 0;
-            }
-        }
-    }
-
-    @Override
-    public long getWrites() {
-        try {
-            long writes = extractRow(5);
-            long cancelledWrites = extractRow(6);
-            return (writes - cancelledWrites);
-        } catch (IOException e) {
-            try {
-                long writes = extractColumn(5) * PAGE_SIZE;
-                return writes - baseWrites;
-            } catch (IOException e2) {
-                return 0;
-            }
-        }
-    }
-
-    private long extractColumn(int columnIndex) throws IOException {
-        BufferedReader reader = exec(COMMAND);
-        String line = null;
-        boolean device = false;
-        long ios = 0;
-        while ((line = reader.readLine()) != null) {
-            if (line.contains("Blk_read")) {
-                device = true;
-                continue;
-            }
-            if (device == true) {
-                StringTokenizer tokenizer = new StringTokenizer(line);
-                int i = 0;
-                while (tokenizer.hasMoreTokens()) {
-                    String column = tokenizer.nextToken();
-                    if (i == columnIndex) {
-                        ios += Long.parseLong(column);
-                        break;
-                    }
-                    i++;
-                }
-            }
-        }
-        reader.close();
-        return ios;
-    }
-
-    private long extractRow(int rowIndex) throws IOException {
-        BufferedReader reader = new BufferedReader(new InputStreamReader(new 
FileInputStream(STATFILE)));
-        String line = null;
-        long ios = 0;
-        int i = 0;
-        while ((line = reader.readLine()) != null) {
-            if (i == rowIndex) {
-                StringTokenizer tokenizer = new StringTokenizer(line);
-                int j = 0;
-                while (tokenizer.hasMoreTokens()) {
-                    String column = tokenizer.nextToken();
-                    if (j == 1) {
-                        ios = Long.parseLong(column);
-                        break;
-                    }
-                    j++;
-                }
-            }
-            i++;
-        }
-        reader.close();
-        return ios;
-    }
-
-    private BufferedReader exec(String command) throws IOException {
-        Process p = Runtime.getRuntime().exec(command);
-        return new BufferedReader(new InputStreamReader(p.getInputStream()));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/94b6da6a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterOSX.java
----------------------------------------------------------------------
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterOSX.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterOSX.java
index 729157b..a48d55d 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterOSX.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterOSX.java
@@ -19,16 +19,18 @@
 
 package org.apache.hyracks.control.nc.io.profiling;
 
+import static 
org.apache.hyracks.control.nc.io.profiling.IOCounterDefault.IO_COUNTER_UNAVAILABLE;
+
 public class IOCounterOSX implements IIOCounter {
 
     @Override
     public long getReads() {
-        return 0;
+        return IO_COUNTER_UNAVAILABLE;
     }
 
     @Override
     public long getWrites() {
-        return 0;
+        return IO_COUNTER_UNAVAILABLE;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/94b6da6a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterProc.java
----------------------------------------------------------------------
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterProc.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterProc.java
new file mode 100644
index 0000000..8882271
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/io/profiling/IOCounterProc.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.hyracks.control.nc.io.profiling;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class IOCounterProc extends IOCounterCache<List<String>> {
+    private static final Logger LOGGER = LogManager.getLogger();
+    @SuppressWarnings("squid:S1075") // hardcoded URI
+    public static final File STATFILE = new File("/proc/self/io");
+    private long failureCount;
+
+    @Override
+    public long getReads() {
+        try {
+            return extractRow(getInfo(), 4);
+        } catch (Exception e) {
+            LOGGER.log(failureCount++ > 0 ? Level.DEBUG : Level.WARN, "Failure 
getting reads", e);
+            return IOCounterDefault.IO_COUNTER_UNAVAILABLE;
+        }
+    }
+
+    @Override
+    public long getWrites() {
+        try {
+            List<String> rows = getInfo();
+            long writes = extractRow(rows, 5);
+            long cancelledWrites = extractRow(rows, 6);
+            return writes - cancelledWrites;
+        } catch (Exception e) {
+            LOGGER.log(failureCount++ > 0 ? Level.DEBUG : Level.WARN, "Failure 
getting writes", e);
+            return IOCounterDefault.IO_COUNTER_UNAVAILABLE;
+        }
+    }
+
+    private long extractRow(List<String> rows, int rowIndex) {
+        return Long.parseLong(StringUtils.split(rows.get(rowIndex), ' ')[1]);
+    }
+
+    @Override
+    protected List<String> calculateInfo() throws IOException {
+        return FileUtils.readLines(STATFILE, Charset.defaultCharset());
+    }
+
+}

Reply via email to