Possible memory leak in ajv.compile
See original GitHub issueWhat version of Ajv are you using?
8.1.0, 8.6.2
Does the issue happen if you use the latest version? Yes
Ajv options object:
{allErrors: true}
Description
As per the issue reference https://github.com/ajv-validator/ajv/issues/1221, we have to use ajv.compile
to validate meta schema for a custom keyword, because ajv.validateSchema
is not performing it.
While doing so, its observed a possible memory leak in ajv.compile
method. On frequent calling of ajv.compile
on the same schema object keep increasing the memory usage. Even ajv.removeSchema
does not clear up the cache.
Code
const Ajv = require('ajv');
const ajv = new Ajv({allErrors: true});
ajv.addKeyword({
keyword: "range",
type: "number",
compile([min, max], parentSchema) {
return (data) => data > min && data < max
},
errors: false,
metaSchema: {
// schema to validate keyword value
type: "array",
items: [{type: "number"}, {type: "number"}],
minItems: 2,
additionalItems: false,
},
});
const schema = {
$id: '/our/schema',
type: "object",
properties: {
foo: {
type: "number",
range: [6, 1]
},
bar: {
type: "number",
range: [1, 5],
}
},
required: ["foo"],
additionalProperties: false
}
const run = () => {
try {
ajv.compile(schema)
} catch (error) {
console.error("Ajv schema is invalid", error)
} finally {
ajv.removeSchema(schema.$id)
}
ajv.validate(schema, { foo: 7, bar: 2 })
ajv.validate(schema, { foo: 1, bar: 4 })
console.log(Math.ceil(process.memoryUsage().heapUsed / 1024) + "KB")
}
for(let i=0; i < 10; i++) {
run();
}
Its observe that memory usage is increased linearly, tested it for longer time and it end up filling GBs of memory.
Possible causes
- It seesm
ajv.compile
is not recognizing the same schema object - And
ajv.removeSchema
is not clearing up the cache properly
A working example of the code can be tested here.
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (3 by maintainers)
Top Results From Across the Web
Ajv Compile - Memory Leak - RunKit
Ajv Compile - Memory Leak ; 1. const Ajv = require('ajv'); ; 2. ; 3. const ajv = new Ajv({allErrors: true}); ;...
Read more >Isolating and fixing a memory leak in a real Node.js web ...
A quick search revealed issues and articles discussing some unexpected behavior of the library that could lead to memory-leak-like behavior.
Read more >Ajv Version 7, Big changes and improvements
There are 2 possible approaches: 1. Compile schemas either at start time or on demand, lazily, and manage how validation functions are re-used ......
Read more >Managing schemas - Ajv JSON schema validator
There are several approaches to manage compiled schemas. # Standalone validation code. The motivation to pre-compile schemas: faster startup times; lower memory ......
Read more >Apache 2.4 Change Log
Apache Lounge changes: *) VS17 download available - Announcement *) VS17 ... [Armin Abfalterer a.abfalterer gmail.com ] *) mod_ssl: Fix memory leak in ......
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
#1221 is not an issue to be resolved, it’s a limitation that is very unlikely to be removed.
You don’t want to just validate the schema - you want to confirm that it will compile, and the only way to do it is to compile it - it’s the same as compilers work - 1) analyse and validate the syntax (that’s what validateSchema does), 2) process semantics and convert it into the executable code. The first cannot do what the second does, nor it can guarantee that the second would succeed.
So, you need to do two things:
This way you can get what you need ensuring that no memory leaks happen, because the whole ajv instance (the second one) would be garbage collected. Does it make sense?
You just need to make sure that the second instance is created with meta: false and validateSchema: false options (see the docs). Or if performance is not a concern, you could just use one ajv instance and dispose of it every time.
@epoberezkin For now we fixed that behaviour to make sure we don’t compile (validate meta schema) more than once for any schema in the application. But if that would get difficult in future (considering extensibility of application) then will try usage that approach you suggested. To create new Ajv instance for this task so it could be garbage collected.