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)
|
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 backend can POST here to publish a message to clients with no caching.
|
||||||
// The POST arguments are `cmd`, `args`, `channel`, and `scope`.
|
// 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.
|
// 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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cm := ClientMessage{MessageID: -1, Command: Command(cmd), origArguments: json}
|
cm := ClientMessage{MessageID: -1, Command: CommandPool.Intern(cmd), origArguments: json}
|
||||||
cm.parseOrigArguments()
|
cm.parseOrigArguments()
|
||||||
var count int
|
var count int
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ type ErrBackendNotOK struct {
|
||||||
Code int
|
Code int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the error interface.
|
// Error Implements the error interface.
|
||||||
func (noe ErrBackendNotOK) Error() string {
|
func (noe ErrBackendNotOK) Error() string {
|
||||||
return fmt.Sprintf("backend returned %d: %s", noe.Code, noe.Response)
|
return fmt.Sprintf("backend returned %d: %s", noe.Code, noe.Response)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,25 @@ var commandHandlers = map[Command]CommandHandler{
|
||||||
"user_history": C2SHandleRemoteCommand,
|
"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.
|
// DispatchC2SCommand handles a C2S Command in the provided ClientMessage.
|
||||||
// It calls the correct CommandHandler function, catching panics.
|
// It calls the correct CommandHandler function, catching panics.
|
||||||
// It sends either the returned Reply ClientMessage, setting the correct messageID, or sends an ErrorCommand
|
// 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 janitorsOnce sync.Once
|
||||||
|
|
||||||
|
var CommandPool StringPool
|
||||||
|
|
||||||
// SetupServerAndHandle starts all background goroutines and registers HTTP listeners on the given ServeMux.
|
// 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.
|
// Essentially, this function completely preps the server for a http.ListenAndServe call.
|
||||||
// (Uses http.DefaultServeMux if `serveMux` is nil.)
|
// (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
|
// startJanitors starts the 'is_init_func' goroutines
|
||||||
func startJanitors() {
|
func startJanitors() {
|
||||||
loadUniqueUsers()
|
loadUniqueUsers()
|
||||||
|
internCommands()
|
||||||
|
|
||||||
go authorizationJanitor()
|
go authorizationJanitor()
|
||||||
go bunchCacheJanitor()
|
go bunchCacheJanitor()
|
||||||
|
@ -508,11 +511,11 @@ func UnmarshalClientMessage(data []byte, payloadType int, v interface{}) (err er
|
||||||
|
|
||||||
spaceIdx = strings.IndexRune(dataStr, ' ')
|
spaceIdx = strings.IndexRune(dataStr, ' ')
|
||||||
if spaceIdx == -1 {
|
if spaceIdx == -1 {
|
||||||
out.Command = Command(dataStr)
|
out.Command = CommandPool.Intern(dataStr)
|
||||||
out.Arguments = nil
|
out.Arguments = nil
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
out.Command = Command(dataStr[:spaceIdx])
|
out.Command = CommandPool.Intern(dataStr[:spaceIdx])
|
||||||
}
|
}
|
||||||
dataStr = dataStr[spaceIdx+1:]
|
dataStr = dataStr[spaceIdx+1:]
|
||||||
argumentsJSON := dataStr
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := Command(formData.Get("cmd"))
|
cmd := CommandPool.Intern(formData.Get("cmd"))
|
||||||
json := formData.Get("args")
|
json := formData.Get("args")
|
||||||
channel := formData.Get("channel")
|
channel := formData.Get("channel")
|
||||||
deleteMode := formData.Get("delete") != ""
|
deleteMode := formData.Get("delete") != ""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue