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

Bytewise crc32 #41

Merged
merged 3 commits into from
Sep 8, 2022
Merged

Bytewise crc32 #41

merged 3 commits into from
Sep 8, 2022

Conversation

k-danil
Copy link
Contributor

@k-danil k-danil commented Sep 5, 2022

Good day!

This pull request introduce bytewise crc32 calculation instead of current bitwise. Code based on VLC implementation, but instead per-object table generation, it use static crc32 table (+1kb additional lifetime memory use but no recalculations and reallocations) .
Current:

Benchmark_updateCRC32/Calc_PAT_crc32
Benchmark_updateCRC32/Calc_PAT_crc32-8         	 9470034	       122.9 ns/op	       0 B/op	       0 allocs/op
Benchmark_updateCRC32/Calc_PMT_crc32
Benchmark_updateCRC32/Calc_PMT_crc32-8         	 4010506	       283.4 ns/op	       0 B/op	       0 allocs/op

Introduced in this patch:

Benchmark_updateCRC32/Calc_PAT_crc32_precomputed
Benchmark_updateCRC32/Calc_PAT_crc32_precomputed-8         	71367823	        16.79 ns/op	       0 B/op	       0 allocs/op
Benchmark_updateCRC32/Calc_PMT_crc32_precomputed
Benchmark_updateCRC32/Calc_PMT_crc32_precomputed-8         	18918052	        54.75 ns/op	       0 B/op	       0 allocs/op

Test's and benchmarks based on real TS headers. Old implementation renamed and kept in file for comparison sake, you can remove it safely.

Copy link
Owner

@asticode asticode left a comment

Choose a reason for hiding this comment

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

Nice PR!

I'd rather see it organized differently, I've made comments.

crc32.go Outdated
*/
// https://github.com/videolan/vlc/blob/master/modules/mux/mpeg/ps.c

var tableCRC32 = [256]uint32{
Copy link
Owner

Choose a reason for hiding this comment

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

Could you create a command to generate this table in a separate go file?

  1. Add an internal/cmd/crc32_table folder
  2. Add a main.go in it that would create a crc32_table.go with only the tableCRC32 variable in it.
  3. Also make sure to add // Code generated by astits. DO NOT EDIT. a the top of this file before the package name

That way we have a command to generate the file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All done! This is my first attempt with code generation, so it may be kind of ugly

crc32.go Outdated

// computeCRC32 computes a CRC32
// https://stackoverflow.com/questions/35034042/how-to-calculate-crc32-in-psi-si-packet
func computeCRC32old(bs []byte) uint32 {
Copy link
Owner

Choose a reason for hiding this comment

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

You can remove the old implementation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

crc32_test.go Outdated
},
}

func Benchmark_updateCRC32(b *testing.B) {
Copy link
Owner

Choose a reason for hiding this comment

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

No need to keep the benchmark here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

crc32_test.go Outdated

func Test_updateCRC32(t *testing.T) {

for _, test := range tests {
Copy link
Owner

Choose a reason for hiding this comment

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

You can remove this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

crc32_test.go Outdated
}

for _, test := range tests {
t.Run(test.name+" precomputed", func(t *testing.T) {
Copy link
Owner

Choose a reason for hiding this comment

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

You can remove the " precomputed" here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

…lation func and corresponding tests/benchmarks.
crc32.go Outdated
@@ -4,22 +4,17 @@ const (
crc32Polynomial = uint32(0xffffffff)
)

// computeCRC32 computes a CRC32
// https://stackoverflow.com/questions/35034042/how-to-calculate-crc32-in-psi-si-packet
// this solution based on vlc implementation + static crc table (1kb additional memory on start, without reallocations)
Copy link
Owner

Choose a reason for hiding this comment

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

Could you put this comment above updateCRC32 instead ?

And could you replace it with :

// Based on VLC implementation using a static CRC table (1kb additional memory on start, without 
// reallocations): https://github.com/videolan/vlc/blob/master/modules/mux/mpeg/ps.c

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

)

const (
disclaimer = `// Code generated by astits. DO NOT EDIT`
Copy link
Owner

Choose a reason for hiding this comment

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

Could you update the disclaimer to // Code generated by astits using internal/cmd/crc32_table. DO NOT EDIT

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

)

func main() {
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC|os.O_SYNC, 0644)
Copy link
Owner

Choose a reason for hiding this comment

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

Could you use os.Create() instead ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this approach is much neater, thanks!

func main() {
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC|os.O_SYNC, 0644)
if err != nil {
panic(err)
Copy link
Owner

Choose a reason for hiding this comment

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

Could you use log.Fatal(err) instead ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

doOrPanic(fmt.Fprintf(w, "\n%s", `}`))
}

func doOrPanic(_ int, err error) {
Copy link
Owner

Choose a reason for hiding this comment

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

Could you rename this to write() and instead of panic(err) do log.Fatal(err) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On my opinion it is more general purpose function then just writer (and it's not even write, just crash if something go wrong). Maybe 'try()' will be more appropriate name? Anyway, i done as you ask

@asticode asticode merged commit b2efeb7 into asticode:master Sep 8, 2022
@asticode
Copy link
Owner

asticode commented Sep 8, 2022

fyi I've created a v1.11.0 tag

thanks for the PR! ❤️

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.

2 participants