This repository has been archived by the owner on Mar 26, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/gluster/glusterd2 into cl…
…uster-wide-options
- Loading branch information
Showing
23 changed files
with
307 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
Tracking resource usage in Glusterd2 | ||
==================================== | ||
|
||
Tracing and profiling with `pprof` is intended for developers only. This can be | ||
used for debugging memory leaks/consumption, slow flows through the code and so | ||
on. Users will normally not want profiling enabled on their production systems. | ||
To investigate memory allocations in Glusterd2, it is needed to enable the | ||
profiling feature. This can be done by adding `"profiling": true` in | ||
the `--config` file. | ||
Enabling profiling makes standard Golang pprof endpoints available. For memory | ||
allocations `/debug/pprof/heap` is most useful. | ||
Capturing a snapshot of the current allocations in the Glusterd2 is pretty | ||
simple. On the node running Glusterd2, the go pprof tool command can be used: | ||
``` | ||
[root@fedora3 glusterd2]# go tool pprof http://localhost:24007/debug/pprof/heap | ||
File: glusterd2 | ||
Build ID: 7a94c2e498445577aaf7f910d6ef1c3adc19d553 | ||
Type: inuse_space | ||
Time: Nov 28, 2018 at 2:55pm (IST) | ||
Entering interactive mode (type "help" for commands, "o" for options) | ||
(pprof) | ||
``` | ||
|
||
For working with the size of the allocations, it is helpful to set all sizes to | ||
`megabytes`, otherwise `auto` is used as a `unit` and that would add human | ||
readable B, kB, MB postfixes. This however is not useful for sorting with | ||
scripts. So, set the `unit` to `megabytes` instead: | ||
|
||
``` | ||
(pprof) unit=megabytes | ||
``` | ||
|
||
``` | ||
(pprof) top | ||
Showing nodes accounting for 330.75MB, 98.52% of 335.73MB total | ||
Dropped 305 nodes (cum <= 1.68MB) | ||
Showing top 10 nodes out of 14 | ||
flat flat% sum% cum cum% | ||
326MB 97.10% 97.10% 326MB 97.10% github.com/gluster/glusterd2/pkg/sunrpc.ReadFullRecord /root/work/src/github.com/gluster/glusterd2/pkg/sunrpc/record.go | ||
2.38MB 0.71% 97.81% 2.38MB 0.71% github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/rafthttp.startStreamWriter /root/work/src/github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/rafthttp/stream.go | ||
2.38MB 0.71% 98.52% 4.77MB 1.42% github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/rafthttp.startPeer /root/work/src/github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/rafthttp/peer.go | ||
0 0% 98.52% 326.01MB 97.10% github.com/gluster/glusterd2/pkg/sunrpc.(*serverCodec).ReadRequestHeader /root/work/src/github.com/gluster/glusterd2/pkg/sunrpc/servercodec.go | ||
0 0% 98.52% 4.83MB 1.44% github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver.(*EtcdServer).apply /root/work/src/github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver/server.go | ||
0 0% 98.52% 4.83MB 1.44% github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver.(*EtcdServer).applyAll /root/work/src/github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver/server.go | ||
0 0% 98.52% 4.77MB 1.42% github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver.(*EtcdServer).applyConfChange /root/work/src/github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver/server.go | ||
0 0% 98.52% 4.83MB 1.44% github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver.(*EtcdServer).applyEntries /root/work/src/github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver/server.go | ||
0 0% 98.52% 4.83MB 1.44% github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver.(*EtcdServer).run.func6 /root/work/src/github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/etcdserver/server.go | ||
0 0% 98.52% 4.83MB 1.44% github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/pkg/schedule.(*fifo).run /root/work/src/github.com/gluster/glusterd2/vendor/github.com/coreos/etcd/pkg/schedule/schedule.go | ||
(pprof) | ||
``` | ||
|
||
Looking at the above output, we can see that the first line consumes hundreds | ||
of MB while the other lines are just a fraction of it. | ||
This makes sure that ReadFullRecord is consuming more memory than required. | ||
To understand things even more clearly, we can see which line of ReadFullRecord | ||
consumes the memory. To view that use the list command: | ||
|
||
``` | ||
(pprof) list ReadFullRecord | ||
Total: 335.73MB | ||
ROUTINE ======================== github.com/gluster/glusterd2/pkg/sunrpc.ReadFullRecord in /root/work/src/github.com/gluster/glusterd2/pkg/sunrpc/clientcodec.go | ||
8.11kB 8.11kB (flat, cum) 0.0024% of Total | ||
. . 1:package sunrpc | ||
. . 2: | ||
. . 3:import ( | ||
8.11kB 8.11kB 4: "bytes" | ||
. . 5: "io" | ||
. . 6: "net" | ||
. . 7: "net/rpc" | ||
. . 8: "sync" | ||
. . 9: | ||
ROUTINE ======================== github.com/gluster/glusterd2/pkg/sunrpc.ReadFullRecord in /root/work/src/github.com/gluster/glusterd2/pkg/sunrpc/record.go | ||
326MB 326MB (flat, cum) 97.10% of Total | ||
. . 96:func ReadFullRecord(conn io.Reader) ([]byte, error) { | ||
. . 97: | ||
. . 98: // In almost all cases, RPC message contain only one fragment which | ||
. . 99: // is not too big in size. But set a cap on buffer size to prevent | ||
. . 100: // rogue clients from filling up memory. | ||
326MB 326MB 101: record := bytes.NewBuffer(make([]byte, 0, maxRecordSize)) | ||
. . 102: var fragmentHeader uint32 | ||
. . 103: for { | ||
. . 104: // Read record fragment header | ||
. . 105: err := binary.Read(conn, binary.BigEndian, &fragmentHeader) | ||
. . 106: if err != nil { | ||
(pprof) | ||
``` | ||
|
||
The records allocation is the culprit and we need to look further into | ||
the code as to why the records is allocating so much and fix it. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package cmd | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/gluster/glusterd2/pkg/api" | ||
|
||
"github.com/olekukonko/tablewriter" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
const ( | ||
helpClusterOptionCmd = "Gluster Cluster Option Management" | ||
helpClusterOptionSetCmd = "Set Cluster Option" | ||
helpClusterOptionGetCmd = "Get Cluster Option" | ||
) | ||
|
||
func init() { | ||
clusterCmd.AddCommand(clusterOptionGetCmd) | ||
clusterCmd.AddCommand(clusterOptionSetCmd) | ||
} | ||
|
||
var clusterCmd = &cobra.Command{ | ||
Use: "cluster", | ||
Short: helpClusterOptionCmd, | ||
} | ||
|
||
var clusterOptionSetCmd = &cobra.Command{ | ||
Use: "set <option> <value> [<option> <value>]...", | ||
Short: helpClusterOptionSetCmd, | ||
Args: clusterSetCmdArgs, | ||
Run: clusterSetCmdRun, | ||
} | ||
|
||
func clusterSetCmdArgs(cmd *cobra.Command, args []string) error { | ||
// Ensure we have enough arguments for the command | ||
if len(args) < 2 { | ||
return errors.New("need at least 2 arguments") | ||
} | ||
|
||
// Ensure we have a proper option-value pairs | ||
if (len(args) % 2) != 0 { | ||
return errors.New("needs '<option> <value>' to be in pairs") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func clusterSetCmdRun(cmd *cobra.Command, args []string) { | ||
options := args[:] | ||
if err := clusterOptionJSONHandler(cmd, options); err != nil { | ||
if GlobalFlag.Verbose { | ||
log.WithError(err).Error("cluster option set failed") | ||
} | ||
failure("Cluster option set failed", err, 1) | ||
} else { | ||
fmt.Printf("Options set successfully \n") | ||
} | ||
} | ||
|
||
func clusterOptionJSONHandler(cmd *cobra.Command, options []string) error { | ||
copt := make(map[string]string) | ||
for op, val := range options { | ||
if op%2 == 0 { | ||
copt[val] = options[op+1] | ||
} | ||
} | ||
|
||
err := client.ClusterOptionSet(api.ClusterOptionReq{ | ||
Options: copt}) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
var clusterOptionGetCmd = &cobra.Command{ | ||
Use: "get", | ||
Short: helpClusterOptionGetCmd, | ||
Args: cobra.RangeArgs(0, 1), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
table := tablewriter.NewWriter(os.Stdout) | ||
opts, err := client.GetClusterOption() | ||
if err != nil { | ||
if GlobalFlag.Verbose { | ||
log.WithError(err).Error("error getting cluster options") | ||
} | ||
failure("Error getting cluster options", err, 1) | ||
} | ||
table.SetHeader([]string{"Name", "Modified", "Value", "Default Value"}) | ||
table.SetAlignment(tablewriter.ALIGN_LEFT) | ||
for _, opt := range opts { | ||
table.Append([]string{opt.Key, formatBoolYesNo(opt.Modified), opt.Value, opt.DefaultValue}) | ||
} | ||
table.Render() | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -279,6 +279,8 @@ var volumeGetCmd = &cobra.Command{ | |
} | ||
} | ||
table.Render() | ||
fmt.Println("") | ||
|
||
} | ||
}, | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.