When you do...
createInstanceFromElement(
<resistor name="R1" resistance="10k" footprint="0402" />
)...you're creating a new Resistor class instance.
Everything you create in React becomes a class instance.
A project contains react elements and class instances that are added to it:
const project = new Project()
project.add(
<board width="10mm" height="10mm">
<resistor name="R1" resistance="10k" footprint="0402" />
</board>
)when you call project.render(), the project will go through a series of
rendering phases. You can see all the render phases in the Renderable class
The render phases are executed in the order in that file. Each render phase has a specific purpose.
For each render phase, every single class instance in the project gets a call
to the doInitial* method for each render phase (if it's defined for the class)
For example, one of the first render phases is SourceRender. This is where
source_* circuit json/soup elements are
added to the projects output.
The output is stored inside project.db, it's basically an array of circuit
json elements, but it has a bunch of utility methods added to it that make it
easier to work with. Here's an example of inserting a new source_component:
class Resistor extends NormalComponent<typeof resistorProps> {
doInitialSourceRender() {
this.project.db.source_component.insert({
ftype: "simple_resistor",
name: "R1",
manufacturer_part_number: "1234",
supplier_part_numbers: ["12345"],
})
}
}There are other things that happen for render phases, for example, when a
component is removed the remove* method is called in order for each render
phase e.g. removeSourceRender
After all the render phases are complete, you can get the full circuit json/soup
by calling project.getCircuitJson() or project.getSoup()
You can use bun run start:benchmarking to debug the performance of core. The video below
takes you through each step from creating benchmarking circuits, to using chrome dev tools
to see the time spent per function call, to making changes and seeing the result
Most performance issues are due to "some dumb thing", not fundamentally time-consuming algorithms.
Screenshare.-.2025-05-19.9_48_25.AM.mp4
Complex algorithms like the autorouter, pcb packing, schematic trace solving etc. have JSON inputs that can be copied into their respective debuggers, which are hosted on web pages. To get debug inputs for these algorithms:
- Find the relevant function call to the algorithm, e.g. you might find that
Group_doInitialSchematicTraceRender.tsis calling the schematic-trace-solver - Set
export DEBUG=Group_doInitialSchematicTraceRenderin your terminal, this will enable logging of debug files and messages. TheDEBUGenvironment variable should be set to whateverdebugOutputyou're trying to enable. - Run a test that reproduces the issue you're trying to debug, e.g.
bun run test/repros/repro50-rp2040-decoupling-capacitors.test.ts - In the terminal, you'll see that the relevant inputs to the algorithms are
written to the
debug-outputdirectory.
➜ core git:(algo-inputs) bun test tests/repros/repro50-rp2040-decoupling-capacitors.test.tsx
bun test v1.2.21 (7c45ed97)
✓ repro50: rp2040 decoupling capacitors [4861.61ms]
Writing debug output to debug-output/packInput-circuitjson-unnamed_board1.json
Writing debug output to debug-output/packInput-unnamed_board1.json
- Copy that input JSON and paste it into the relevant debugger, e.g. schematic-trace-solver paste input web debugger