Skip to content

Commit

Permalink
Merge pull request #37 from dubbogo/feature/runtime
Browse files Browse the repository at this point in the history
Add: get host/container cpu/mem info
  • Loading branch information
AlexStocks authored Dec 10, 2020
2 parents 6acc198 + 928960b commit 4e3d8d4
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 19 deletions.
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/pbnjay/memory v0.0.0-20201129165224-b12e5d931931 h1:EeWknjeRU+R3O4ghG7XZCpgSfJNStZyEP8aWyQwJM8s=
github.com/pbnjay/memory v0.0.0-20201129165224-b12e5d931931/go.mod h1:RMU2gJXhratVxBDTFeOdNhd540tG57lt9FIUV0YLvIQ=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
4 changes: 2 additions & 2 deletions page/page.go → hash/page/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ func (d *Page) HasData() bool {
return d.GetDataSize() > 0
}

// New will create an instance
func New(requestOffset int, pageSize int,
// NewPage will create an instance
func NewPage(requestOffset int, pageSize int,
data []interface{}, totalSize int) *Page {

remain := totalSize % pageSize
Expand Down
4 changes: 2 additions & 2 deletions page/page_test.go → hash/page/page_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (

func TestNewDefaultPage(t *testing.T) {
data := make([]interface{}, 10)
page := New(121, 10, data, 499)
page := NewPage(121, 10, data, 499)

assert.Equal(t, 10, page.GetDataSize())
assert.Equal(t, 121, page.GetOffset())
Expand All @@ -37,6 +37,6 @@ func TestNewDefaultPage(t *testing.T) {
assert.True(t, page.HasNext())
assert.True(t, page.HasData())

page = New(492, 10, data, 499)
page = NewPage(492, 10, data, 499)
assert.False(t, page.HasNext())
}
File renamed without changes.
64 changes: 64 additions & 0 deletions path/filepath/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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 gxfilepath

import (
"fmt"
"os"
)

// Exists returns whether the given file or directory exists
func Exists(path string) (bool, error) {
_, err := os.Lstat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}

return false, err
}

// FileExists checks whether a file exists in the given path. It also fails if
// the path points to a directory or there is an error when trying to check the file.
func FileExists(path string) (bool, error) {
info, err := os.Lstat(path)
if err != nil {
return false, err
}
if info.IsDir() {
return false, fmt.Errorf("%q is a directory", path)
}

return true, nil
}

// DirExists checks whether a directory exists in the given path. It also fails
// if the path is a file rather a directory or there is an error checking whether it exists.
func DirExists(path string) (bool, error) {
info, err := os.Lstat(path)
if err != nil {
return false, err
}
if !info.IsDir() {
return false, fmt.Errorf("%q is a file", path)
}

return true, nil
}
74 changes: 74 additions & 0 deletions path/filepath/path_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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 gxfilepath

import (
"testing"
)

import (
"github.com/stretchr/testify/assert"
)

func TestFileExists(t *testing.T) {
file := "./path_test.go"
ok, err := Exists(file)
assert.True(t, ok)
assert.Nil(t, err)
ok, err = DirExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
ok, err = FileExists(file)
assert.True(t, ok)
assert.Nil(t, err)

file = "./path_test1.go"
ok, err = Exists(file)
assert.False(t, ok)
assert.Nil(t, err)
ok, err = DirExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
ok, err = FileExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
}

func TestDirExists(t *testing.T) {
file := "./"
ok, err := Exists(file)
assert.True(t, ok)
assert.Nil(t, err)
ok, err = DirExists(file)
assert.True(t, ok)
assert.Nil(t, err)
ok, err = FileExists(file)
assert.False(t, ok)
assert.NotNil(t, err)

file = "./go"
ok, err = Exists(file)
assert.False(t, ok)
assert.Nil(t, err)
ok, err = DirExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
ok, err = FileExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
}
4 changes: 2 additions & 2 deletions runtime/goroutine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
func TestGoSafe(t *testing.T) {
times := int32(1)

wg := sync.WaitGroup{}
var wg sync.WaitGroup
GoSafely(&wg,
false,
func() {
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestGoSafe(t *testing.T) {

func TestGoUnterminated(t *testing.T) {
times := uint64(1)
wg := sync.WaitGroup{}
var wg sync.WaitGroup
GoUnterminated(
func() {
if atomic.AddUint64(&times, 1) == 2 {
Expand Down
39 changes: 35 additions & 4 deletions runtime/sys.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,14 @@ import (
)

import (
"github.com/shirou/gopsutil/mem"
"github.com/shirou/gopsutil/process"
)

import (
"github.com/dubbogo/gost/path/filepath"
)

var (
CurrentPID = os.Getpid()
)
Expand All @@ -39,6 +44,36 @@ const (
cgroupMemLimitPath = "/sys/fs/cgroup/memory/memory.limit_in_bytes"
)

// GetCPUNum gets current os's cpu number
func GetCPUNum() int {
return runtime.NumCPU()
}

// GetMemoryStat gets current os's memory size in bytes
func GetMemoryStat() (total, used, free uint64, usedPercent float64) {
stat, err := mem.VirtualMemory()
if err != nil {
return 0, 0, 0, 0
}

return stat.Total, stat.Used, stat.Free, stat.UsedPercent
}

// IsCgroup checks whether current os is a container or not
func IsCgroup() bool {
ok, _ := gxfilepath.Exists(cgroupMemLimitPath)
if ok {
return true
}

return false
}

// GetCgroupMemoryLimit returns a container's total memory in bytes
func GetCgroupMemoryLimit() (uint64, error) {
return readUint(cgroupMemLimitPath)
}

// GetThreadNum gets current process's thread number
func GetThreadNum() int {
return pprof.Lookup("threadcreate").Count()
Expand Down Expand Up @@ -124,10 +159,6 @@ func readUint(path string) (uint64, error) {
return parseUint(strings.TrimSpace(string(v)), 10, 64)
}

func GetCgroupMemoryLimit() (uint64, error) {
return readUint(cgroupMemLimitPath)
}

// GetCgroupProcessMemoryPercent gets current process's memory usage percent in cgroup env
func GetCgroupProcessMemoryPercent() (float64, error) {
p, err := process.NewProcess(int32(os.Getpid()))
Expand Down
32 changes: 25 additions & 7 deletions runtime/sys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import (
"time"
)

func TestProcessSysStat(t *testing.T) {
func TestSysStat(t *testing.T) {
t.Logf("current os cpu number %d", GetCPUNum())
total, used, free, usedPercent := GetMemoryStat()
t.Logf("memory: limit %d bytes, used %d bytes, free %d bytes, usedPercent %f", total, used, free, usedPercent)
t.Logf("current prcess thread number %d", GetThreadNum())
go func() {
time.Sleep(10e9)
Expand All @@ -40,21 +43,36 @@ func TestProcessSysStat(t *testing.T) {
t.Logf("process cpu stat %v", cpu)

size := 100 * 1024 * 1024
bytes := make([]byte, size)
_ = bytes[:size-1]
arr := make([]byte, size)
for idx := range arr {
arr[idx] = byte(idx / 255)
}
memoryStat, err := GetProcessMemoryStat()
if err != nil {
t.Errorf("GetProcessMemoryStat() = error %+v", err)
}
t.Logf("process memory usage stat %v", memoryStat)
//if memoryStat <= uint64(size) {
// t.Errorf("memory usage stat %d < %d", memoryStat, size)
//}
//t.Logf("process memory usage stat %v", memoryStat)
if memoryStat <= uint64(size) {
t.Errorf("memory usage stat %d < %d", memoryStat, size)
}

memoryUsage, err := GetProcessMemoryPercent()
if err != nil {
t.Errorf("GetProcessMemoryPercent() = error %+v", err)
}
t.Logf("process memory usage percent %v", memoryUsage)

if IsCgroup() {
memoryLimit, err := GetCgroupMemoryLimit()
if err != nil {
t.Errorf("GetCgroupMemoryLimit() = error %+v", err)
}
t.Logf("CGroupMemoryLimit() = %d", memoryLimit)

memoryPercent, err := GetCgroupProcessMemoryPercent()
if err != nil {
t.Errorf("GetCgroupProcessMemoryPercent(ps:%d) = error %+v", CurrentPID, err)
}
t.Logf("GetCgroupProcessMemoryPercent(ps:%d) = %+v", CurrentPID, memoryPercent)
}
}
5 changes: 3 additions & 2 deletions sync/task_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ func TestTaskPoolSimple(t *testing.T) {
}
wg.Wait()

if taskCnt != atomic.LoadInt64(cnt) {
t.Error("want ", taskCnt, " got ", *cnt)
cntValue := atomic.LoadInt64(cnt)
if taskCnt != cntValue {
t.Error("want ", taskCnt, " got ", cntValue)
}
}

Expand Down

0 comments on commit 4e3d8d4

Please sign in to comment.