4 ms·
While the article does argue that faster isn't necessarily greener, I would interpret the data they show as confirmation of that assumption. Of course it isn't
by fabian2k 6y ago
While the article does argue that faster isn't necessarily greener, I would interpret the data they show as confirmation of that assumption. Of course it isn't always the case, but overall the rule holds up very well. And for smaller differences the effect of the specific workload is probably much larger.
What I find odd is that the table shows Typescript as 7x slower than Javascript. That can't be measuring the same thing, so not sure what is going on there.
- cnasc 6y ago> What I find odd is that the table shows Typescript as 7x slower than Javascript. Including type checking and transpilation in the timing, I assume.
- read_if_gay_ 6y agoThat would explain a lot. The speed rankings seemed kinda off to me as well. I found it surprising that both Swift and Go are listed as ~2 times slower than Java, and C++ 1.5 times as slow as C.
- igouy 6y agoCompilation takes place before measurement — fannkuchredux.go https://github.com/greensoftwarelab/Energy-Languages/blob/5c7df57485f37169eb47a48ec349d1d54dd69271/Go/fannkuch-redux/Makefile https://github.com/greensoftwarelab/Energy-Languages/blob/5c... fannkuchredux.java https://github.com/greensoftwarelab/Energy-Languages/blob/5c7df57485f37169eb47a48ec349d1d54dd69271/Java/fannkuch-redux/Makefile https://github.com/greensoftwarelab/Energy-Languages/blob/5c...
- IshKebab 6y agoI don't think so, otherwise Rust wouldn't have done well at all. I think the actual difference is that for some reason the language benchmarks game uses different code for Javascript and Typescript. E.g. the Javascript version of spectral-norm is multithreaded, using web workers, but the Typescript version is single threaded. Yeah it is stupid. https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/node-typescript.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- igouy 6y agoPlease contribute a Typescript equivalent of the multi threaded JavaScript program. I converted the ones I could, like: https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/fannkuchredux-typescript-5.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... :but I couldn't get the spectral-norm program to type check.
- IshKebab 6y agoLol ok I would but apparently I have to sign up to Debian Salsa and you can't sign up with a gmail account. I don't think they really want contributions! Anyway here is the code. I made some minor improvements that won't affect the runtime. You need to `npm install @types/node`. // The Computer Language Benchmarks Game // https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ // // contributed by Ian Osgood // Optimized by Roy Williams // modified for Node.js by Isaac Gouy // multi thread by Andrey Filatkin import { Worker as NodeWorker, isMainThread, parentPort, workerData } from 'worker_threads'; import * as os from 'os'; enum MessageVariant { Sab, Au, Atu, Exit, } interface SabMessage { variant: MessageVariant.Sab; data: Float64Array; } interface AuMessage { variant: MessageVariant.Au; vec1: UVWField, vec2: UVWField, } interface AtuMessage { variant: MessageVariant.Atu; vec1: UVWField, vec2: UVWField, } interface ExitMessage { variant: MessageVariant.Exit; } type Message = SabMessage | AuMessage | AtuMessage | ExitMessage; interface UVW { u: Float64Array; v: Float64Array; w: Float64Array; } type UVWField = keyof UVW; const bytesPerFloat = Float64Array.BYTES_PER_ELEMENT; if (isMainThread) { mainThread(+process.argv[2]); } else { workerThread(workerData); } async function mainThread(n: number) { const sab = new SharedArrayBuffer(3 * bytesPerFloat * n); const u = new Float64Array(sab, 0, n).fill(1); const v = new Float64Array(sab, bytesPerFloat * n, n); const workers = new Set<NodeWorker>(); startWorkers(); for (let i = 0; i < 10; i++) { await atAu('u', 'v', 'w'); await atAu('v', 'u', 'w'); } stopWorkers(); let vBv = 0; let vv = 0; for (let i = 0; i < n; i++) { vBv += u[i] * v[i]; vv += v[i] * v[i]; } const result = Math.sqrt(vBv / vv); console.log(result.toFixed(9)); async function atAu(u: UVWField, v: UVWField, w: UVWField) { await work({ variant: MessageVariant.Au, vec1: u, vec2: w }); await work({ variant: MessageVariant.Atu, vec1: w, vec2: v }); } function startWorkers() { const cpus = os.cpus().length; const chunk = Math.ceil(n / cpus); for (let i = 0; i < cpus; i++) { const start = i * chunk; let end = start + chunk; if (end > n) { end = n; } const worker = new NodeWorker(__filename, {workerData: {n, start, end}}); worker.postMessage({ variant: MessageVariant.Sab, data: sab }); workers.add(worker); } } function work(message: Message) { return new Promise(resolve => { let wait = 0; workers.forEach(worker => { worker.postMessage(message); worker.once('message', () => { wait--; if (wait === 0) { resolve(); } }); wait++; }); }); } function stopWorkers() { workers.forEach(worker => worker.postMessage({ variant: MessageVariant.Exit })); } } function workerThread({n, start, end}: {n: number, start: number, end: number}) { let data: UVW | undefined = undefined; if (parentPort === null) { return; } parentPort.on('message', (message: Message) => { switch (message.variant) { case MessageVariant.Sab: data = { u: new Float64Array(message.data, 0, n), v: new Float64Array(message.data, bytesPerFloat * n, n), w: new Float64Array(message.data, 2 * bytesPerFloat * n, n), }; break; case MessageVariant.Au: if (data === undefined) { throw Error('Au received before Sab'); } au(data[message.vec1], data[message.vec2]); parentPort!.postMessage({}); break; case MessageVariant.Atu: if (data === undefined) { throw Error('Atu received before Sab'); } atu(data[message.vec1], data[message.vec2]); parentPort!.postMessage({}); break; case MessageVariant.Exit: process.exit(); } }); function au(u: Float64Array, v: Float64Array) { for (let i = start; i < end; i++) { let t = 0; for (let j = 0; j < n; j++) { t += u[j] / a(i, j); } v[i] = t; } } function atu(u: Float64Array, v: Float64Array) { for (let i = start; i < end; i++) { let t = 0; for (let j = 0; j < n; j++) { t += u[j] / a(j, i); } v[i] = t; } } function a(i: number, j: number) { return ((i + j) * (i + j + 1) >>> 1) + i + 1; } }
- GordonS 6y agoThat seems like an odd way to compare things if so - compilation/transpilation will only happen once, then the code will run many times.
- igouy 6y agoNope — https://github.com/greensoftwarelab/Energy-Languages/blob/5c7df57485f37169eb47a48ec349d1d54dd69271/TypeScript/spectral-norm/Makefile https://github.com/greensoftwarelab/Energy-Languages/blob/5c...
- steego 6y agoIf it seems odd, it’s because they didn’t implement them the same way. The performance of the same program written in TypeScript and JavaScript should always be identical. TypeScript doesn’t add anything to the runtime. If they got this simple thing wrong, what else did they get wrong? Here’s the flawed study so you can see for yourself. https://github.com/greensoftwarelab/Energy-Languages https://github.com/greensoftwarelab/Energy-Languages