1 回答
TA贡献1796条经验 获得超7个赞
您是否发现上述两个计划更改中的任何一个存在任何问题?这些是一个好的起点吗?
两者都没有问题。如果日志肯定是行分隔的,您可以只存储行号,但存储字节偏移量可能更健壮。标准io.Reader接口返回读取的字节数,因此您可以使用它来获得偏移量。
对于优化我们如何存储日志行的内存消耗,您还有其他提示/建议吗?
这取决于您想将它们用于什么目的,但是一旦它们被标记化(并且您已经从该行获得了您想要的数据),为什么要在内存中保留该行?它已经在文件中,您现在有一个偏移量可以快速再次查找它。
除了枚举之外,是否有任何等效于咆哮的位图?或者任何其他巧妙的方式来紧凑地存储它?
我倾向于将每个枚举类型定义为一个 int,并使用iota. 就像是:
package main
import (
"fmt"
"time"
)
type LogLevel int
type LogComponent int
type Operation int
const (
Info LogLevel = iota
Warning
Debug
Error
)
const (
Storage LogComponent = iota
Journal
Commands
Indexin
)
const (
Query Operation = iota
Insert
Delete
)
type LogLine struct {
DateTime time.Time
QueryDuration time.Duration
ThreadName string
ConNum uint
Level LogLevel
Comp LogComponent
Op Operation
Namespace string
}
func main() {
l := &LogLine{
time.Now(),
10 * time.Second,
"query1",
1000,
Info,
Journal,
Delete,
"ns1",
}
fmt.Printf("%v\n", l)
}
产生&{2009-11-10 23:00:00 +0000 UTC 10s query1 1000 0 1 2 ns1}.
操场
您可以打包一些结构体字段,但是您需要为每个字段定义位范围,并且您会失去一些开放性。例如,将 LogLevel 定义为前 2 位,将 Component 定义为下 2 位等。
我还想到了布隆过滤器,也许使用它们来存储每个日志行是否在一个集合中(即日志级别警告、日志级别错误)——但是,它只能在这些集合中,所以我不知道那讲得通。另外,不确定如何处理误报。
对于您当前的示例,布隆过滤器可能有点矫枉过正。为每个枚举或其他一些跟踪行号到(例如)日志级别关系的主“索引”设置一个 []int 可能更容易。正如您所说,每个日志行只能在一组中。事实上,根据枚举字段的数量,使用打包的枚举作为标识符可能更容易map[int][]int。
Set := make(map[int][]int)
Set[int(Delete) << 4 + int(Journal) << 2 + int(Debug)] = []int{7, 45, 900} // Line numbers in this set.
见这里为一个完整的,虽然hackish的例子。
- 1 回答
- 0 关注
- 213 浏览
添加回答
举报