mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-28 15:27:43 +00:00
memory: Use a string pool for Commands
This commit is contained in:
parent
c85e8b10c3
commit
abb032f0c1
5 changed files with 65 additions and 6 deletions
|
@ -62,7 +62,7 @@ func getCacheKey(remoteCommand, data string) string {
|
|||
return fmt.Sprintf("%s/%s", remoteCommand, data)
|
||||
}
|
||||
|
||||
// HBackendPublishRequest handles the /uncached_pub route.
|
||||
// HTTPBackendUncachedPublish handles the /uncached_pub route.
|
||||
// The backend can POST here to publish a message to clients with no caching.
|
||||
// The POST arguments are `cmd`, `args`, `channel`, and `scope`.
|
||||
// The `scope` argument is required because no attempt is made to infer the scope from the command, unlike /cached_pub.
|
||||
|
@ -93,7 +93,7 @@ func HTTPBackendUncachedPublish(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
cm := ClientMessage{MessageID: -1, Command: Command(cmd), origArguments: json}
|
||||
cm := ClientMessage{MessageID: -1, Command: CommandPool.Intern(cmd), origArguments: json}
|
||||
cm.parseOrigArguments()
|
||||
var count int
|
||||
|
||||
|
@ -219,7 +219,7 @@ type ErrBackendNotOK struct {
|
|||
Code int
|
||||
}
|
||||
|
||||
// Implements the error interface.
|
||||
// Error Implements the error interface.
|
||||
func (noe ErrBackendNotOK) Error() string {
|
||||
return fmt.Sprintf("backend returned %d: %s", noe.Code, noe.Response)
|
||||
}
|
||||
|
|
|
@ -41,6 +41,25 @@ var commandHandlers = map[Command]CommandHandler{
|
|||
"user_history": C2SHandleRemoteCommand,
|
||||
}
|
||||
|
||||
func internCommands() {
|
||||
CommandPool = NewStringPool()
|
||||
CommandPool._Intern_Setup(HelloCommand)
|
||||
CommandPool._Intern_Setup("ping")
|
||||
CommandPool._Intern_Setup(SetUserCommand)
|
||||
CommandPool._Intern_Setup(ReadyCommand)
|
||||
CommandPool._Intern_Setup("sub")
|
||||
CommandPool._Intern_Setup("unsub")
|
||||
CommandPool._Intern_Setup("track_follow")
|
||||
CommandPool._Intern_Setup("emoticon_uses")
|
||||
CommandPool._Intern_Setup("twitch_emote")
|
||||
CommandPool._Intern_Setup("get_link")
|
||||
CommandPool._Intern_Setup("get_display_name")
|
||||
CommandPool._Intern_Setup("update_follow_buttons")
|
||||
CommandPool._Intern_Setup("chat_history")
|
||||
CommandPool._Intern_Setup("user_history")
|
||||
CommandPool._Intern_Setup("adjacent_history")
|
||||
}
|
||||
|
||||
// DispatchC2SCommand handles a C2S Command in the provided ClientMessage.
|
||||
// It calls the correct CommandHandler function, catching panics.
|
||||
// It sends either the returned Reply ClientMessage, setting the correct messageID, or sends an ErrorCommand
|
||||
|
|
|
@ -60,6 +60,8 @@ var Configuration *ConfigFile
|
|||
|
||||
var janitorsOnce sync.Once
|
||||
|
||||
var CommandPool StringPool
|
||||
|
||||
// SetupServerAndHandle starts all background goroutines and registers HTTP listeners on the given ServeMux.
|
||||
// Essentially, this function completely preps the server for a http.ListenAndServe call.
|
||||
// (Uses http.DefaultServeMux if `serveMux` is nil.)
|
||||
|
@ -115,6 +117,7 @@ func SetupServerAndHandle(config *ConfigFile, serveMux *http.ServeMux) {
|
|||
// startJanitors starts the 'is_init_func' goroutines
|
||||
func startJanitors() {
|
||||
loadUniqueUsers()
|
||||
internCommands()
|
||||
|
||||
go authorizationJanitor()
|
||||
go bunchCacheJanitor()
|
||||
|
@ -508,11 +511,11 @@ func UnmarshalClientMessage(data []byte, payloadType int, v interface{}) (err er
|
|||
|
||||
spaceIdx = strings.IndexRune(dataStr, ' ')
|
||||
if spaceIdx == -1 {
|
||||
out.Command = Command(dataStr)
|
||||
out.Command = CommandPool.Intern(dataStr)
|
||||
out.Arguments = nil
|
||||
return nil
|
||||
} else {
|
||||
out.Command = Command(dataStr[:spaceIdx])
|
||||
out.Command = CommandPool.Intern(dataStr[:spaceIdx])
|
||||
}
|
||||
dataStr = dataStr[spaceIdx+1:]
|
||||
argumentsJSON := dataStr
|
||||
|
|
37
socketserver/server/intern.go
Normal file
37
socketserver/server/intern.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type StringPool struct {
|
||||
sync.RWMutex
|
||||
lookup map[string]Command
|
||||
}
|
||||
|
||||
func NewStringPool() *StringPool {
|
||||
return &StringPool{lookup: make(map[string]Command)}
|
||||
}
|
||||
|
||||
// doesn't lock, doesn't check for dupes.
|
||||
func (p *StringPool) _Intern_Setup(s string) {
|
||||
p.lookup[s] = Command(s)
|
||||
}
|
||||
|
||||
func (p *StringPool) Intern(s string) Command {
|
||||
p.RLock()
|
||||
ss, exists := p.lookup[s]
|
||||
p.RUnlock()
|
||||
if exists {
|
||||
return ss
|
||||
}
|
||||
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
ss, exists = p.lookup[s]
|
||||
if exists {
|
||||
return ss
|
||||
}
|
||||
p.lookup[s] = Command(string([]byte(s)))
|
||||
return s
|
||||
}
|
|
@ -236,7 +236,7 @@ func HTTPBackendCachedPublish(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
cmd := Command(formData.Get("cmd"))
|
||||
cmd := CommandPool.Intern(formData.Get("cmd"))
|
||||
json := formData.Get("args")
|
||||
channel := formData.Get("channel")
|
||||
deleteMode := formData.Get("delete") != ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue