User Tools

Site Tools


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;
}