mirror of
https://github.com/nkanaev/yarr.git
synced 2026-06-27 18:45:17 +00:00
storage: performance tests
This commit is contained in:
272
src/storage/tests/item_performance_test.go
Normal file
272
src/storage/tests/item_performance_test.go
Normal file
@@ -0,0 +1,272 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nkanaev/yarr/src/storage"
|
||||
"github.com/nkanaev/yarr/src/storage/model"
|
||||
)
|
||||
|
||||
var loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
|
||||
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
|
||||
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " +
|
||||
"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in " +
|
||||
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " +
|
||||
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " +
|
||||
"culpa qui officia deserunt mollit anim id est laborum. " +
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
|
||||
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
|
||||
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " +
|
||||
"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in " +
|
||||
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " +
|
||||
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " +
|
||||
"culpa qui officia deserunt mollit anim id est laborum."
|
||||
|
||||
func perfDB(t testing.TB) storage.Storage {
|
||||
t.Helper()
|
||||
db, err := storage.New(filepath.Join(t.TempDir(), "perf.db"))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create perf db: %v", err)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func createBenchFeed(db storage.Storage, tag string, n int) *model.Feed {
|
||||
feed := db.CreateFeed(model.CreateFeedParams{FeedLink: fmt.Sprintf("http://%s.xml", tag)})
|
||||
now := time.Now()
|
||||
items := make([]model.Item, n)
|
||||
for i := range items {
|
||||
items[i] = model.Item{
|
||||
GUID: fmt.Sprintf("b-%s-%d", tag, i),
|
||||
FeedId: feed.Id,
|
||||
Title: "t",
|
||||
Date: now.Add(time.Duration(i) * time.Second),
|
||||
}
|
||||
}
|
||||
db.CreateItems(items)
|
||||
return feed
|
||||
}
|
||||
|
||||
func BenchmarkCreateItems_Batch10(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
feed := db.CreateFeed(model.CreateFeedParams{FeedLink: "http://b10.xml"})
|
||||
|
||||
for b.Loop() {
|
||||
items := make([]model.Item, 10)
|
||||
for j := range items {
|
||||
items[j] = model.Item{
|
||||
GUID: fmt.Sprintf("b10-%d", j),
|
||||
FeedId: feed.Id,
|
||||
Title: "t",
|
||||
Content: loremIpsum,
|
||||
Date: time.Now(),
|
||||
}
|
||||
}
|
||||
db.CreateItems(items)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCreateItems_Batch100(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
feed := db.CreateFeed(model.CreateFeedParams{FeedLink: "http://b100.xml"})
|
||||
|
||||
for b.Loop() {
|
||||
items := make([]model.Item, 100)
|
||||
for j := range items {
|
||||
items[j] = model.Item{
|
||||
GUID: fmt.Sprintf("b100-%d", j),
|
||||
FeedId: feed.Id,
|
||||
Title: "t",
|
||||
Content: loremIpsum,
|
||||
Date: time.Now(),
|
||||
}
|
||||
}
|
||||
db.CreateItems(items)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCreateItems_Batch1000(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
feed := db.CreateFeed(model.CreateFeedParams{FeedLink: "http://b1000.xml"})
|
||||
|
||||
for b.Loop() {
|
||||
items := make([]model.Item, 1000)
|
||||
for j := range items {
|
||||
items[j] = model.Item{
|
||||
GUID: fmt.Sprintf("b1000-%d", j),
|
||||
FeedId: feed.Id,
|
||||
Title: "t",
|
||||
Content: loremIpsum,
|
||||
Date: time.Now(),
|
||||
}
|
||||
}
|
||||
db.CreateItems(items)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCreateItems_Upsert(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
feed := db.CreateFeed(model.CreateFeedParams{FeedLink: "http://upsert.xml"})
|
||||
|
||||
items := make([]model.Item, 100)
|
||||
for j := range items {
|
||||
items[j] = model.Item{
|
||||
GUID: fmt.Sprintf("u-%d", j),
|
||||
FeedId: feed.Id,
|
||||
Title: "t",
|
||||
Date: time.Now(),
|
||||
}
|
||||
}
|
||||
db.CreateItems(items)
|
||||
|
||||
for b.Loop() {
|
||||
db.CreateItems(items)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFeedStats_Empty(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
|
||||
for b.Loop() {
|
||||
db.FeedStats()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFeedStats_MultipleFeeds(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
|
||||
numFeeds := 1000
|
||||
var feeds []*model.Feed
|
||||
for k := 0; k < numFeeds; k++ {
|
||||
feeds = append(feeds, db.CreateFeed(model.CreateFeedParams{
|
||||
FeedLink: fmt.Sprintf("http://f%d.xml", k),
|
||||
}))
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
var all []model.Item
|
||||
for i := 0; i < 100_000; i++ {
|
||||
all = append(all, model.Item{
|
||||
GUID: fmt.Sprintf("i-%d", i),
|
||||
FeedId: feeds[i%numFeeds].Id,
|
||||
Title: "t",
|
||||
Date: now.Add(time.Duration(i) * time.Second),
|
||||
Status: model.ItemStatus(i % 3),
|
||||
})
|
||||
}
|
||||
db.CreateItems(all)
|
||||
|
||||
for b.Loop() {
|
||||
db.FeedStats()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkListItems_All(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
createBenchFeed(db, "all", 10000)
|
||||
|
||||
for b.Loop() {
|
||||
db.ListItems(model.ItemFilter{}, 50, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkListItems_ByFeed(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
feed := createBenchFeed(db, "feed", 10000)
|
||||
|
||||
for b.Loop() {
|
||||
db.ListItems(model.ItemFilter{FeedID: &feed.Id}, 50, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkListItems_ByStatus(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
createBenchFeed(db, "status", 10000)
|
||||
starred := model.STARRED
|
||||
|
||||
for b.Loop() {
|
||||
db.ListItems(model.ItemFilter{Status: &starred}, 50, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkListItems_Search(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
feed := db.CreateFeed(model.CreateFeedParams{FeedLink: "http://search.xml"})
|
||||
now := time.Now()
|
||||
var all []model.Item
|
||||
for i := 0; i < 10000; i++ {
|
||||
all = append(all, model.Item{
|
||||
GUID: fmt.Sprintf("s-%d", i),
|
||||
FeedId: feed.Id,
|
||||
Title: fmt.Sprintf("searchable title %d", i),
|
||||
Content: "common text for full-text search indexing",
|
||||
Date: now.Add(time.Duration(i) * time.Second),
|
||||
})
|
||||
}
|
||||
db.CreateItems(all)
|
||||
query := "searchable"
|
||||
|
||||
for b.Loop() {
|
||||
db.ListItems(model.ItemFilter{Search: &query}, 50, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkListItems_Paginated(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
feed := createBenchFeed(db, "page", 10000)
|
||||
|
||||
all := db.ListItems(model.ItemFilter{FeedID: &feed.Id}, 10000, false, false)
|
||||
cursor := all[len(all)/2].Id
|
||||
|
||||
for b.Loop() {
|
||||
db.ListItems(model.ItemFilter{After: &cursor}, 50, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarkItemsRead_All(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
createBenchFeed(db, "all", 1_000_000)
|
||||
|
||||
for b.Loop() {
|
||||
db.MarkItemsRead(model.MarkFilter{})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarkItemsRead_ByFeed(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
createBenchFeed(db, "feed0", 500_000)
|
||||
feed := createBenchFeed(db, "feed1", 500_000)
|
||||
for b.Loop() {
|
||||
db.MarkItemsRead(model.MarkFilter{FeedID: &feed.Id})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarkItemsRead_ByFolder(b *testing.B) {
|
||||
db := perfDB(b)
|
||||
|
||||
folder := db.CreateFolder("perf")
|
||||
now := time.Now()
|
||||
var all []model.Item
|
||||
for k := 0; k < 5; k++ {
|
||||
feed := db.CreateFeed(model.CreateFeedParams{
|
||||
FeedLink: fmt.Sprintf("http://f%d.xml", k),
|
||||
FolderID: &folder.Id,
|
||||
})
|
||||
for i := 0; i < 1_000_000 / 5; i++ {
|
||||
all = append(all, model.Item{
|
||||
GUID: fmt.Sprintf("f%d-i%d", k, i),
|
||||
FeedId: feed.Id,
|
||||
Title: "t",
|
||||
Date: now.Add(time.Duration(len(all)) * time.Second),
|
||||
})
|
||||
}
|
||||
}
|
||||
db.CreateItems(all)
|
||||
|
||||
for b.Loop() {
|
||||
db.MarkItemsRead(model.MarkFilter{FolderID: &folder.Id})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user