eclipse-bench — Eclipse vs Linux

Misma máquina, 20 CPUs, working set 32 MiB. Ambos runs completos (CPU → Ratios). Filas [user] miden la CPU y deben salir parecidas; las [kernel] miden el sistema operativo — ahí está la diferencia real.

Eclipse Linux Pop!_OS userspace kernel gana pierde anomalía / dato no comparable

● Eclipse

self
/bin/eclipse-bench
dir / disk / mem
. · 32 MiB · 32 MiB
cpus
20
free en dir
242 547 MiB
vDSO
0x7ffffff7c000

● Linux Pop!_OS

self
…/tools/eclipse-bench/eclipse-bench
dir / disk / mem
. · 32 MiB · 32 MiB
cpus
20
free en dir
466 338 MiB
vDSO
0x7b24440f8000

Resumen lo que dicen los números

Donde Eclipse gana

  • fork + exit: 79.9 µs vs 2442 µs — 31× más rápido
  • fork + exec: 207 µs / 991 µs vs 2286 / 4599 µs — 11× y 4.6×
  • pthread_create + join: 24.4 µs vs 1626 µs
  • Ancho de banda de pipe: 7406 MB/s vs 1107 MB/s (6.7×)
  • vDSO (clock_gettime, time): ~2× mejor, sin trap
  • pipe round trip bajo carga: 8.51 µs vs 47.1 µs
  • forks/s x1: 14 111 vs 488 (29×)

Donde Eclipse pierde

  • Latencia de timer: sleep 1ms late idle 5001 µs vs 81 µs; bajo carga 113 751 µs vs 52 µs
  • wake late loaded/idle: 22.7× vs 0.64× — el titular de interactividad
  • Disco: escritura 107 MB/s vs 741; lectura 1.0 vs 8.9 GB/s; IOPS 137 k vs 1.92 M
  • Syscalls con trap (getpid, pread, fstat): 4–7× más lentas
  • Escalado de syscall 6.1 % vs 58 %; de fault 6.7 % vs 3.35 %
  • fork copy ratio 2.72× → fork copia eager, no COW
  • fork+exit bajo carga: 25 658 µs vs 1542 µs
Lectura corta: Eclipse tiene rutas de proceso (fork/exec/hilos) y de pipe excelentes, pero la latencia de despertar por temporizador es su problema dominante — y empeora ~23× bajo carga. Eso es exactamente lo que se percibe como sistema a tirones, por buenos que sean los números [user].

CPU user · más alto mejor

Propiedad de la CPU, no del OS. Si difieren: gobernador P-state o hypervisor. Aquí quedan a un 4–7 %, lo esperable.

MétricaEclipseLinuxE/L
userint latency (dependent) 1034 Mops/s 1102 Mops/s 0.94×
userint throughput (4-wide) 4228 Mops/s 4427 Mops/s 0.96×
userfloat latency (dependent) 515.3 Mops/s 553.0 Mops/s 0.93×

Memory user · working set 32 MiB

MétricaEclipseLinuxE/L
usermemcpy bandwidth 6.5 GB/s 8.3 GB/s 0.78×
usermemset bandwidth 24.0 GB/s 24.1 GB/s 1.00× (empate)
userrandom access latency (pre-faulted) 55.4 ns 58.8 ns 0.94×

Syscall kernel · más bajo mejor

Round-trip al kernel. Resta la fila getpid de cualquier otra para aislar el coste del subsistema del coste del trap.

MétricaEclipseLinuxhintE/L
kernelgetpid() 506.6 ns89.7 ns ~555.6×
kernelclock_gettime(MONOTONIC) 7.79 ns14.4 ns ~25 (vDSO)0.54×
kernelclock_gettime(REALTIME) 8.02 ns14.6 ns ~25 (vDSO)0.55×
kernelgettimeofday() 11.9 ns20.9 ns ~25 (vDSO)0.57×
kerneltime() 9.27 ns15.2 ns ~25 (vDSO)0.61×
kernelraise(SIGUSR1)+handler 2908 ns1217 ns ~15002.4×
kernelsigprocmask() 553.2 ns99.8 ns ~905.5×
kernelsched_yield() 717.3 ns229.2 ns ~3003.1×
kernelpread(/dev/zero, 1B) 947.8 ns138.5 ns ~2506.8×
kernelwrite(/dev/null, 1B) 577.9 ns134.0 ns ~2504.3×
kernelfstat() 796.0 ns192.5 ns ~3004.1×
kernelstat("/dev/null") 952.3 ns407.8 ns ~900 (path walk)2.3×
kernelopen+close(/dev/null) 3624 ns1841 ns ~12002.0×
Patrón claro: todo lo que pasa por vDSO (sin trap) lo gana Eclipse; todo lo que entra al kernel cuesta ~500 ns de base frente a los ~90 ns de Linux. Ese suelo de trap es el que arrastra las 8 filas siguientes.

VM / page faults kernel · más bajo mejor

Se pagan en el arranque de cada programa y en cada allocation que se toca; no aparecen en un benchmark de memcpy.

MétricaEclipseLinuxhintE/L
kernelmmap+munmap (4 KiB) 4274 ns1269 ns ~25003.4×
kernelmprotect (4 KiB, ×2) 2440 ns741.0 ns ~18003.3×
kernelminor fault (anon touch) 1366 ns803.7 ns ~5001.7×
kernelCOW fault (after fork) ⚠ 566.9 ns3757 ns ~1500no comparable
kernelfork memory isolation PASSPASS
La fila COW fault de Eclipse no significa nada. El fork copy ratio es 2.72× (sección Process), es decir el fork copia de forma eager: las páginas del hijo ya son privadas, así que esos 566.9 ns cronometran escrituras normales, no fallos copy-on-write. Un número implausiblemente bueno es justamente la señal. El propio benchmark lo advierte.

Scheduler / IPC kernel · interactividad

Lo que hace que un sistema se sienta rápido o lento. La latencia de despertar bajo carga es LA métrica de interactividad.

MétricaEclipseLinuxhintE/L
kernelpipe round trip (2 procs) 8.13 µs5.94 µs ~61.4×
kernelpipe round trip (2 thrds) 8.45 µs5.53 µs ~41.5×
kernelsocketpair round trip 8.92 µs5.52 µs ~81.6×
kernelfutex wake round trip 7.95 µs3.91 µs ~32.0×
kernelpthread_create + join 24.4 µs1626 µs ~150.015×
kernelpipe bandwidth (64K writes) 7406 MB/s1107 MB/s >10006.7×
kernelsleep 1ms late, idle (mean) 5001 µs81.2 µs ~6062×
kernelsleep 1ms late, idle (worst) 25412 µs132.2 µs ~200192×
con 20 procesos CPU-bound compitiendo por las CPUs
kernelsleep 1ms late, load (mean) 113 751 µs52.3 µs ~1002175×
kernelsleep 1ms late, load (worst) ← stutter 514 715 µs62.5 µs ~5008235×
kernelpipe round trip, load 8.51 µs47.1 µs ~200.18×
Dos señales opuestas en la misma sección, y merece la pena separarlas: el pipe bajo carga aguanta (8.51 µs, prácticamente igual que en reposo, y mejor que Linux) — la preempción al despertar funciona por la vía de IPC. Pero el sleep por temporizador se desploma (5 ms en reposo → 114 ms bajo carga, peor caso 515 ms). El problema está en la ruta de timer wake, no en la de pipe.

SMP scaling kernel · 20 CPUs

El trabajo es ALU pura en userspace: cualquier cosa por debajo del escalado lineal es del kernel (colocación, contención o CPUs offline).

MétricaEclipseLinuxhintE/L
kernel1 thread aggregate 1002 Mops/s1091 Mops/s 0.92×
kernel20 threads aggregate 15 113 Mops/s18 544 Mops/s 0.82×
kernelscaling efficiency 75.4 %85.0 % >900.89×
rutas SMP del kernel: contención, shootdowns, wakes cross-CPU
kernelgetpid/s ×1 1.98 Mops/s10.6 Mops/s 0.19×
kernelgetpid/s ×20 2.41 Mops/s123.4 Mops/s 0.02×
kernelsyscall scaling 6.10 %58.4 % >850.10×
kernelmprotect flip, peers idle 1449 ns1094 ns 1.3×
kernelmprotect flip, 19 spinning 10 080 ns5861 ns 1.7×
kernelshootdown cost 6.96 ×5.36 × ~2–4 (IPI + ack)1.3×
kernelmmap+touch+munmap ×20 vs ×1 1.42 %0.55 % ~40–702.6×
kernelminor faults/s ×1 675.5 kflt/s811.9 kflt/s 0.83×
kernelminor faults/s ×20 900.1 kflt/s543.4 kflt/s 1.7×
kernelfault scaling 6.66 %3.35 % >602.0×
kernelcontended mutex collapse 16.7 ×16.9 × ~10–400.99× (empate)
kernelpipe RT pinned same-CPU ⚠ 123.0 µs2.38 µs 52×
kernelpipe RT pinned cross-CPU 16.5 µs4.73 µs 3.5×
kernelcross-CPU wake cost ⚠ 0.13 ×1.99 × ~0.5–2fuera de rango
kernelforks/s ×1 14 111 forks/s488.5 forks/s 28.9×
kernelforks/s ×20 procs 17 666 forks/s12 860 forks/s 1.4×
kernelfork scaling 6.26 %131.6 % ~50–800.05×
kernelfairness max/min (2× hogs) n/an/a <1.5
Anomalía en el pipe fijado: en Eclipse el ping-pong en la misma CPU (123 µs) sale 7× más lento que cruzando CPUs (16.5 µs), de ahí un cross-CPU wake cost de 0.13× cuando lo normal es 0.5–2×. Físicamente debería ser al revés (misma CPU = cambio de contexto con caché caliente, sin IPI). Apunta a que sched_setaffinity no está migrando el hilo al momento, o a que dos tareas fijadas a la misma CPU se serializan esperando la rodaja en vez de alternarse.

El fork scaling de 6.26 % tiene truco: la base forks/s ×1 de Eclipse ya es 29× la de Linux, así que el porcentaje mide cuánto se degrada respecto a un punto de partida altísimo — en absoluto Eclipse sigue haciendo más forks/s que Linux con 20 procesos.

Disk kernel · 32 MiB solicitados

Ojo al contexto: el espacio libre difiere (242 547 MiB en Eclipse vs 466 338 MiB en Linux), así que no es necesariamente el mismo dispositivo ni el mismo sistema de ficheros.

MétricaEclipseLinuxE/L
kernelseq write (+fsync) 107.4 MB/s741.3 MB/s 0.14×
kernelseq read 1.0 GB/s8.9 GB/s 0.11×
kernelrand 4K read 137 420 IOPS1 921 647 IOPS 0.07×
kernelrand 4K read latency 7.28 µs0.52 µs 14×
kernelfsync latency (best) 1.95 ms0.92 ms 2.1×
kernelmeta create small files 452.7 files/s2014 files/s 0.22×
kernelmeta stat 57 342 stats/s334 274 stats/s 0.17×
kernelmeta unlink 1072 unlinks/s4186 unlinks/s 0.26×
Las cifras de Linux (8.9 GB/s de lectura secuencial, 1.9 M IOPS, 0.52 µs de latencia) son de caché de páginas, no de disco físico: 32 MiB entran enteros en RAM. La comparación honesta aquí es "cuánta caché de página consigue cada kernel", y Eclipse está entre 4× y 14× por detrás en todas las filas.

Process creation kernel · más bajo mejor

La prueba de copy-on-write, y la sección donde Eclipse gana con más holgura… en reposo.

MétricaEclipseLinuxhintE/L
kernelfork + exit 79.9 µs2442 µs ~700.033×
kernelfork + exit, 1 MiB resident 250.3 µs2586 µs 0.097×
kernelfork + exit, 16 MiB resident 3423 µs4011 µs 0.85×
kernelfork cost per MiB resident 211.5 µs/MiB95.0 µs/MiB 2.2×
vs memcpy 1 MiB aquí 77.7 µs/MiB241.0 µs/MiB referencia
fork copy ratio ⚠ 2.72 ×0.39 × COW ~0.3, eager ≥17.0×
kernelfork + exit, 8 mappings 268.9 µs2779 µs 0.097×
kernelfork + exit, 256 mappings 652.5 µs3928 µs 0.17×
kernelfork cost per mapping 1.55 µs/map4.63 µs/map 0.33×
con 19 procesos CPU-bound compitiendo
kernelfork+exit, 8 maps, load 25 658 µs1542 µs 17×
kernelfork+exit, 256 maps, load 25 384 µs2078 µs 12×
kernelfork cost per mapping, load 0.00 µs/map (plano)2.16 µs/map dominado por scheduler
kernelfork + exec(self, static) 207.1 µs2286 µs ~3500.091×
kernelfork + exec(/bin/sh -c :) 990.7 µs4599 µs ~12000.22×
El fork de Eclipse copia eager, no copy-on-write. El ratio de 2.72× significa que bifurcar cuesta casi tres veces más que copiar el proceso con memcpy; Linux está en 0.39× porque comparte los frames y los protege contra escritura. Se ve en la pendiente: de 1 MiB a 16 MiB residentes, Eclipse pasa de 250 µs a 3423 µs (×13.7), mientras Linux apenas se mueve (2586 → 4011 µs). Aun así Eclipse gana casi todas las filas en absoluto porque su coste base de fork es 30× menor.

Lo que sí rompe es bajo carga: 25.7 ms por fork+exit frente a 1.5 ms de Linux, y sin diferencia entre 8 y 256 mapeos — a esa escala el coste ya no es de la capa VM, es esperar CPU. Es el mismo problema de scheduling que la sección anterior.

Ratios independientes del hardware

Estas sobreviven a correr en una VM: cada una es una división entre dos medidas de la misma máquina.

MétricaEclipseLinuxhint
syscall cost in CPU ops 523.8 ops98.8 ops ~150–250
context switch / syscall 16.0 ×66.3 × ~100
wake late loaded/idle (mean) 22.7 ×0.64 × ~1–3
wake late loaded/idle (worst) ← interactividad 20.3 ×0.47 × ~1–5
SMP efficiency 75.4 %85.0 % >90
fork copy ratio 2.72 ×0.39 × COW ~0.3, eager ≥1
wake late loaded/idle es el titular. Un valor cerca de 1 significa que una tarea despertada consigue CPU al instante aunque la máquina esté ocupada. Linux está en 0.64× / 0.47× (bajo carga despierta incluso antes que en reposo, porque las CPUs no llegan a dormirse). Eclipse está en 22.7× / 20.3×: espera a que se agote la rodaja de otro. Eso es el tirón que se nota al usarlo.

El context switch / syscall de 16× frente a 66× de Linux no es una victoria real: el denominador de Eclipse (su syscall) ya es 5.6× más caro, así que el cociente sale bajo porque la referencia es mala, no porque el cambio de contexto sea barato.