mirror of
				https://github.com/TeaOSLab/EdgeNode.git
				synced 2025-11-04 16:00:25 +08:00 
			
		
		
		
	优化Partial Content配置编码速度
This commit is contained in:
		@@ -3,8 +3,9 @@
 | 
			
		||||
package caches
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"github.com/iwind/TeaGo/types"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -22,8 +23,37 @@ func NewPartialRanges(expiresAt int64) *PartialRanges {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewPartialRangesFromData 从数据中解析范围
 | 
			
		||||
func NewPartialRangesFromData(data []byte) (*PartialRanges, error) {
 | 
			
		||||
	var rs = NewPartialRanges(0)
 | 
			
		||||
	for {
 | 
			
		||||
		var index = bytes.IndexRune(data, '\n')
 | 
			
		||||
		if index < 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		var line = data[:index]
 | 
			
		||||
		var colonIndex = bytes.IndexRune(line, ':')
 | 
			
		||||
		if colonIndex > 0 {
 | 
			
		||||
			switch string(line[:colonIndex]) {
 | 
			
		||||
			case "e":
 | 
			
		||||
				rs.ExpiresAt = types.Int64(line[colonIndex+1:])
 | 
			
		||||
			case "r":
 | 
			
		||||
				var commaIndex = bytes.IndexRune(line, ',')
 | 
			
		||||
				if commaIndex > 0 {
 | 
			
		||||
					rs.Ranges = append(rs.Ranges, [2]int64{types.Int64(line[colonIndex+1 : commaIndex]), types.Int64(line[commaIndex+1:])})
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		data = data[index+1:]
 | 
			
		||||
		if len(data) == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return rs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewPartialRangesFromJSON 从JSON中解析范围
 | 
			
		||||
func NewPartialRangesFromJSON(data []byte) (*PartialRanges, error) {
 | 
			
		||||
func newPartialRangesFromJSON(data []byte) (*PartialRanges, error) {
 | 
			
		||||
	var rs = NewPartialRanges(0)
 | 
			
		||||
	err := json.Unmarshal(data, &rs)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -38,7 +68,17 @@ func NewPartialRangesFromFile(path string) (*PartialRanges, error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return NewPartialRangesFromJSON(data)
 | 
			
		||||
	if len(data) == 0 {
 | 
			
		||||
		return NewPartialRanges(0), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 兼容老的JSON格式
 | 
			
		||||
	if data[0] == '{' {
 | 
			
		||||
		return newPartialRangesFromJSON(data)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 新的格式
 | 
			
		||||
	return NewPartialRangesFromData(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add 添加新范围
 | 
			
		||||
@@ -109,27 +149,22 @@ func (this *PartialRanges) Nearest(begin int64, end int64) (r [2]int64, ok bool)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AsJSON 转换为JSON
 | 
			
		||||
func (this *PartialRanges) AsJSON() ([]byte, error) {
 | 
			
		||||
	return json.Marshal(this)
 | 
			
		||||
// 转换为字符串
 | 
			
		||||
func (this *PartialRanges) String() string {
 | 
			
		||||
	var s = "e:" + types.String(this.ExpiresAt) + "\n"
 | 
			
		||||
	for _, r := range this.Ranges {
 | 
			
		||||
		s += "r:" + types.String(r[0]) + "," + types.String(r[1]) + "\n"
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *PartialRanges) Bytes() []byte {
 | 
			
		||||
	return []byte(this.String())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteToFile 写入到文件中
 | 
			
		||||
func (this *PartialRanges) WriteToFile(path string) error {
 | 
			
		||||
	data, err := this.AsJSON()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("convert to json failed: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return os.WriteFile(path, data, 0666)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadFromFile 从文件中读取
 | 
			
		||||
func (this *PartialRanges) ReadFromFile(path string) (*PartialRanges, error) {
 | 
			
		||||
	data, err := os.ReadFile(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return NewPartialRangesFromJSON(data)
 | 
			
		||||
	return os.WriteFile(path, this.Bytes(), 0666)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *PartialRanges) Max() int64 {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,10 +3,12 @@
 | 
			
		||||
package caches_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeNode/internal/caches"
 | 
			
		||||
	"github.com/iwind/TeaGo/assert"
 | 
			
		||||
	"github.com/iwind/TeaGo/logs"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestNewPartialRanges(t *testing.T) {
 | 
			
		||||
@@ -133,36 +135,49 @@ func TestNewPartialRanges_Large_Range(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	var r = caches.NewPartialRanges(0)
 | 
			
		||||
	r.Add(1, largeSize)
 | 
			
		||||
	jsonData, err := r.AsJSON()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	t.Log(string(jsonData))
 | 
			
		||||
	var s = r.String()
 | 
			
		||||
	t.Log(s)
 | 
			
		||||
 | 
			
		||||
	r2, err := caches.NewPartialRangesFromJSON(jsonData)
 | 
			
		||||
	r2, err := caches.NewPartialRangesFromData([]byte(s))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a.IsTrue(largeSize == r2.Ranges[0][1])
 | 
			
		||||
	logs.PrintAsJSON(r, t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNewPartialRanges_AsJSON(t *testing.T) {
 | 
			
		||||
func TestPartialRanges_Encode_JSON(t *testing.T) {
 | 
			
		||||
	var r = caches.NewPartialRanges(0)
 | 
			
		||||
	for j := 0; j < 1000; j++ {
 | 
			
		||||
		r.Add(int64(j), int64(j+100))
 | 
			
		||||
	r.ExpiresAt = time.Now().Unix()
 | 
			
		||||
	for i := 0; i < 10; i++ {
 | 
			
		||||
		r.Ranges = append(r.Ranges, [2]int64{int64(i * 100), int64(i*100 + 100)})
 | 
			
		||||
	}
 | 
			
		||||
	data, err := r.AsJSON()
 | 
			
		||||
	var before = time.Now()
 | 
			
		||||
	data, err := json.Marshal(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	t.Log(string(data))
 | 
			
		||||
	t.Log(time.Since(before).Seconds()*1000, "ms")
 | 
			
		||||
	t.Log(len(data))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	r2, err := caches.NewPartialRangesFromJSON(data)
 | 
			
		||||
func TestPartialRanges_Encode_String(t *testing.T) {
 | 
			
		||||
	var r = caches.NewPartialRanges(0)
 | 
			
		||||
	r.ExpiresAt = time.Now().Unix()
 | 
			
		||||
	for i := 0; i < 10; i++ {
 | 
			
		||||
		r.Ranges = append(r.Ranges, [2]int64{int64(i * 100), int64(i*100 + 100)})
 | 
			
		||||
	}
 | 
			
		||||
	var before = time.Now()
 | 
			
		||||
	var data = r.String()
 | 
			
		||||
	t.Log(time.Since(before).Seconds()*1000, "ms")
 | 
			
		||||
	t.Log(len(data))
 | 
			
		||||
 | 
			
		||||
	r2, err := caches.NewPartialRangesFromData([]byte(data))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	t.Log(r2.Ranges)
 | 
			
		||||
	logs.PrintAsJSON(r2, t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkNewPartialRanges(b *testing.B) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user