---
title: "Computed-column UDF calls: insert, read, recompute, update"
description: "Reduced run, 1000 rows. Insert 1000 UDF calls, stored read 0, full recompute 1000, 100-row update 100. No hosted LLM. Intel(R) Xeon(R) Processor, 4 cores, 15.6 GB, Linux 6.12.94+, Python 3.12.3, pixeltable 0.7.21."
url: "https://www.pixeltable.com/benchmarks/computed-column-udf-calls"
updated: "2026-10-28"
doc: "https://docs.pixeltable.com/datastore/computed-columns"
---

# Computed-column UDF calls: insert, read, recompute, update

On 1000 rows a local stand-in UDF ran 1000 times on insert, 0 times when a select read the stored column, 1000 times on recompute_columns, and 100 times when 100 titles changed. No hosted LLM was called, and the page publishes call counts, not a cost. 1,000,000 rows were not run.

Updated: 2026-10-28

## How to run

- `python benchmarks/run.py --write`
- `Or: PIXELTABLE_HOME=$(mktemp -d) python benchmarks/scenarios/udf_calls.py --rows 1000 --changed 100 --out /tmp/udf.json --scale reduced`

## Results

Insert: 1000 UDF calls, 0.089 s wall, 0.081 s CPU. Stored read: 0 UDF calls, 0.016 s wall, 0.014 s CPU.

Full recompute: 1000 UDF calls, 0.087 s wall, 0.079 s CPU. Update of 100 rows: 100 UDF calls, 0.022 s wall, 0.014 s CPU.

| Measure | Value |
| --- | --- |
| Rows | 1000 |
| Insert UDF calls | 1000 |
| Stored-read UDF calls | 0 |
| Full-recompute UDF calls | 1000 |
| Subset-update UDF calls | 100 |
| Hosted LLM called | no |

## Methods

- **Scale of this page:** reduced: 1000 rows, change 100
- **Full scale (not run here):** 1,000,000 rows. The suite flag is --rows 1000000.
- **UDF:** fake_llm in benchmarks/udfs.py. Writes a counter file. Returns the first 24 characters. Not an API call.
- **Stored read:** select of the computed column after insert. It reads the stored values, so it is expected to call the UDF zero times.
- **Machine:** Intel(R) Xeon(R) Processor, 4 cores, 15.6 GB, Linux 6.12.94+, Python 3.12.3, pixeltable 0.7.21
- **Recorded:** 2026-10-28, command python benchmarks/run.py --write

## Limitations

- No hosted model ran. Call counts measure when Pixeltable runs the UDF, not GPT latency or price.
- Each step ran once, with no warmup, so every time is one sample. scripts/release-bench repeats its runs.
- 1,000,000 rows were not run.
- File I/O inside the stand-in UDF is part of the wall time. A real HTTP client would look different.

## Where Pixeltable fits

If you want to fire a new HTTP call on every read, Pixeltable is the wrong tool. A computed column runs when its inputs change, and a read returns the stored value. That is what this page counted.

```python
import pixeltable as pxt
from pixeltable.functions.openai import chat_completions

TableModel = pxt.model_base()

class Notes(TableModel, name='notes'):
    text: pxt.String
    summary = chat_completions(
        messages=[{'role': 'user', 'content': text}],
        model='gpt-4o-mini',
    ).choices[0].message.content
```

## Questions

### Does reading a computed column call the UDF again? {#faq-1}

No. A select reads the stored value: 0 UDF calls on this run. The UDF runs on insert, on recompute_columns (1000 calls), and for the rows an update changes (100 calls).

## Related

- [Incremental recompute vs full reindex](https://www.pixeltable.com/benchmarks/incremental-recompute-vs-full-reindex)
- [How do I add computed columns with LLM calls?](https://www.pixeltable.com/learn/how-to/add-computed-columns-with-llm-calls)

Docs: https://docs.pixeltable.com/datastore/computed-columns
