Public

sgl-project/sglang

Updated: 8/15/2026

Languages

Python76.9%MDX6.8%Rust6.1%Cuda4.3%C++2.7%JavaScript1.9%Other1.3%
14 Models59 Tasks

SGLang is a high-performance serving framework for large language models and multimodal models.

Harness

1

Mini-SWE-agent
46 / 59

$0.49

2m42s

2

Mini-SWE-agent
45 / 59

$0.12

4m27s

3

Mini-SWE-agent
45 / 59

$2.28

5m39s

4

Mini-SWE-agent
45 / 59

$0.77

13m46s

5

Mini-SWE-agent
45 / 59

$7.11

14m58s

6

Mini-SWE-agent
44 / 59

$2.41

8m06s

7

Mini-SWE-agent
43 / 59

$0.66

2m40s

8

Mini-SWE-agent
43 / 59

$0.74

3m46s

9

Mini-SWE-agent
43 / 59

$8.84

13m12s

10

Mini-SWE-agent
43 / 59

$4.25

14m15s

11

Mini-SWE-agent
42 / 59

$1.50

7m39s

12

Mini-SWE-agent
42 / 59

$4.69

18m05s

13

Mini-SWE-agent
41 / 59

$4.06

10m59s

14

Mini-SWE-agent
33 / 59

$0.37

3m50s

Key Takeaways

  • Claude Fable 5, GLM 5.2 (Fireworks), GPT 5.5, and GPT-5.6 Luna with Mini-SWE-agent each resolve 45 tasks, one behind GPT-5.6 Terra.
  • GPT-5.6 Luna with Mini-SWE-agent has the lowest cost per test among the 45-task results at $0.12; Gemini 3.1 Pro Preview (02/26) is fastest among the 43-task results at 159.84 seconds.
  • GPT-5.6 Terra with Mini-SWE-agent is also faster than every other result resolving at least 44 tasks, at 162.20 seconds.

Model Comparison

Accuracy

77.97%

GPT-5.6 Terra

76.27%

GPT-5.6 Luna

Task outcomes

59 tasks

Both
GPT-5.6 Terra only
GPT-5.6 Luna only
Neither
Not attempted

Cost / test

$0.49

GPT-5.6 Terra

$0.12

GPT-5.6 Luna

Cost distribution

$0.00$0.89$1.77

Latency

2m 42s

GPT-5.6 Terra

4m 27s

GPT-5.6 Luna

Latency distribution

0s7m 43s15m 26s

Cost Analysis

Cost / Test vs. Accuracy
ACCURACYCOST

Average Token Use / Test

Token Usage
InputOutputReasoningCache readCache write
Claude Sonnet 5
10.8M
Claude Opus 4.7
5.3M
Claude Opus 4.8
4.7M
Claude Fable 5
3.8M
Gemini 3.5 Flash
3.6M
GLM 5.2
3.5M
Kimi K3
2.8M
GPT-5.6 Luna
2.6M
GPT 5.5
2.4M
Claude Haiku 4.5 (Nonthinking)
2.1M
GPT-5.6 Sol
2.0M
Grok 4.5
1.0M
Gemini 3.1 Pro Preview (02/26)
994K
GPT-5.6 Terra
760K

Cost is the clearest tradeoff in this comparison. GPT-5.6 Terra leads at 77.97% for $0.49 per test. GPT-5.6 Luna is the lower-cost option at 76.27% for $0.12 per test.

Latency Analysis

Latency vs. Accuracy
ACCURACYLATENCY

Average Response Time / Test

Response Time
Claude Sonnet 5
18m 5s
Claude Fable 5
14m 58s
Claude Opus 4.8
14m 15s
GLM 5.2
13m 46s
Kimi K3
13m 12s
Claude Opus 4.7
10m 59s
GPT-5.6 Sol
8m 6s
Gemini 3.5 Flash
7m 39s
GPT 5.5
5m 39s
GPT-5.6 Luna
4m 27s
Claude Haiku 4.5 (Nonthinking)
3m 50s
Grok 4.5
3m 46s
GPT-5.6 Terra
2m 42s
Gemini 3.1 Pro Preview (02/26)
2m 40s

Latency separates several models with similarly strong scores. GPT-5.6 Terra leads at 77.97%, while Gemini 3.1 Pro Preview (02/26) is fastest at 2m 40s with 72.88% accuracy.

Tasks with failures

Models
GPT-5.6 Terra
GPT-5.6 Luna
GLM 5.2
GPT 5.5
Claude Fable 5
GPT-5.6 Sol
Gemini 3.1 Pro Preview (02/26)
Grok 4.5
Claude Opus 4.8
Kimi K3
Gemini 3.5 Flash
Claude Sonnet 5
Claude Opus 4.7
Claude Haiku 4.5 (Nonthinking)

Task detail

f8eac99

Issue statement

HiCache reports two Prometheus metrics for KV-cache load-back operations: the number of tokens moved from host (CPU) memory back to device (GPU) memory (sglang:load_back_num_tokens) and the time each load-back takes (sglang:load_back_duration_seconds).

Today the duration is measured on the host with time.perf_counter() around the code that enqueues the asynchronous host-to-device copy. Because the copy runs on a separate device stream and completes later, this wall-clock span only covers the time spent submitting the work, not the time the transfer actually takes. The reported duration is therefore misleading and the token counter is updated at enqueue time rather than when the load actually completes.

The load-back duration should instead be measured on the device around the actual copy, and both metrics should be recorded when the load-back operation is confirmed complete (i.e. when its completion event is processed), not when it is submitted.

Requirements:

  1. Add a helper in sglang/srt/managers/cache_controller.py that creates a pair of device timing events for a load-back operation:

    • A cached predicate _timing_events_supported() that returns whether the active device backend's Event type accepts enable_timing=True. It must probe by constructing device_module.Event(enable_timing=True) and return False (logging a warning) when that raises TypeError or NotImplementedError, and True otherwise. The result must be cached so the probe runs at most once, and the cache must be clearable.
    • A function make_timing_event_pair() that returns a 3-tuple (start_event, finish_event, timing_enabled). When timing is supported both events are created with enable_timing=True; otherwise they are created with no timing kwargs. The two returned events must be distinct objects, and timing_enabled must reflect whether timing is supported.
  2. Extend the HiCacheAck record with two new fields carrying the completion information for a load-back: num_tokens (defaulting to 0) and timing_enabled (defaulting to False). Existing construction of HiCacheAck with only start_event, finish_event, and node_ids must continue to work.

  3. Record the load-back metrics when completed load acks are processed in HiRadixCache.loading_check() (rather than at submission time). For each completed ack, and only when a metrics collector is present, always increment the load-back token counter by the ack's num_tokens. Additionally, when the ack has timing enabled, compute the elapsed device time between its start and finish events (start_event.elapsed_time(finish_event), which returns milliseconds) and observe the load-back duration in seconds. When timing is not enabled, the duration must not be observed and the events' elapsed time must not be queried.

The submission-time time.perf_counter() based duration/token bookkeeping for load-back should be removed so the metrics are only recorded on completion.

View Hidden Tests
diff --git a/test/registered/unit/mem_cache/test_hicache_load_back_metrics.py b/test/registered/unit/mem_cache/test_hicache_load_back_metrics.pynew file mode 100644index 0000000..a4333b5--- /dev/null+++ b/test/registered/unit/mem_cache/test_hicache_load_back_metrics.py@@ -0,0 +1,152 @@+"""Unit tests for the HiCache load-back duration/token metrics.++These tests exercise the device-event based instrumentation that HiCache uses to+report how long a KV-cache load-back took and how many tokens it moved. They run+on any backend (including CPU-only environments) by using mock device events, so+they do not require a real GPU.+"""++import unittest+from types import SimpleNamespace+from unittest.mock import MagicMock, patch+++class TestMakeTimingEventPair(unittest.TestCase):+    def setUp(self):+        from sglang.srt.managers import cache_controller as cc++        cc._timing_events_supported.cache_clear()+        self.cc = cc++    def tearDown(self):+        self.cc._timing_events_supported.cache_clear()++    def test_timing_supported_uses_enable_timing(self):+        created = []++        def create_event(*, enable_timing=False):+            created.append(enable_timing)+            return MagicMock()++        with patch.object(self.cc.device_module, "Event", side_effect=create_event):+            self.cc._timing_events_supported.cache_clear()+            start, finish, timing_enabled = self.cc.make_timing_event_pair()++        self.assertTrue(timing_enabled)+        self.assertIsNot(start, finish)+        # Every event (probe + the returned pair) was created with enable_timing.+        self.assertTrue(created and all(created))++    def test_timing_fallback_uses_dedicated_events(self):+        events = []++        def create_event(*, enable_timing=False):+            if enable_timing:+                raise TypeError("Event() takes no arguments")+            event = MagicMock()+            events.append(event)+            return event++        with patch.object(self.cc.device_module, "Event", side_effect=create_event):+            self.cc._timing_events_supported.cache_clear()+            start, finish, timing_enabled = self.cc.make_timing_event_pair()++        self.assertFalse(timing_enabled)+        self.assertIs(start, events[0])+        self.assertIs(finish, events[1])+        self.assertIsNot(start, finish)+++class TestHiCacheAckFields(unittest.TestCase):+    def test_num_tokens_and_timing_defaults(self):+        from sglang.srt.managers.cache_controller import HiCacheAck++        ack = HiCacheAck(start_event=None, finish_event=None, node_ids=[1])+        self.assertEqual(ack.num_tokens, 0)+        self.assertFalse(ack.timing_enabled)++    def test_fields_carry_supplied_values(self):+        from sglang.srt.managers.cache_controller import HiCacheAck++        ack = HiCacheAck(+            start_event=None,+            finish_event=None,+            node_ids=[3, 4],+            num_tokens=128,+            timing_enabled=True,+        )+        self.assertEqual(ack.num_tokens, 128)+        self.assertTrue(ack.timing_enabled)+++def _make_load_stub(ack):+    return SimpleNamespace(+        cache_controller=SimpleNamespace(ack_load_queue=[ack]),+        ongoing_load_back={i: object() for i in ack.node_ids},+        dec_lock_ref=MagicMock(),+        metrics_collector=MagicMock(),+        pp_rank=0,+        _all_reduce=MagicMock(),+    )+++class TestLoadingCheckMetrics(unittest.TestCase):+    def test_loading_check_records_duration_and_tokens(self):+        from sglang.srt.managers.cache_controller import HiCacheAck+        from sglang.srt.mem_cache.hiradix_cache import HiRadixCache++        finish_event = MagicMock()+        finish_event.query.return_value = True+        start_event = MagicMock()+        start_event.elapsed_time.return_value = 2000.0  # milliseconds++        ack = HiCacheAck(+            start_event=start_event,+            finish_event=finish_event,+            node_ids=[1, 2],+            num_tokens=1024,+            timing_enabled=True,+        )+        stub = _make_load_stub(ack)++        HiRadixCache.loading_check(stub)++        stub.metrics_collector.increment_load_back_num_tokens.assert_called_once_with(+            1024+        )+        stub.metrics_collector.observe_load_back_duration.assert_called_once()+        (observed,), _ = stub.metrics_collector.observe_load_back_duration.call_args+        # Duration is reported in seconds (2000 ms -> 2.0 s).+        self.assertAlmostEqual(observed, 2.0)+        self.assertEqual(stub.cache_controller.ack_load_queue, [])+        self.assertEqual(stub.ongoing_load_back, {})++    def test_loading_check_skips_duration_when_timing_unsupported(self):+        from sglang.srt.managers.cache_controller import HiCacheAck+        from sglang.srt.mem_cache.hiradix_cache import HiRadixCache++        finish_event = MagicMock()+        finish_event.query.return_value = True+        start_event = MagicMock()++        ack = HiCacheAck(+            start_event=start_event,+            finish_event=finish_event,+            node_ids=[7],+            num_tokens=512,+            timing_enabled=False,+        )+        stub = _make_load_stub(ack)++        HiRadixCache.loading_check(stub)++        stub.metrics_collector.increment_load_back_num_tokens.assert_called_once_with(+            512+        )+        stub.metrics_collector.observe_load_back_duration.assert_not_called()+        start_event.elapsed_time.assert_not_called()+        self.assertEqual(stub.cache_controller.ack_load_queue, [])+++if __name__ == "__main__":+    unittest.main()