Skip to content

Add per-node setValue or setInstance method to improve performance for large schemas #46

@StacyMader

Description

@StacyMader

Currently, Jedison only provides a top-level setValue method that recursively walks the entire schema tree to apply values. For schemas with multiple nested anyOf combinators, this can cause significant performance overhead, especially in arrays or tables with many rows, because every node is evaluated recursively, even when only a single node needs updating.

Could there be a per-node setValue method that allows updating a specific node directly? This would avoid full recursion, skip unnecessary anyOf evaluations, and improve both speed and memory usage when importing or updating large datasets.

Hopefully, this example demonstrates the issue.

<!DOCTYPE html>
<html data-bs-theme="auto">
<head>
    <meta charset="utf-8"/>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jedison@latest/dist/umd/jedison.umd.js"></script>
</head>
<body>
<div class="container">
    <h2 class="mt-5">Jedison Performance Test</h2>
    <div class="mt-3" id="jedison-container-slow"></div>
    <div class="mt-5" id="jedison-container-fast"></div>
</div>

<script>
  // Generate 300 sample observations with targets and apollo
  const sampleObservations = Array.from({ length: 300 }, (_, i) => ({
    observer: `Observer ${i+1}`,
    location: `Location ${i+1}`,
    date: new Date(2026, 3, (i % 28) + 1).toISOString().split('T')[0],
    targets: i % 2 === 0
      ? { type: "PlantTarget", species: `Plant Species ${i+1}`, count: Math.floor(Math.random() * 20) }
      : { type: "AnimalTarget", species: `Animal Species ${i+1}`, behavior: "Active" },
    apollo: i % 3 === 0
      ? { version: "v1", notes: "Apollo test 1" }
      : { version: "v2", notes: "Apollo test 2", extra: "Extra info" }
  }));

  // ----------- Version A: with second anyOf (slow) -----------------
  console.time("load-with-anyof");

  const jedisonSlow = new Jedison.Create({
    container: document.querySelector('#jedison-container-slow'),
    theme: new Jedison.ThemeBootstrap5(),
    schema: {
      "title": "UW observation (with apollo anyOf)",
      "type": "object",
      "properties": {
        "project": { "type": "string", "description": "Project name" },
        "observations": {
          "type": "array",
          "title": "Observations",
          "default": sampleObservations,
          "items": {
            "type": "object",
            "properties": {
              "observer": { "type": "string" },
              "location": { "type": "string" },
              "date": { "type": "string", "format": "date" },
              "targets": {
                "type": "object",
                "anyOf": [
                  {
                    "title": "PlantTarget",
                    "type": "object",
                    "properties": {
                      "type": { "const": "PlantTarget" },
                      "species": { "type": "string" },
                      "count": { "type": "integer", "minimum": 0 }
                    },
                    "required": ["type","species","count"]
                  },
                  {
                    "title": "AnimalTarget",
                    "type": "object",
                    "properties": {
                      "type": { "const": "AnimalTarget" },
                      "species": { "type": "string" },
                      "behavior": { "type": "string" }
                    },
                    "required": ["type","species","behavior"]
                  }
                ]
              },
              "apollo": {
                "anyOf": [
                  {
                    "title": "Apollo v1",
                    "type": "object",
                    "properties": {
                      "version": { "const": "v1" },
                      "notes": { "type": "string" }
                    },
                    "required": ["version","notes"]
                  },
                  {
                    "title": "Apollo v2",
                    "type": "object",
                    "properties": {
                      "version": { "const": "v2" },
                      "notes": { "type": "string" },
                      "extra": { "type": "string" }
                    },
                    "required": ["version","notes"]
                  }
                ]
              }
            },
            "required": ["observer","location","date","targets","apollo"]
          }
        }
      }
    }
  });

  console.timeEnd("load-with-anyof");

  // ----------- Version B: remove second anyOf (fast) -----------------
  console.time("load-without-anyof");

  const jedisonFast = new Jedison.Create({
    container: document.querySelector('#jedison-container-fast'),
    theme: new Jedison.ThemeBootstrap5(),
    schema: {
      "title": "UW observation (apollo single schema)",
      "type": "object",
      "properties": {
        "project": { "type": "string", "description": "Project name" },
        "observations": {
          "type": "array",
          "title": "Observations",
          "default": sampleObservations,
          "items": {
            "type": "object",
            "properties": {
              "observer": { "type": "string" },
              "location": { "type": "string" },
              "date": { "type": "string", "format": "date" },
              "targets": {
                "type": "object",
                "anyOf": [
                  {
                    "title": "PlantTarget",
                    "type": "object",
                    "properties": {
                      "type": { "const": "PlantTarget" },
                      "species": { "type": "string" },
                      "count": { "type": "integer", "minimum": 0 }
                    },
                    "required": ["type","species","count"]
                  },
                  {
                    "title": "AnimalTarget",
                    "type": "object",
                    "properties": {
                      "type": { "const": "AnimalTarget" },
                      "species": { "type": "string" },
                      "behavior": { "type": "string" }
                    },
                    "required": ["type","species","behavior"]
                  }
                ]
              },
              "apollo": {
                "title": "Apollo",
                "type": "object",
                "properties": {
                  "version": { "type": "string" },
                  "notes": { "type": "string" }
                },
                "required": ["version","notes"]
              }
            },
            "required": ["observer","location","date","targets","apollo"]
          }
        }
      }
    }
  });

  console.timeEnd("load-without-anyof");

</script>
</body>
</html>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions