Skip to content

Instantly share code, notes, and snippets.

@feelfreetofee
Last active September 21, 2024 17:14
Show Gist options
  • Select an option

  • Save feelfreetofee/a076c0385e4a4ea88eb8e650aa641956 to your computer and use it in GitHub Desktop.

Select an option

Save feelfreetofee/a076c0385e4a4ea88eb8e650aa641956 to your computer and use it in GitHub Desktop.
Bencode module inspired on https://github.com/webtorrent/node-bencode
const types = {
100(data, position) { // d
position[0]++
const dictionary = {}
while (data[position[0]] !== 101) dictionary[buffer(data, position)] = decode(data, position)
position[0]++
return dictionary
},
108(data, position) { // l
position[0]++
const list = []
while (data[position[0]] !== 101) list.push(decode(data, position))
position[0]++
return list
},
105: (data, position) => parseInt(data.toString('ascii', position[0] + 1, (position[0] = data.indexOf(101, position[0]) + 1) - 1)) // i
}
const buffer = (data, position, sep) => data.slice(sep = data.indexOf(58, position[0]) + 1, position[0] = sep + parseInt(data.toString(undefined, position[0], sep - 1)))
export const decode = (data, position = [0]) => data[position[0]] in types ? types[data[position[0]]]?.(data, position) : buffer(data, position).toString('ascii')
export function encode(data) {
const type = typeof data
if (type === 'string')
return (data.length + (encodeURIComponent(data).match(/%[89ABab]/g)?.length || 0)) + ':' + data
else if (type === 'number')
return 'i' + data + 'e'
let buffer = data instanceof Array ? 'l' : 'd'
if (buffer == 'l')
for (const value of data)
buffer += encode(value)
else
for (const key of Object.keys(data).sort())
buffer += encode(key) + encode(data[key])
return buffer + 'e'
}
@feelfreetofee
Copy link
Author

feelfreetofee commented Mar 12, 2024

Some benchmarks:

Mine		60 seconds	61561 iterations
Webtorrent	60 seconds	61895 iterations
Mine		120 seconds	123274 iterations
Webtorrent	120 seconds	121057 iterations
Mine		300 seconds	300362 iterations
Webtorrent	300 seconds	305824 iterations

Mine		10k iterations	9612 milliseconds
Webtorrent	10k iterations	9613 milliseconds
Mine		100k iterations	95373 milliseconds
Webtorrent	100k iterations	96158 milliseconds
Mine		1m iterations	943118 milliseconds
Webtorrent	1m iterations	961008 milliseconds
Mine		60 seconds	63582 iterations
Webtorrent	60 seconds	62816 iterations
Mine		120 seconds	125730 iterations
Webtorrent	120 seconds	124865 iterations
Mine		300 seconds	314340 iterations
Webtorrent	300 seconds	312137 iterations

Mine		10k iterations	9337 ms
Webtorrent	10k iterations	9450 ms
Mine		100k iterations	93294 ms
Webtorrent	100k iterations	95330 ms
Mine		1m iterations	985772 ms
Webtorrent	1m iterations	1014818 ms
Mine		60 seconds	63621 iterations
Webtorrent	60 seconds	62967 iterations
Mine		120 seconds	126177 iterations
Webtorrent	120 seconds	121301 iterations
Mine		300 seconds	300402 iterations
Webtorrent	300 seconds	298310 iterations

Mine		10k iterations	9847 ms
Webtorrent	10k iterations	10057 ms
Mine		100k iterations	99325 ms
Webtorrent	100k iterations	102688 ms
Mine		1m iterations	1007355 ms
Webtorrent	1m iterations	1008157 ms

Code:

function benchmarkT(time, func, ...args) {
	time = time * 1e3 + Date.now()
	let iterations = 0
	do func(...args)
	while (Date.now() < time && ++iterations)
	return iterations
}

function benchmarkI(iterations, func, ...args) {
	const time = Date.now()
	for (let i = 0; i < iterations; i++) func(...args)
	return Date.now() - time
}

const code = Buffer.from(await Bun.file('test.torrent').arrayBuffer())

import {decode} from './bencode' // Mine
import {default as bencode} from 'bencode' // Webtorrent

console.log('Mine', '60 seconds', benchmarkT(60, decode,  code), 'iterations')
console.log('Webtorrent', '60 seconds', benchmarkT(60, bencode.decode, code, 'utf8'), 'iterations')

console.log('Mine', '120 seconds', benchmarkT(120, decode,  code), 'iterations')
console.log('Webtorrent', '120 seconds', benchmarkT(120, bencode.decode, code, 'utf8'), 'iterations')

console.log('Mine', '300 seconds', benchmarkT(300, decode,  code), 'iterations')
console.log('Webtorrent', '300 seconds', benchmarkT(300, bencode.decode, code, 'utf8'), 'iterations')

console.log('Mine', '10k iterations', benchmarkI(1e4, decode,  code), 'milliseconds')
console.log('Webtorrent', '10k iterations', benchmarkI(1e4, bencode.decode, code, 'utf8'), 'milliseconds')

console.log('Mine', '100k iterations', benchmarkI(1e5, decode,  code), 'milliseconds')
console.log('Webtorrent', '100k iterations', benchmarkI(1e5, bencode.decode, code, 'utf8'), 'milliseconds')

console.log('Mine', '1m iterations', benchmarkI(1e6, decode,  code), 'milliseconds')
console.log('Webtorrent', '1m iterations', benchmarkI(1e6, bencode.decode, code, 'utf8'), 'milliseconds')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment