Don't deepcopy job when retrieving copy of Alloc

This PR removes deepcopying of the job attached to the allocation in the
alloc runner. This operation is called very often so removing reflect
from the code path and the potentially large number of mallocs need to
create a job reduced memory and cpu pressure.
This commit is contained in:
Alex Dadgar
2017-04-28 13:18:04 -07:00
parent 9dc002a9b3
commit 9def7e1a14
5 changed files with 33 additions and 19 deletions

View File

@@ -279,8 +279,17 @@ func copyTaskStates(states map[string]*structs.TaskState) map[string]*structs.Ta
// Alloc returns the associated allocation
func (r *AllocRunner) Alloc() *structs.Allocation {
r.allocLock.Lock()
// Clear the job before copying
job := r.alloc.Job
r.alloc.Job = nil
alloc := r.alloc.Copy()
// Restore
r.alloc.Job = job
alloc.Job = job
// The status has explicitly been set.
if r.allocClientStatus != "" || r.allocClientDescription != "" {
alloc.ClientStatus = r.allocClientStatus

View File

@@ -1,6 +1,7 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
@@ -9,6 +10,7 @@ import (
"path/filepath"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/ugorji/go/codec"
)
type allocTuple struct {
@@ -78,15 +80,17 @@ func shuffleStrings(list []string) {
// persistState is used to help with saving state
func persistState(path string, data interface{}) error {
buf, err := json.Marshal(data)
if err != nil {
return fmt.Errorf("failed to encode state: %v", err)
var buf bytes.Buffer
enc := codec.NewEncoder(&buf, structs.JsonHandlePretty)
if err := enc.Encode(data); err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
return fmt.Errorf("failed to make dirs for %s: %v", path, err)
}
tmpPath := path + ".tmp"
if err := ioutil.WriteFile(tmpPath, buf, 0600); err != nil {
if err := ioutil.WriteFile(tmpPath, buf.Bytes(), 0600); err != nil {
return fmt.Errorf("failed to save state to tmp: %v", err)
}
if err := os.Rename(tmpPath, path); err != nil {

View File

@@ -21,6 +21,7 @@ import (
"github.com/docker/docker/pkg/ioutils"
"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hpcloud/tail/watch"
"github.com/ugorji/go/codec"
)
@@ -290,7 +291,7 @@ func NewStreamFramer(out io.WriteCloser, plainTxt bool,
heartbeatRate, batchWindow time.Duration, frameSize int) *StreamFramer {
// Create a JSON encoder
enc := codec.NewEncoder(out, jsonHandle)
enc := codec.NewEncoder(out, structs.JsonHandle)
// Create the heartbeat and flush ticker
heartbeat := time.NewTicker(heartbeatRate)

View File

@@ -29,18 +29,6 @@ const (
scadaHTTPAddr = "SCADA"
)
var (
// jsonHandle and jsonHandlePretty are the codec handles to JSON encode
// structs. The pretty handle will add indents for easier human consumption.
jsonHandle = &codec.JsonHandle{
HTMLCharsAsIs: true,
}
jsonHandlePretty = &codec.JsonHandle{
HTMLCharsAsIs: true,
Indent: 4,
}
)
// HTTPServer is used to wrap an Agent and expose it over an HTTP interface
type HTTPServer struct {
agent *Agent
@@ -248,13 +236,13 @@ func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Reque
if obj != nil {
var buf bytes.Buffer
if prettyPrint {
enc := codec.NewEncoder(&buf, jsonHandlePretty)
enc := codec.NewEncoder(&buf, structs.JsonHandlePretty)
err = enc.Encode(obj)
if err == nil {
buf.Write([]byte("\n"))
}
} else {
enc := codec.NewEncoder(&buf, jsonHandle)
enc := codec.NewEncoder(&buf, structs.JsonHandle)
err = enc.Encode(obj)
}
if err != nil {

View File

@@ -4231,6 +4231,18 @@ var MsgpackHandle = func() *codec.MsgpackHandle {
return h
}()
var (
// JsonHandle and JsonHandlePretty are the codec handles to JSON encode
// structs. The pretty handle will add indents for easier human consumption.
JsonHandle = &codec.JsonHandle{
HTMLCharsAsIs: true,
}
JsonHandlePretty = &codec.JsonHandle{
HTMLCharsAsIs: true,
Indent: 4,
}
)
var HashiMsgpackHandle = func() *hcodec.MsgpackHandle {
h := &hcodec.MsgpackHandle{RawToString: true}