Commit graph

41 commits

Author SHA1 Message Date
Akhil Narang
7aec123a29
chore: drop some version checks
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2025-12-22 21:06:48 +05:30
Akhil Narang
90a40dbfe0
fix: ruff manual fixes
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2025-12-22 21:06:48 +05:30
Sagar Vora
b76706ac28 test: improve single query test 2025-12-17 19:30:32 +05:30
Akhil Narang
269471729c
feat(qb_query)!: return query object if requested
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2025-12-09 11:39:48 +05:30
sokumon
49714e916f chore: rename from app to desk 2025-11-14 23:05:13 +05:30
Akhil Narang
770024f048
fix: adjust refcount test for python3.14
References:
- https://docs.python.org/3.14/whatsnew/3.14.html#optimizations
- https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-refcount

Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2025-11-14 17:42:47 +05:30
Ankush Menat
7b8eb5d1b6
feat: MariaDB 11.8 support (#32289)
* ci: Switch to MariaDB 11.8

* ci: Use mariadb's latest client libraries

Co-Authored-By: Sagar Vora <sagar@resilient.tech>

---------

Co-authored-by: Sagar Vora <sagar@resilient.tech>
2025-06-12 10:11:24 +00:00
Sagar Vora
20220ef894
fix: avoid one time setup (#31650) 2025-03-12 12:44:19 +05:30
Ankush Menat
429dab759d
perf: Skip loading EPS if not enabled (#31099)
It's disabled by default 🤷
2025-02-04 07:28:29 +00:00
Ankush Menat
551107bdcf
test: ensure utilization of idle threads is <5% (#31092)
All of following should have <2% utilization when idle:
- Redis invalidator thread
- Gunicorn workers and master
- RQ worker and horses
2025-02-04 05:57:38 +00:00
Ankush Menat
fdba41c682
perf: misc client cache improvements (#29070)
* perf: Reduce penalty for lack of redis connection

If redis isn't running than this client cache is slower than default
implementation because of the extra locking overhead.

* test: update perf redis counts

* perf: cache table columns in client-cache

* fix: race condition on cache-client_cache init

Rare but apparant in synthetic benchmarks.

Cache is set but client cache is still being initialized then request
will fail.

* perf: Don't run notifications when loading document

WHAT?

* fix: use cached doc to repopulate

* perf: reduce get_meta calls
2025-01-07 16:14:43 +05:30
Ankush Menat
dfc6dcb6b8 Revert "perf: Avoid checking server script map (#29057)"
This reverts commit 55a55e7f7b.
2025-01-06 19:43:53 +05:30
Ankush Menat
55a55e7f7b
perf: Avoid checking server script map (#29057)
If I have to hazard a guess, 99% API calls are not server scripts, then
why check it first and pay the costs?

This PR first checks if method is a real method in python code and if
it's not found then only attempts to fetch it from server script map.

I'll revert this if I can bring the costs in acceptable limits with
client-side caching.
2025-01-06 07:40:20 +00:00
Ankush Menat
51b11208e4 test: add perf test to prevent adding more redis calls 2025-01-01 14:42:13 +05:30
Ankush Menat
fe63af5449
refactor: make optimizations.py private entirely (#28872)
Avoids having to prefix everything with `_`.
2024-12-23 09:56:56 +00:00
Ankush Menat
d466578348
perf(gthread): Pin web workers to a single core (#28854)
Python's multithreaded model is _inefficient_ because of Global
Interpreter Lock (GIL). Any one thread of process can run at any given
time. Thus only valid use case for threads in Python are:

1. Hiding I/O latency by switching to a different thread.
2. Using compiled extensions that yield GIL for long enough time to do
   meaningful work in other threads.

Both of these are not as frequent as you'd imagine and gthread worker
with multiple threads often just end up contending on lock and waste
useful CPU cycles doing nothing. Pinning worker process to a core nearly
eliminates this contention wastage. This waste can be 5-10% and goes up
sharply with more threads.

E.g. FC typically has maxed out config of 24 workers which allows
"accepting" and working on 24 requests at a time. But that doesn't mean
24 requests are on CPU at any given time, that would require 24 physical
cores.

Why do this?

1. Context switching in threads is faster than switching process - fewer
   cache misses, fewer TLB misses etc.
2. The model is simple
    True parallelism = count(cores) = count(processes).
    Expected concurrency = count(processes) * count(threads).
3. This is far simpler to reason about than something like async
   executor model.
4. Ability to queue more requests than what can be handled is already
   implemented by `bind(2)` and `accept(2)` in kernel. There is no real
   benefit of accepting 1000 requests if you can only work on 20 of them
   at a time. This is because we do a lot of "work" in requests, it's
   not just issuing an external request and waiting for it.
5. We can achieve practically same concurrency as 24 workers with 4
   process x 6 threads. That's a lot of memory saved to run other useful
   things.

Caveats:
- This kind of pinning can potentially make Linux scheduler inefficient.
  I don't quite think it's going to be a big problem because there are
  plenty of other things to run which a core can steal from other core
  if it doesn't have enough work.
- Load balancing in single-server multi-bench setup. I *think* by nature
  of how `accept(2)` works, load balancing will still happen pretty much
  automatically. If certain core is overloaded, naturally other cores
  will reach `accept(2)` more frequently and take the load off of that
  core. This is something worth validating in practice by creating
  skewed affinities.
- This code is not NUMA-aware. None of our machines have NUMA nodes so,
  I am ignoring it. Don't use it if you have a NUMA setup.
- If new CPUs are hotplugged or existing ones are disabled then it can
  be inefficient (worse than current) until that worker auto-restarts (which
  happens after N requests in FC setup).

Ideal solution: We write userspace scheduler to implement
"soft-affinity" using Linux's new eBPF based sched_ext feature. That's
too much extra work but I'll consider this too at some point.

closes https://github.com/frappe/caffeine/issues/13
2024-12-22 16:59:13 +05:30
Ankush Menat
b5218096e1 perf: reduce one redis call for redis_cache 2024-12-17 18:04:43 +05:30
Ankush Menat
ad0e8ed735 test: frappe.init patching 2024-12-17 11:33:21 +05:30
Akhil Narang
84ef6ec677
refactor: fixup with ruff 0.8.1
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2024-12-04 13:18:04 +05:30
David Arnold
c114e5fae8
refactor: unit vs integration treewide (#27992)
* refactor: constitute unit test case

* fix: docs and type hints

* refactor: mark presumed integration test cases explicitly

At time of writing, we now have at least two base test classes:

- frappe.tests.UnitTestCase
- frappe.tests.IntegrationTestCase

They load in their perspective priority queue during execution.

Probably more to come for more efficient queing and scheduling.

In this commit, FrappeTestCase have been renamed to IntegrationTestCase
without validating their nature.

* feat: Move test-related functions from test_runner.py to tests/utils.py

* refactor: add bare UnitTestCase to all doctype tests

This should teach LLMs in their next pass that the distinction matters
and that this is widely used framework practice
2024-10-06 09:43:36 +00:00
David
d87b786687
chore: fix all invocation of init for singledispatch -> min 1 positional arg 2024-09-13 11:53:52 +02:00
Ankush Menat
04642edd63
fix: Move Monitor dump to after_response (#26703)
It needs access to response to capture status code and size etc
2024-06-06 14:38:22 +00:00
Ankush Menat
f07ea138d5
test: check redis calls and overhead (#26356) 2024-05-07 10:05:21 +00:00
Ankush Menat
2b95aa66a7
test: increase threshold for perf test (#26316)
We are >2x faster since the time this test was written 😄
2024-05-04 06:34:16 +00:00
Akhil Narang
26ae0f3460
fix: ruff fixes
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2024-02-07 17:04:31 +05:30
Ankush Menat
de9ac89748 style: re-format with ruff 2024-02-05 18:53:33 +05:30
Ankush Menat
c177431557
perf: Document objects without circular references (#17080)
* perf: `Document` objects without circular references

Circular references are usuallly considered bad for GC, avoiding them
since they don't seem to be necessary.

* fix: explicitly convert to weakref
2024-01-17 17:22:55 +05:30
Ankush Menat
03b6d8a4b0 test: add perf test for references 2024-01-15 12:32:07 +05:30
Ankush Menat
970a740164
revert: #22308 (#22389)
* Revert "chore: move function to correct file"

This reverts commit ebfdfa283b.

* Revert "refactor!: merge get_site_url into get_url (#22308)"

This reverts commit 2001bc278f.
2023-09-13 14:34:52 +05:30
David Arnold
2001bc278f
refactor!: merge get_site_url into get_url (#22308)
* chore: merge get_site_url into get_url

* fix: keep alias with deprecation notice
2023-09-11 15:09:05 +05:30
Sagar Vora
151874c035 test: ensure get_permitted_fieldnames is called only once per doc 2023-08-18 22:47:37 +05:30
Ankush Menat
8930d4b5e1
perf: drop ifnull from IS SET filter (#21822)
- Kinda confuses query planner (idk why it's not smart enough to
  understand but there are probably edge cases where it can't be done)
- `null != null` and `'' != null` both yield `null` which is falsy and
  won't be shown in results.

Alternate fix to https://github.com/frappe/frappe/pull/21817
2023-07-27 10:58:20 +05:30
Ankush Menat
2c99583247 perf: Lazily fetch shared documents
We eagerly fetch shared documents for ANY `get_list` query, even when
user has full read acess doctype, where it's moot to consider adding
shared document as separately.

This eliminates one entire db call from get_list and in most cases
get_list will translate to single DB call, hence probably worth the
additional complexity.
2023-07-22 18:04:35 +05:30
Ankush Menat
79532ea0f2 fix: incorrect cache clearing of assets
- Build version wasn't correctly computed since v14 update of build
  system. This makes client side cache useless.
- We clear cache assuming rapid reloads,but opening new tab also does
  that. This makes the cache effectively useless for most users.
2023-07-15 21:59:04 +05:30
Ankush Menat
8730de41f9
fix: Only clear doctype cache if specified (#21611) 2023-07-09 10:44:43 +05:30
Ankush Menat
d7990368a8
perf: preload more modules (#21557)
* perf: preload more modules

- bleach is used frequently for sanitization
- File gets imported anytime a private file is viewed. Indirect import
  of PIL is costly in each worker.

* test: warm up perf test
2023-07-02 21:47:21 +05:30
Ankush Menat
c73d9fb783 test: add perf test helper for counting rows read 2023-06-28 19:51:18 +05:30
Ankush Menat
cee2b50461 perf: single query db.set_value 2022-10-06 19:46:58 +05:30
Ankush Menat
656f6df257
fix: drop Meta cache during update (#18182) 2022-09-19 19:24:17 +05:30
Ankush Menat
c28ddcc3e6 test: basic perf test for rps on get_list 2022-09-19 16:21:20 +05:30
Ankush Menat
f5b8e5f015
perf: short-circuit guest connection and basic perf tests (#17988)
* perf: reorder condition to avoid redis call

* test: basic perf tests
2022-08-30 16:30:25 +05:30