Repository navigation
Expand file tree
/
Copy pathbenchmark_test.go
More file actions
113 lines (95 loc) · 2.69 KB
/
Copy pathbenchmark_test.go
File metadata and controls
113 lines (95 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package pdf
import (
"fmt"
"os"
"testing"
)
func BenchmarkGetObject(b *testing.B) {
// Use a test file that exists in the repo
// internal/pdf is at /Users/paulvanbrouwershaven/Code/pdfsign/internal/pdf
// testfiles are at /Users/paulvanbrouwershaven/Code/pdfsign/testfiles
file := "../../testfiles/testfile12.pdf"
if _, err := os.Stat(file); os.IsNotExist(err) {
b.Skip("skipping benchmark; testfile12.pdf not found")
}
f, err := os.Open(file)
if err != nil {
b.Fatal(err)
}
defer f.Close()
info, err := f.Stat()
if err != nil {
b.Fatal(err)
}
r, err := NewReader(f, info.Size())
if err != nil {
b.Fatal(err)
}
// Find a valid object ID to resolve.
// For testfile1.pdf (produced by simple writer), object 1 usually exists.
// Or we can scan xref to find a valid one.
var traceID uint32
for id, x := range r.xref {
if x.offset > 0 {
traceID = uint32(id)
break
}
}
if traceID == 0 {
b.Fatal("no valid object found to benchmark")
}
fmt.Printf("Benchmarking resolution of Object ID: %d\n", traceID)
b.ResetTimer()
for i := 0; i < b.N; i++ {
// This should hit the cache after the first iteration
_, err := r.GetObject(traceID)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkParseAllObjects(b *testing.B) {
file := "../../testfiles/testfile12.pdf"
if _, err := os.Stat(file); os.IsNotExist(err) {
b.Skip("skipping benchmark; testfile12.pdf not found")
}
f, err := os.Open(file)
if err != nil {
b.Fatal(err)
}
defer f.Close()
info, err := f.Stat()
if err != nil {
b.Fatal(err)
}
// We want to measure parsing, so we need to run resolve() which populates cache.
// To measure repeat parsing performance, we would need to prevent caching or create new readers.
// Creating new readers involves scanning xref which is also parsing.
// Option A: Create new reader each iter (measures xref parsing + object parsing if we trigger it)
// Option B: Reuse reader but read distinct objects (only works if file is huge, eventually hits cache)
// Let's do Option A: NewReader + Resolve All Objects. This is the "Load + Verify" scenario.
b.ResetTimer()
for i := 0; i < b.N; i++ {
b.StopTimer()
f.Seek(0, 0) // Reset file cursor
b.StartTimer()
r, err := NewReader(f, info.Size())
if err != nil {
b.Fatal(err)
}
// Iterate all objects
for id, x := range r.xref {
if x.offset > 0 {
_, err := r.GetObject(uint32(id))
if err != nil {
// Some objects might be malformed or fail, but usually testfile should be clean.
// Just continue or log? Fatal for now.
// b.Fatal(err)
// Actually, ignore errors for stress testing if file has known issues,
// but testfile12 should be good.
_ = err
}
}
}
}
}