Golang string inside
type stringStruct struct {
str unsafe.Pointer
len int
}
func rawstring(size int) (s string, b []byte) {
p := mallocgc(uintptr(size), nil, false)
stringStructOf(&s).str = p
stringStructOf(&s).len = size
*(*slice)(unsafe.Pointer(&b)) = slice{p, size, size}
return
}
type slice struct {
array unsafe.Pointer
len int
cap int
}
- test.go
/*
* Copyright 2022 Oleg Borodin <borodin@unix7.org>
*/
package main
import (
"testing"
)
func dummys(str string) {
}
func dummyb(bstr []byte) {
}
func BenchmarkStrCat1(b *testing.B) {
str := "1234567qwerty"
pBench := func(pb *testing.PB) {
for pb.Next() {
nstr := str + str
dummys(nstr)
}
}
b.SetParallelism(10)
b.RunParallel(pBench)
}
func BenchmarkStrCat2(b *testing.B) {
str := []byte("1234567qwerty")
pBench := func(pb *testing.PB) {
for pb.Next() {
nstr := string(str) + string(str)
dummys(nstr)
}
}
b.SetParallelism(10)
b.RunParallel(pBench)
}
func BenchmarkStrCat3(b *testing.B) {
str := []byte("1234567qwerty")
bstr := make([]byte, 0, 32)
bstr = append(bstr, str...)
pBench := func(pb *testing.PB) {
for pb.Next() {
nstr := append(bstr, bstr...)
dummyb(nstr)
}
}
b.SetParallelism(10)
b.RunParallel(pBench)
}
func BenchmarkStrCat4(b *testing.B) {
str := []byte("1234567qwerty")
bstr := make([]byte, 0, 64)
bstr = append(bstr, str...)
pBench := func(pb *testing.PB) {
for pb.Next() {
nstr := append(bstr, bstr...)
dummys(string(nstr))
}
}
b.SetParallelism(10)
b.RunParallel(pBench)
}
# go test -bench=. -benchtime=1s -benchmem
goos: freebsd
goarch: amd64
cpu: Intel(R) Core(TM) i5-4300U CPU @ 1.90GHz
BenchmarkStrCat1-4 83143010 13.35 ns/op 0 B/op 0 allocs/op
BenchmarkStrCat2-4 64920298 18.34 ns/op 0 B/op 0 allocs/op
BenchmarkStrCat3-4 92924496 13.05 ns/op 0 B/op 0 allocs/op
BenchmarkStrCat4-4 54096423 22.37 ns/op 0 B/op 0 allocs/op
PASS
C near
- bstream.h
/*
* Copyright 2022 Oleg Borodin <borodin@unix7.org>
*/
#ifndef BSTREAM_H_QWERTY
#define BSTREAM_H_QWERTY
#include <stdint.h>
#define BSTREAM_ICAPA 1024
typedef struct {
size_t size;
size_t capa;
size_t rpos;
uint8_t* data;
} bstream_t;
bstream_t* new_bstream();
size_t bstream_write(bstream_t* stream, const uint8_t* data, size_t size);
size_t bstream_read(bstream_t* stream, uint8_t* buf, size_t size);
size_t bstream_rsize(const bstream_t* stream);
void bstream_free(bstream_t* stream);
#endif
- bstream.c
/*
* Copyright 2022 Oleg Borodin <borodin@unix7.org>
*/
#include <sys/endian.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <bstream.h>
bstream_t* new_bstream() {
uint64_t icapa = BSTREAM_ICAPA;
bstream_t* stream = malloc(icapa);
if (stream == NULL) return NULL;
stream->data = malloc(icapa);
if (stream->data == NULL) {
free(stream);
return NULL;
}
memset(stream->data, 0, icapa);
stream->size = 0;
stream->rpos = 0;
stream->capa = icapa;
return stream;
}
size_t bstream_write(bstream_t* stream, const uint8_t* data, size_t size) {
//if (stream == NULL) return 0;
if ((stream->capa - stream->size) < size) {
size_t new_capa = stream->capa * 2;
if ((new_capa - stream->size) < size) {
new_capa += size;
}
uint8_t* new_data = realloc(stream->data, new_capa);
if (new_data == NULL) {
return 0;
}
stream->data = new_data;
stream->capa = new_capa;
}
memcpy(&(stream->data[stream->size]), data, size);
stream->size += size;
return size;
}
size_t bstream_read(bstream_t* stream, uint8_t* buf, size_t size) {
if (stream == NULL) return 0;
size_t rsize = stream->size - stream->rpos;
if (rsize < 0) {
return 0;
}
if (rsize < size) {
size = rsize;
}
memcpy(buf, &(stream->data[stream->rpos]), size);
stream->rpos += size;
return size;
}
size_t bstream_rsize(const bstream_t* stream) {
return stream->size - stream->rpos;
}
void bstream_free(bstream_t* stream) {
free(stream->data);
free(stream);
stream = NULL;
}