podman/libpod
Paul Holzinger 0136a66a83
libpod: deduplicate ports in db
The OCICNI port format has one big problem: It does not support ranges.
So if a users forwards a range of 1k ports with podman run -p 1001-2000
we have to store each of the thousand ports individually as array element.
This bloats the db and makes the JSON encoding and decoding much slower.
In many places we already use a better port struct type which supports
ranges, e.g. `pkg/specgen` or the new network interface.

Because of this we have to do many runtime conversions between the two
port formats. If everything uses the new format we can skip the runtime
conversions.

This commit adds logic to replace all occurrences of the old format
with the new one. The database will automatically migrate the ports
to new format when the container config is read for the first time
after the update.

The `ParsePortMapping` function is `pkg/specgen/generate` has been
reworked to better work with the new format. The new logic is able
to deduplicate the given ports. This is necessary the ensure we
store them efficiently in the DB. The new code should also be more
performant than the old one.

To prove that the code is fast enough I added go benchmarks. Parsing
1 million ports took less than 0.5 seconds on my laptop.

Benchmark normalize PortMappings in specgen:
Please note that the 1 million ports are actually 20x 50k ranges
because we cannot have bigger ranges than 65535 ports.
```
$ go test -bench=. -benchmem  ./pkg/specgen/generate/
goos: linux
goarch: amd64
pkg: github.com/containers/podman/v3/pkg/specgen/generate
cpu: Intel(R) Core(TM) i7-10850H CPU @ 2.70GHz
BenchmarkParsePortMappingNoPorts-12             480821532                2.230 ns/op           0 B/op          0 allocs/op
BenchmarkParsePortMapping1-12                      38972             30183 ns/op          131584 B/op          9 allocs/op
BenchmarkParsePortMapping100-12                    18752             60688 ns/op          141088 B/op        315 allocs/op
BenchmarkParsePortMapping1k-12                      3104            331719 ns/op          223840 B/op       3018 allocs/op
BenchmarkParsePortMapping10k-12                      376           3122930 ns/op         1223650 B/op      30027 allocs/op
BenchmarkParsePortMapping1m-12                         3         390869926 ns/op        124593840 B/op   4000624 allocs/op
BenchmarkParsePortMappingReverse100-12             18940             63414 ns/op          141088 B/op        315 allocs/op
BenchmarkParsePortMappingReverse1k-12               3015            362500 ns/op          223841 B/op       3018 allocs/op
BenchmarkParsePortMappingReverse10k-12               343           3318135 ns/op         1223650 B/op      30027 allocs/op
BenchmarkParsePortMappingReverse1m-12                  3         403392469 ns/op        124593840 B/op   4000624 allocs/op
BenchmarkParsePortMappingRange1-12                 37635             28756 ns/op          131584 B/op          9 allocs/op
BenchmarkParsePortMappingRange100-12               39604             28935 ns/op          131584 B/op          9 allocs/op
BenchmarkParsePortMappingRange1k-12                38384             29921 ns/op          131584 B/op          9 allocs/op
BenchmarkParsePortMappingRange10k-12               29479             40381 ns/op          131584 B/op          9 allocs/op
BenchmarkParsePortMappingRange1m-12                  927           1279369 ns/op          143022 B/op        164 allocs/op
PASS
ok      github.com/containers/podman/v3/pkg/specgen/generate    25.492s
```

Benchmark convert old port format to new one:
```
go test -bench=. -benchmem  ./libpod/
goos: linux
goarch: amd64
pkg: github.com/containers/podman/v3/libpod
cpu: Intel(R) Core(TM) i7-10850H CPU @ 2.70GHz
Benchmark_ocicniPortsToNetTypesPortsNoPorts-12          663526126                1.663 ns/op           0 B/op          0 allocs/op
Benchmark_ocicniPortsToNetTypesPorts1-12                 7858082               141.9 ns/op            72 B/op          2 allocs/op
Benchmark_ocicniPortsToNetTypesPorts10-12                2065347               571.0 ns/op           536 B/op          4 allocs/op
Benchmark_ocicniPortsToNetTypesPorts100-12                138478              8641 ns/op            4216 B/op          4 allocs/op
Benchmark_ocicniPortsToNetTypesPorts1k-12                   9414            120964 ns/op           41080 B/op          4 allocs/op
Benchmark_ocicniPortsToNetTypesPorts10k-12                   781           1490526 ns/op          401528 B/op          4 allocs/op
Benchmark_ocicniPortsToNetTypesPorts1m-12                      4         250579010 ns/op        40001656 B/op          4 allocs/op
PASS
ok      github.com/containers/podman/v3/libpod  11.727s
```

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
2021-10-27 18:59:56 +02:00
..
common
define Pod Volumes From Support 2021-10-01 14:09:11 -04:00
driver bump go module to v3 2021-02-22 09:03:51 +01:00
events standardize logrus messages to upper case 2021-09-22 15:29:34 -04:00
layers
linkmode
lock standardize logrus messages to upper case 2021-09-22 15:29:34 -04:00
logs standardize logrus messages to upper case 2021-09-22 15:29:34 -04:00
network Document to not set K8S envars for CNI 2021-10-26 16:11:46 +02:00
plugin bump go module to v3 2021-02-22 09:03:51 +01:00
shutdown Fix CI flake on time of shutdown for API service 2021-10-12 09:53:19 -07:00
boltdb_state.go Ensure pod ID bucket is properly updated on rename 2021-09-28 14:12:18 -04:00
boltdb_state_internal.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
boltdb_state_linux.go standardize logrus messages to upper case 2021-09-22 15:29:34 -04:00
common_test.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
container.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
container_api.go Ensure `podman ps --sync` functions 2021-10-06 11:19:32 -04:00
container_commit.go standardize logrus messages to upper case 2021-09-22 15:29:34 -04:00
container_config.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
container_copy_linux.go Don't use docker/pkg/archive, use containers/storage/pkg/archive 2021-10-14 10:28:42 -04:00
container_exec.go libpod: add execSessionNoCopy 2021-09-29 13:44:55 +02:00
container_graph.go implement init containers in podman 2021-08-04 14:14:36 -05:00
container_graph_test.go bump go module to v3 2021-02-22 09:03:51 +01:00
container_inspect.go Merge pull request #11686 from cdoern/podDeviceOptions 2021-10-01 10:53:14 -04:00
container_internal.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
container_internal_linux.go Update vendor github.com/opencontainers/runtime-tools 2021-10-25 16:50:45 -04:00
container_internal_linux_test.go feat: add localhost into hosts if the networking mode is not host 2021-09-04 18:24:41 +04:30
container_internal_test.go
container_linux.go
container_log.go logging: new mode -l passthrough 2021-09-27 12:07:01 +02:00
container_log_linux.go Fix a few problems in 'podman logs --tail' with journald driver 2021-10-26 12:18:57 -04:00
container_log_unsupported.go Switch eventlogger to journald by default 2021-08-23 17:59:42 -04:00
container_path_resolution.go libpod: do not call (*container).Config() 2021-09-28 17:18:02 +02:00
container_stat_linux.go podman cp: evaluate symlink correctly when copying from container 2021-03-09 10:45:15 +01:00
container_top_linux.go Bump github.com/containers/psgo from 1.5.2 to 1.6.0 2021-09-10 15:23:43 +02:00
container_validate.go implement init containers in podman 2021-08-04 14:14:36 -05:00
diff.go Implement SD-NOTIFY proxy in conmon 2021-08-20 11:12:05 +02:00
events.go standardize logrus messages to upper case 2021-09-22 15:29:34 -04:00
healthcheck.go sync container state before reading the healthcheck 2021-09-22 17:40:16 +02:00
healthcheck_linux.go bump go module to v3 2021-02-22 09:03:51 +01:00
info.go [NO NEW TESTS NEEDED] Fix off-by-one index comparision (reported by LGTM) 2021-10-25 10:52:01 +02:00
kube.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
mounts_linux.go
networking_linux.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
networking_linux_test.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
networking_slirp4netns.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
oci.go Fix resize race with podman exec -it 2021-06-16 16:43:30 +02:00
oci_attach_linux.go libpod: fix race when closing STDIN 2021-10-06 17:51:07 +02:00
oci_conmon.go
oci_conmon_exec_linux.go libpod: fix race when closing STDIN 2021-10-06 17:51:07 +02:00
oci_conmon_linux.go Warn if podman stop timeout expires that sigkill was sent 2021-10-08 07:06:37 -04:00
oci_missing.go Fix resize race with podman exec -it 2021-06-16 16:43:30 +02:00
oci_util.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
options.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
pod.go codespell code 2021-10-12 16:44:25 -04:00
pod_api.go Add --time out for podman * rm -f commands 2021-10-04 07:07:56 -04:00
pod_internal.go standardize logrus messages to upper case 2021-09-22 15:29:34 -04:00
pod_status.go bump go module to v3 2021-02-22 09:03:51 +01:00
pod_top_linux.go bump go module to v3 2021-02-22 09:03:51 +01:00
reset.go Add --time out for podman * rm -f commands 2021-10-04 07:07:56 -04:00
runtime.go runtime: check for pause pid existence 2021-10-27 11:24:50 +02:00
runtime_cstorage.go Storage can remove ErrNotAContainer as well 2021-09-29 10:12:49 -04:00
runtime_ctr.go Update vendor github.com/opencontainers/runtime-tools 2021-10-25 16:50:45 -04:00
runtime_img.go Add --time out for podman * rm -f commands 2021-10-04 07:07:56 -04:00
runtime_migrate.go standardize logrus messages to upper case 2021-09-22 15:29:34 -04:00
runtime_pod.go Add --time out for podman * rm -f commands 2021-10-04 07:07:56 -04:00
runtime_pod_linux.go Remove infra ID from DB before removing containers 2021-10-20 14:56:22 -04:00
runtime_renumber.go bump go module to v3 2021-02-22 09:03:51 +01:00
runtime_volume.go Add --time out for podman * rm -f commands 2021-10-04 07:07:56 -04:00
runtime_volume_linux.go Remove a volume with --force if container is running 2021-10-11 15:02:04 -04:00
state.go Rewrite Rename backend in a more atomic fashion 2021-03-02 13:30:28 -05:00
state_test.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
stats.go stats: detect containers restart 2021-09-10 09:03:10 +02:00
storage.go Storage can remove ErrNotAContainer as well 2021-09-29 10:12:49 -04:00
util.go libpod: deduplicate ports in db 2021-10-27 18:59:56 +02:00
util_linux.go standardize logrus messages to upper case 2021-09-22 15:29:34 -04:00
util_linux_test.go
util_test.go bump go module to v3 2021-02-22 09:03:51 +01:00
volume.go volumes: Add support for exporting volumes to external tar 2021-08-23 20:42:41 +05:30
volume_inspect.go bump go module to v3 2021-02-22 09:03:51 +01:00
volume_internal.go Support size and inode options on builtin volumes 2021-08-02 10:32:45 -04:00
volume_internal_linux.go Support size and inode options on builtin volumes 2021-08-02 10:32:45 -04:00