Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: cache Available results to reduce network io #240

Merged
merged 8 commits into from
May 7, 2024
Merged

Conversation

aooohan
Copy link
Member

@aooohan aooohan commented Apr 26, 2024

  • Wrap the Available hook in the plugin with a layer of cache so that the cache can be used regardless of vfox calls or calls within the plugin.
  • Allows configurable cache duration, defaults to 12 hours.

see #227 (comment)

@aooohan aooohan requested review from Chance-fyi and bytemain and removed request for Chance-fyi April 26, 2024 07:53
@Chance-fyi
Copy link
Member

  • We should be able to refresh the cache manually.

  • Should the cache be invalidated for the following operation?

    vfox config cache.availableHookDuration 12h
    # Cache and sleep
    vfox config cache.availableHookDuration 1s

@yanecc yanecc assigned yanecc and unassigned yanecc Apr 26, 2024
@aooohan
Copy link
Member Author

aooohan commented Apr 28, 2024

  • We should be able to refresh the cache manually.

Agreed, but this can be enhanced later, for now it can be done with the config command.

  • Should the cache be invalidated for the following operation?

The cache is invalidated only in the following cases:

vfox config cache.availableHookDuration 0

vfox config cache.availableHookDuration -1

In addition, there seems to be an issue with config command. I cannot directly assign 1s to availableHookDuration that is a field of type time.Duration by command.

@bytemain
Copy link
Member

bytemain commented Apr 28, 2024

and we also can provide a cache library for the plugins, let them can store some data.

local cache = require("vfox/cache")

local key = "nodejs-index-json"
local hit = cache.has(key)
if (!hit) then
  local data = -- fetch --
  cache.set(key, data, 12 * 60 * 60 * 1000)
end

Sorry, I accidentally clicked the close button.

@bytemain bytemain closed this Apr 28, 2024
@bytemain bytemain reopened this Apr 28, 2024
@aooohan
Copy link
Member Author

aooohan commented Apr 28, 2024

and we also can provide a cache library for the plugins, let them can store some data.

Sure. I have this plan.

@Chance-fyi
Copy link
Member

In addition, there seems to be an issue with config command. I cannot directly assign 1s to availableHookDuration that is a field of type time.Duration by command.

I've added support for time.Duration type, but haven't pushed yet.

image

I noticed that YAML parsing fails if there's no type.

image

@aooohan
Copy link
Member Author

aooohan commented Apr 28, 2024

I noticed that YAML parsing fails if there's no type.

Oops, thanks for point out. Let me think about how to deal with it.

@jan-bar
Copy link
Contributor

jan-bar commented Apr 28, 2024

I noticed that YAML parsing fails if there's no type.

You can try adding the following code

func (c *Cache) UnmarshalYAML(node *yaml.Node) error {
	var data map[string]any
	err := node.Decode(&data)
	if err != nil {
		return err
	}

	if v, ok := data["availableHookDuration"]; ok {
		switch va := v.(type) {
		case int:
			c.AvailableHookDuration = time.Duration(va)
		case string:
			c.AvailableHookDuration, err = time.ParseDuration(va)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

Or

type Cache struct {
	AvailableHookDuration VfoxDuration `yaml:"availableHookDuration"` // Available hook result cache time
}

type VfoxDuration time.Duration

func (c *VfoxDuration) UnmarshalYAML(node *yaml.Node) error {
	var data any
	err := node.Decode(&data)
	if err != nil {
		return err
	}

	switch va := data.(type) {
	case int:
		*c = VfoxDuration(va)
	case string:
		pd, err := time.ParseDuration(va)
		if err != nil {
			return err
		}
		*c = VfoxDuration(pd)
	}
	return nil
}

The second option adds a new type
The first option also needs to modify this part of the code when adding fields to the Cache later

@aooohan
Copy link
Member Author

aooohan commented Apr 28, 2024

The second option adds a new type

I took your second option. ; )

// wrap Available hook with Cache.
if source.HasFunction("Available") {
targetHook := PLUGIN.RawGetString("Available")
source.pluginObj.RawSetString("Available", vm.Instance.NewFunction(func(L *lua.LState) int {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

看起来可以把这个 hook 的能力做到 LuaVM 里,

一个初始的想法是这样的:

vm.DecorateFunction(func, func () int {})

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好主意! 可以放到下一版本去做. 目前先保证功能优先.

@aooohan aooohan merged commit 719dca5 into main May 7, 2024
3 checks passed
@aooohan aooohan deleted the feat/file_cache branch May 7, 2024 01:20
@aooohan
Copy link
Member Author

aooohan commented May 7, 2024

I've added support for time.Duration type, but haven't pushed yet.

Hi, Can you push your changes?

@aooohan aooohan added this to the 0.4.3 milestone May 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants