xlat performance / "compile time" parsing?

Phil Mayers p.mayers at imperial.ac.uk
Sat Oct 27 16:59:22 CEST 2012


I recently made some changes to our FreeRADIUS logging config, inspired 
by Matthew Newton's creative use of linelog as discussed on the -users 
list. The config uses a wrapping unlang policy, along with quite a bit 
of conditional expansion.

Since deploying it, I've noticed the CPU use of our FreeRADIUS server 
has jumped, at lot. Hotspot profiling with "oprofile" tells me that 
almost all the time is being spent inside a few critical functions:

  radius_xlat
  rad_copy_variable
  radius_evaluate_condition

I've stared at the code for the first two a bit, and I think I 
understand why it's so expensive; it essentially parses the input string 
one character at a time, every time, and in the case of a conditional 
attribute, it walks over the input twice (or more).

A roughly similar thing happens wth radius_evaluate_condition.

This set me to wondering about some kind of parser cache. The idea would 
be that a string like:

"var %{%{foo}:-%{%{bar}:-baz}}"

...would be parsed into some kind of linked-list / tree, like so:

v[0].type = LITERAL
v[0].value = "var "
v[1].type = CONDITIONAL
v[1].value = struct {
   left.type = EXPANSION
   left.value = "foo"
   right.type = CONDITIONAL
   right.value = struct {
     left.type = EXPANSION
     left.value = "bar"
     right.type = LITERAL
     right.value = "baz"
   }
}

The parsing would be done transparently by radius_xlat the first time it 
saw an input template, and cached for the lifetime of the process - 
though I haven't yet figured out how to do this without locking. Once 
parsed, the expansion function should be both very simple, and very fast.

If we wanted to go even further, the EXPANSION values could be the 
attribute number rather than name, but I am having trouble reasoning out 
whether this might lead to problems with changing xlat or attribute 
registrations e.g. on HUP or similar.

Something similar could be done for radius_evaluate_condition, except 
it's even easier there - only the unlang code calls uses conditions, so 
we can just compile it - no need to transparently convert the string.

Before I embark on this to see if it helps - is this even a reasonable 
approach?

Cheers,
Phil


More information about the Freeradius-Devel mailing list