* [PATCH net-next] tools: ynl: try to avoid the very slow YAML loader
@ 2026-06-03 21:08 Jakub Kicinski
2026-06-03 22:08 ` Jacob Keller
0 siblings, 1 reply; 4+ messages in thread
From: Jakub Kicinski @ 2026-06-03 21:08 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, Jakub Kicinski,
donald.hunter
Turns out Python YAML defaults to a pure Python loader for YAML
files which is a lot slower than the C loader (using libyaml).
Try to use the C one whenever possible.
The avg time to run:
$ tools/net/ynl/pyynl/cli.py --family tc --no-schema
drops from 300+ ms to 115 ms with this change (40 samples).
We could drop the load time further to 85 ms if we "compiled"
the specs to JSON. Slightly tricky parts are that we don't
currently install the specs at all on make install, so it's
unclear where to put the conversion. Also JSON has questionable
support for comments and we need an SPDX line.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: donald.hunter@gmail.com
---
tools/net/ynl/pyynl/lib/nlspec.py | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/tools/net/ynl/pyynl/lib/nlspec.py b/tools/net/ynl/pyynl/lib/nlspec.py
index fcffeb5b7ba3..0469a0e270d0 100644
--- a/tools/net/ynl/pyynl/lib/nlspec.py
+++ b/tools/net/ynl/pyynl/lib/nlspec.py
@@ -439,6 +439,11 @@ import yaml as pyyaml
# To be loaded dynamically as needed
jsonschema = None
+ try:
+ _yaml_loader = pyyaml.CSafeLoader
+ except AttributeError:
+ _yaml_loader = pyyaml.SafeLoader
+
def __init__(self, spec_path, schema_path=None, exclude_ops=None):
with open(spec_path, "r", encoding='utf-8') as stream:
prefix = '# SPDX-License-Identifier: '
@@ -448,7 +453,7 @@ import yaml as pyyaml
self.license = first[len(prefix):]
stream.seek(0)
- spec = pyyaml.safe_load(stream)
+ spec = pyyaml.load(stream, Loader=self._yaml_loader)
self.fixed_header = None
self._resolution_list = []
@@ -464,7 +469,7 @@ import yaml as pyyaml
schema_path = os.path.dirname(os.path.dirname(spec_path)) + f'/{self.proto}.yaml'
if schema_path:
with open(schema_path, "r", encoding='utf-8') as stream:
- schema = pyyaml.safe_load(stream)
+ schema = pyyaml.load(stream, Loader=self._yaml_loader)
if SpecFamily.jsonschema is None:
SpecFamily.jsonschema = importlib.import_module("jsonschema")
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH net-next] tools: ynl: try to avoid the very slow YAML loader
2026-06-03 21:08 [PATCH net-next] tools: ynl: try to avoid the very slow YAML loader Jakub Kicinski
@ 2026-06-03 22:08 ` Jacob Keller
2026-06-03 23:35 ` Jakub Kicinski
0 siblings, 1 reply; 4+ messages in thread
From: Jacob Keller @ 2026-06-03 22:08 UTC (permalink / raw)
To: Jakub Kicinski, davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, donald.hunter
On 6/3/2026 2:08 PM, Jakub Kicinski wrote:
> Turns out Python YAML defaults to a pure Python loader for YAML
> files which is a lot slower than the C loader (using libyaml).
> Try to use the C one whenever possible.
>
> The avg time to run:
> $ tools/net/ynl/pyynl/cli.py --family tc --no-schema
> drops from 300+ ms to 115 ms with this change (40 samples).
>
> We could drop the load time further to 85 ms if we "compiled"
> the specs to JSON. Slightly tricky parts are that we don't
> currently install the specs at all on make install, so it's
> unclear where to put the conversion. Also JSON has questionable
> support for comments and we need an SPDX line.
> > Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> CC: donald.hunter@gmail.com
> ---
> tools/net/ynl/pyynl/lib/nlspec.py | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/tools/net/ynl/pyynl/lib/nlspec.py b/tools/net/ynl/pyynl/lib/nlspec.py
> index fcffeb5b7ba3..0469a0e270d0 100644
> --- a/tools/net/ynl/pyynl/lib/nlspec.py
> +++ b/tools/net/ynl/pyynl/lib/nlspec.py
> @@ -439,6 +439,11 @@ import yaml as pyyaml
> # To be loaded dynamically as needed
> jsonschema = None
>
> + try:
> + _yaml_loader = pyyaml.CSafeLoader
> + except AttributeError:
> + _yaml_loader = pyyaml.SafeLoader
> +
> def __init__(self, spec_path, schema_path=None, exclude_ops=None):
> with open(spec_path, "r", encoding='utf-8') as stream:
> prefix = '# SPDX-License-Identifier: '
> @@ -448,7 +453,7 @@ import yaml as pyyaml
> self.license = first[len(prefix):]
>
> stream.seek(0)
> - spec = pyyaml.safe_load(stream)
> + spec = pyyaml.load(stream, Loader=self._yaml_loader)
>
Hmm. I was a bit confused at first by the switch from safe_load to
load.. but we're passing Loader as _yaml_loader which will either be
CSafeLoader *or* the default SafeLoader, so we'll get the appropriate
loader equivalent to what safe_load would have done, so there's no
change. Ok
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
> self.fixed_header = None
> self._resolution_list = []
> @@ -464,7 +469,7 @@ import yaml as pyyaml
> schema_path = os.path.dirname(os.path.dirname(spec_path)) + f'/{self.proto}.yaml'
> if schema_path:
> with open(schema_path, "r", encoding='utf-8') as stream:
> - schema = pyyaml.safe_load(stream)
> + schema = pyyaml.load(stream, Loader=self._yaml_loader)
>
> if SpecFamily.jsonschema is None:
> SpecFamily.jsonschema = importlib.import_module("jsonschema")
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH net-next] tools: ynl: try to avoid the very slow YAML loader
2026-06-03 22:08 ` Jacob Keller
@ 2026-06-03 23:35 ` Jakub Kicinski
2026-06-04 0:17 ` Jacob Keller
0 siblings, 1 reply; 4+ messages in thread
From: Jakub Kicinski @ 2026-06-03 23:35 UTC (permalink / raw)
To: Jacob Keller
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
donald.hunter
On Wed, 3 Jun 2026 15:08:46 -0700 Jacob Keller wrote:
> Hmm. I was a bit confused at first by the switch from safe_load to
> load.. but we're passing Loader as _yaml_loader which will either be
> CSafeLoader *or* the default SafeLoader, so we'll get the appropriate
> loader equivalent to what safe_load would have done, so there's no
> change. Ok
Maybe I should have mentioned this in the commit msg. I was also super
confused by these APIs but IDK how much is this me not knowing Python
and how much it's special. AFAIU basically:
somewhere in pyyaml...
def safe_load(file):
return load(file, Loader=SafeLoader)
so safe_load() is just a "shorthand" for using SafeLoader, which unlike
load()s default loader doesn't allow constructing real/binary Python
objects ?
Why it doesn't default to the C one is beyond my understanding.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net-next] tools: ynl: try to avoid the very slow YAML loader
2026-06-03 23:35 ` Jakub Kicinski
@ 2026-06-04 0:17 ` Jacob Keller
0 siblings, 0 replies; 4+ messages in thread
From: Jacob Keller @ 2026-06-04 0:17 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
donald.hunter
On 6/3/2026 4:35 PM, Jakub Kicinski wrote:
> On Wed, 3 Jun 2026 15:08:46 -0700 Jacob Keller wrote:
>> Hmm. I was a bit confused at first by the switch from safe_load to
>> load.. but we're passing Loader as _yaml_loader which will either be
>> CSafeLoader *or* the default SafeLoader, so we'll get the appropriate
>> loader equivalent to what safe_load would have done, so there's no
>> change. Ok
>
> Maybe I should have mentioned this in the commit msg. I was also super
> confused by these APIs but IDK how much is this me not knowing Python
> and how much it's special. AFAIU basically:
>
This is a pyyaml issue not a generic python one I think.
> somewhere in pyyaml...
>
> def safe_load(file):
> return load(file, Loader=SafeLoader)
>
> so safe_load() is just a "shorthand" for using SafeLoader, which unlike
> load()s default loader doesn't allow constructing real/binary Python
> objects ?
load() by default uses the generic Loader that supports the full spec
and because of that is "unsafe":
https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation
Basically, loading the full YAML spec on untrusted input is unsafe since
it allows arbitrary execution.
>
> Why it doesn't default to the C one is beyond my understanding.
Right. I'm not super familiar here as to how it ends up not defaulting
to CSafeLoader, but probably its because its not always available.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-06-04 0:17 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-03 21:08 [PATCH net-next] tools: ynl: try to avoid the very slow YAML loader Jakub Kicinski
2026-06-03 22:08 ` Jacob Keller
2026-06-03 23:35 ` Jakub Kicinski
2026-06-04 0:17 ` Jacob Keller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox