Skip to content

Commit

Permalink
0.1.0 tag, checkpoint release.
Browse files Browse the repository at this point in the history
Upped the user cache capacity and topic cache capacity.
More resource management work. WIP.
Added Hyperdrive to the experimental folder. It doesn't really work right now, but I'd like to track it's progress.
Eliminated a line in global.js
  • Loading branch information
Azareal committed Sep 19, 2018
1 parent cd89e83 commit 225a2cc
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 14 deletions.
4 changes: 3 additions & 1 deletion common/null_user_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ func NewNullUserCache() *NullUserCache {
}

// nolint
func (mus *NullUserCache) DeallocOverflow() {}
func (mus *NullUserCache) DeallocOverflow(evictPriority bool) (evicted int) {
return 0
}
func (mus *NullUserCache) Get(id int) (*User, error) {
return nil, ErrNoRows
}
Expand Down
24 changes: 22 additions & 2 deletions common/user_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

// UserCache is an interface which spits out users from a fast cache rather than the database, whether from memory or from an application like Redis. Users may not be present in the cache but may be in the database
type UserCache interface {
DeallocOverflow() // May cause thread contention, looks for items to evict
DeallocOverflow(evictPriority bool) (evicted int) // May cause thread contention, looks for items to evict
Get(id int) (*User, error)
GetUnsafe(id int) (*User, error)
BulkGet(ids []int) (list []*User)
Expand Down Expand Up @@ -40,7 +40,7 @@ func NewMemoryUserCache(capacity int) *MemoryUserCache {
}

// TODO: Avoid deallocating topic list users
func (mus *MemoryUserCache) DeallocOverflow() {
func (mus *MemoryUserCache) DeallocOverflow(evictPriority bool) (evicted int) {
var toEvict = make([]int, 10)
var evIndex = 0
mus.RLock()
Expand All @@ -58,6 +58,25 @@ func (mus *MemoryUserCache) DeallocOverflow() {
}
mus.RUnlock()

// Clear some of the less active users now with a bit more aggressiveness
if evIndex == 0 && evictPriority {
toEvict = make([]int, 20)
mus.RLock()
for _, user := range mus.items {
if user.Score < 100 && !user.IsMod {
if EnableWebsockets && WsHub.HasUser(user.ID) {
continue
}
toEvict[evIndex] = user.ID
evIndex++
if evIndex == 20 {
break
}
}
}
mus.RUnlock()
}

// Remove zero IDs from the evictable list, so we don't waste precious cycles locked for those
var lastZero = -1
for i, uid := range toEvict {
Expand All @@ -70,6 +89,7 @@ func (mus *MemoryUserCache) DeallocOverflow() {
}

mus.BulkRemove(toEvict)
return len(toEvict)
}

// Get fetches a user by ID. Returns ErrNoRows if not present.
Expand Down
4 changes: 2 additions & 2 deletions config/config_example.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
"MaxRequestSizeStr":"5MB",
"UserCache":"static",
"TopicCache":"static",
"UserCacheCapacity":120,
"TopicCacheCapacity":200,
"UserCacheCapacity":150,
"TopicCacheCapacity":250,
"DefaultPath":"/topics/",
"DefaultGroup":3,
"ActivationGroup":5,
Expand Down
34 changes: 34 additions & 0 deletions experimental/plugin_hyperdrive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Highly experimental plugin for caching rendered pages for guests
package main

import (
"sync/atomic"

"./common"
)

var hyperPageCache *HyperPageCache

func init() {
common.Plugins.Add(&common.Plugin{UName: "hyperdrive", Name: "Hyperdrive", Author: "Azareal", Init: initHyperdrive, Deactivate: deactivateHyperdrive})
}

func initHyperdrive() error {
hyperPageCache = newHyperPageCache()
common.Plugins["hyperdrive"].AddHook("somewhere", deactivateHyperdrive)
return nil
}

func deactivateHyperdrive() {
hyperPageCache = nil
}

type HyperPageCache struct {
topicList atomic.Value
}

func newHyperPageCache() *HyperPageCache {
pageCache := new(HyperPageCache)
pageCache.topicList.Store([]byte(""))
return pageCache
}
4 changes: 2 additions & 2 deletions install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ func main() {
"MaxRequestSizeStr":"5MB",
"UserCache":"static",
"TopicCache":"static",
"UserCacheCapacity":120,
"TopicCacheCapacity":200,
"UserCacheCapacity":150,
"TopicCacheCapacity":250,
"DefaultPath":"/topics/",
"DefaultGroup":3,
"ActivationGroup":5,
Expand Down
14 changes: 10 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
"github.com/pkg/errors"
)

var version = common.Version{Major: 0, Minor: 1, Patch: 0, Tag: "dev"}
var version = common.Version{Major: 0, Minor: 1, Patch: 0}
var router *GenRouter
var logWriter = io.MultiWriter(os.Stderr)

Expand Down Expand Up @@ -373,27 +373,33 @@ func main() {
go tickLoop(thumbChan, halfSecondTicker, secondTicker, fifteenMinuteTicker, hourTicker)

// Resource Management Goroutine
go func() {
/*go func() {
ucache := common.Users.GetCache()
tcache := common.Topics.GetCache()
if ucache == nil && tcache == nil {
return
}
var lastEvictedCount int
var couldNotDealloc bool
for {
select {
case <-secondTicker.C:
// TODO: Add a LastRequested field to cached User structs to avoid evicting the same things which wind up getting loaded again anyway?
if ucache != nil {
ucap := ucache.GetCapacity()
if ucache.Length() <= ucap || common.Users.GlobalCount() <= ucap {
countNotDealloc = false
continue
}
//ucache.DeallocOverflow()
lastEvictedCount = ucache.DeallocOverflow(countNotDealloc)
countNotDealloc = (lastEvictedCount == 0)
} else {
countNotDealloc = false
}
}
}
}()
}()*/

log.Print("Initialising the router")
router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
Expand Down
4 changes: 1 addition & 3 deletions public/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,11 @@ function loadAlerts(menuAlerts) {
updateAlertList(menuAlerts)
},
error: (magic,theStatus,error) => {
let errtxt
let errtxt = "Unable to get the alerts";
try {
var data = JSON.parse(magic.responseText);
if("errmsg" in data) errtxt = data.errmsg;
else errtxt = "Unable to get the alerts";
} catch(err) {
errtxt = "Unable to get the alerts";
console.log(magic.responseText);
console.log(err);
}
Expand Down

0 comments on commit 225a2cc

Please sign in to comment.