데이터브릭스(Databricks)는 자사의 수백만 줄에 달하는 실제 코드베이스를 바탕으로 다양한 코딩 에이전트의 성능과 비용을 분석했습니다. 이를 통해 토큰(Token) 가격이 전체 작업 비용과 비례하지 않으며, 작업 복잡도에 맞춰 모델을 분산 사용하고 단순한 하네스(Harness)를 활용하는 것이 훨씬 효율적이라는 실무적 인사이트를 도출했습니다.
번역된 본문
본문으로 건너뛰기. 데이터브릭스(Databricks)에서는 엔지니어링 부문에 AI를 적극적으로 도입하면서 소프트웨어를 개발하는 방식이 빠르게 변화하고 있습니다. 지난 1년 동안 코드 작성을 위한 모델과 하네스(Harness, 구동 환경) 생태계가 급격히 확장되어 개발자들이 선택할 수 있는 옵션이 그 어느 때보다 많아졌습니다. 선택지가 많아짐에 따라, 실제 코딩 작업에서 어느 코딩 에이전트가 최고의 성능을 제공하는지, 그리고 작업 성능이 가격에 따라 어떻게 달라지는지 이해하는 것이 매우 중요해졌습니다.
이 글은 데이터브릭스 내부에서 구축한 코딩 벤치마크의 결과와 방법론을 공유합니다. 이 벤치마크는 데이터브릭스 엔지니어들이 당사 코드베이스에서 수행한 실제 코딩 작업을 바탕으로 도구들을 평가했습니다. 작업에는 Python, Go, Typescript, Scala 등 다양한 인기 언어로 작성된 수백만 줄의 코드베이스를 수정하는 과정이 포함되었으며, 정확성을 보장하기 위해 과제와 해결책을 모두 면밀히 검토했습니다. 이 결과가 모든 것을 포괄하는 것은 아니지만, 이 과정을 통해 얻은 인사이트 덕분에 엔지니어링 팀은 이미 코딩 에이전트를 훨씬 더 의미 있게 효율적으로 사용하고 있습니다. 아래에서는 전체 벤치마크에서 모델과 하네스가 어떤 점수를 받았는지 확인할 수 있습니다.
그림 1: 벤치마크에 따른 비용 대비 성능
분석을 통해 얻은 주요 결론은 다음과 같습니다:
코딩 작업의 파레토 최전선(Pareto frontier, 주어진 비용 대비 최고의 품질)에는 OpenAI, Anthropic 및 오픈소스 모델이 포함되어 있습니다. 이는 현재 여러 도구를 혼합해야만 최고 수준의 성능을 얻을 수 있음을 의미합니다.
오픈 모델, 특히 GLM 5.2는 이제 가장 높은 수준의 난이도를 가진 작업도 처리할 수 있게 되었습니다.
모델의 토큰 가격은 엔드투엔드(End-to-End) 작업에서 발생하는 실제 비용을 가늠하는 좋은 지표가 아닙니다. 대형 모델이 토큰을 훨씬 더 효율적으로 사용하여 전체 비용이 더 낮을 수 있습니다.
모델을 호출하는 하네스(Harness)는 비용과 품질에 엄청난 영향을 미칩니다. 대부분의 경우, 우리의 워크로드에서는 Pi와 같은 단순한 하네스가 최고의 성능을 보였습니다.
각 항목에 대해 조금 더 자세히 살펴보겠습니다.
모델들은 대략적인 '역량 등급(Capability tiers)'으로 묶임
실제 환경의 작업에서는 특정 결과가 몇 점 차이가 나는 것이 종종 평준화되기도 합니다. 우리는 다양한 작업에 어떤 모델을 사용해야 할지 추론하는 데 도움이 되는 주요 패턴에 더 초점을 맞췄습니다. 실제로 결과는 모델과 하네스가 3개의 역량 등급으로 명확하게 군집화됨을 보여주었습니다.
그림 2: 전체 결과에서 3개의 뚜렷한 역량 등급이 나타났으며, 각 그룹에서 어떤 모델이 효과적인지에 대한 차이가 존재합니다.
성능의 최상위권을 보면, 가장 지능적인 모델은 모든 종류의 문제를 해결하는 데 매우 효과적이지만 매우 비쌉니다. 반면 중간 및 하위 지능 모델은 여전히 일반적인 작업에서 매우 효과적이며, 많은 경우 비용도 훨씬 저렴합니다. 일상적으로 엔지니어들은 복잡도가 다양하고 매우 다른 작업을 많이 수행합니다. 예를 들어, 플래그를 설정하거나 구성(configs)을 업데이트하는 일반적인 운영 작업에는 최고 수준으로 지능적인 모델이 필요하지 않지만, 심층적인 설계 탐색 작업에는 필요합니다. 그러나 과거에는 우리의 기본 모델이 항상 가장 비싼 모델이었습니다. 이 분석을 바탕으로 우리는 Haiku 및 GPT 5.4 Mini 급의 모델로 더 많은 작업을 넘겨야 한다고 결론지었습니다.
오픈 모델이 코딩 분야에 정착하다
최근 GLM 5.2에 대한 기대가 매우 높았으며, 당사의 결과 역시 GLM이 많은 개발자를 위한 일상적인 메인 모델(Daily driver model)이 될 수 있다는 증거를 보여주었습니다. 이 모델은 최상위 역량 등급에 위치하며 품질 면에서 통계적으로 Opus 4.8과 동등한 수준이었지만, 비용은 Opus의 $1.94에 비해 작업당 $1.28에 불과했습니다. 이러한 GLM의 품질 점수는 일상적인 개발을 위해 GLM을 시범적으로 사용해 온 내부 개발자들의 정성적 피드백과도 일치합니다. 일상적인 코딩 작업에서 훌륭한 성능을 보여주기 때문에 우리는 최고의 성능으로 GLM을 제공하는 데 집중해 왔으며, 증거에 따르면 이제 이 모델을 코딩용 메인 모델로 배포할 때가 되었습니다.
작업당 가격 vs 토큰당 가격
개발자들은 종종 코딩 작업을 완료할 때 모델이 얼마나 비쌀지 판단하기 위해 토큰 비용을 대략적으로 계산합니다. 그러나 우리는 모델 간의 추론 효율성 차이로 인해 토큰 비용이 전체 작업 비용을 가늠하는 좋은 지표가 아닌 경우가 많다는 것을 발견했습니다.
Skip to main content At Databricks, the way we build software is changing quickly as we aggressively adopt AI for engineering. The landscape of models and harnesses for code authoring has rapidly expanded in the last year, giving developers more choices than ever. With more options, it has become increasingly important to understand which coding agents offer the best performance on real-world coding tasks as well as understanding how task-performance varies with price. This article shares the results and methodology of the internal coding benchmark we built at Databricks, which evaluates tools on actual coding tasks our engineers performed on the Databricks codebase. Tasks featured edits against a multi-million line codebase covering many popular languages (Python, Go, Typescript, Scala, etc.) and both tasks and solutions were carefully reviewed to ensure accuracy. This isn't meant to be comprehensive, but the exercise surfaced insights that have already made our engineering team meaningfully more efficient with coding agents. Below, you can see how models and harnesses scored on the overall benchmark: Figure 1: Cost vs. Performance on our benchmark The main conclusions from our analysis were: The Pareto frontier for coding tasks (i.e. best quality for a given cost) includes models from OpenAI, Anthropic, and open source. This means today, only a mix of tools can provide frontier performance. Open models, and GLM 5.2 in particular, are now able to handle even the highest level of task difficulty. The token price of a model is a poor indicator of actual costs incurred on end-to-end tasks. Larger models can be far more token efficient and have lower overall costs. The harness a model is called from dramatically impacts cost and quality. In many cases, simple harnesses like Pi performed best on our workloads. Let’s dive a bit deeper on each one. Models cluster into rough “capability tiers” Specific results being a couple points off can often even out in real world tasks. We focused more on the thematic patterns that help us reason about which models to use for various tasks. In fact, the results showed clear clustering of the models and harnesses into 3 capability tiers. Figure 2: Three distinct capability tiers emerged in our overall results, with nuance in which models were effective in each group At the upper end of performance, we see that the most intelligent models are very effective at solving all kinds of problems, but they’re very expensive. Medium and lower intelligence models are still highly effective at the common tasks, and in many cases, they’re also significantly cheaper. Day to day, engineers do a lot of different things that vary significantly in complexity: common operational tasks like flipping a flag or updating configs don’t require extremely intelligent models, but deeper design explorations do. However, in the past, our default models were always the most expensive ones. Based on this analysis we determined we should push more work to the Haiku and GPT 5.4 Mini class of models. Open models are here for coding There’s been a lot of excitement about GLM 5.2, and our results showed evidence that GLM can be a daily driver model for a lot of our developers. It landed in the top capability tier, statistically tied with Opus 4.8 on quality, but costing $1.28/task against Opus’s $1.94. The GLM quality scores are consistent with qualitative feedback we’ve gotten from internal developers who have been piloting GLM for daily development. Because of its great performance for everyday coding tasks, we’ve been focused on serving GLM with the best performance , and the evidence shows it’s time to start deploying these as daily drivers for coding. Price-per-task vs price-per-token Developers often eyeball token costs to determine how expensive a model will be when completing coding tasks. We found, however, that token costs are often a poor indicator of overall task costs, due to variance in reasoning efficiency amongst models. This underscores the need for task-level benchmarking, since task shape and complexity may be different in different contexts. As an example, Sonnet 5 is ~1.7x cheaper per token than Opus 4.8, but, on our tasks, we found that Sonnet cost $2.09/task vs Opus’s $1.94, while scoring six points lower on task completion (81% vs 87%). This was mostly because Sonnet 5 worked longer and read more to get there, consuming 1.9x more tokens. Harnesses have a major impact on efficiency When we ran the same model with the same thinking effort through two different harnesses (Claude Code/Codex vs Pi), we observed that the cost per task differed significantly (more than 2x in some cases), while quality remained the same. The main difference came down to how much context each harness fed the model on each turn. Pi sent about 3x less context per turn. It managed context better, keeping a tighter working set and finishing the tasks in fewer runs. The lesson here isn’t that one harness is always cheaper or that native harnesses are worse. Instead, model choice is only one piece of the puzzle. Establishing this flexibility is why we invested in Omnigent to make mode-and-harness swaps seamless. Why build your own benchmark? Public benchmarks like SWE-Bench and TerminalBench are useful, but they can’t answer the questions we had. There are a few reasons for this: The tasks are public, so the solutions leak into training data over time. We found the results weren’t representative for our codebase, which spans 10+ languages and many services written in Scala, Go, Rust, Java and Python, Bazel, Protobuf, and more. By building a benchmark on our own PRs, we can make these decisions with higher confidence that we won’t hamper our developers by rolling out optimizations. How we built the benchmark We used Unity AI Gateway to capture logs of all our coding interactions, which enabled us to analyze the complexity of the tasks engineers tackle using coding agents. There was a significant diversity in the task complexity, and about a quarter were tagged as low-complexity work and ~60% as medium complexity. However, expensive models are the default models engineers use, so there was clearly a huge opportunity for improving efficiency. Task Construction Our engineers merge thousands of code changes a day, so we already have a great dataset to build off. A good pull request is a rich artifact, with commits that show iteration from the developer, review by humans, and tests that help verify a code change is faithful to its intent. However, we needed several quality checks and filters to construct a high-quality benchmark out of them: Recency: We pull from recent history so the tasks reflect how we build today, including the frameworks, patterns, and conventions currently in use. Human written: Bot commits, service accounts, fully AI generated changes, and auto-generated changes were filtered. Associated high quality test suite: We filtered for PRs that included high-quality tests for validating the code changes. Self-contained: The changes were confined to a few modules. Representative of typical tasks: We selected PRs from a distribution of tasks across the full stack: Scala backend services, Rust systems code, the React and TypeScript frontend, protobuf and gRPC contracts, and Bazel configs. Once we had candidate PRs, we focused on constructing well-specified tasks by: Gleaning the intent and summarizing it as a prompt. We read the PR to understand what it was actually for and then describe the outcome we want. Usually, that meant rewriting the PR description by stating the problem or goal, naming any constraints, and removing the description of the solution. It’s important to remove, for example, explanations of why a bug fix is the right one, since that makes the task too easy. Splitting out the relevant tests. The non-test files were the change the model has to reproduce on its own, so we set the test files aside and ensured we could compile that.