Commit f7c2f706 authored by Shu's avatar Shu 🍠
Browse files

Remove some useless allocations

parent 9e9bb898
......@@ -370,10 +370,9 @@ namespace contouring {
const auto area_offset = glm::divide(std::get<0>(area.first).as_voxel());
robin_hood::unordered_set<chunk_pos> done;
for (const auto& occ: occlusion) {
const geometry::Ray ray(start, occ, dist);
std::vector<voxel_pos> points; //TODO: iterator
ray.grid(points);
for(auto& point: points) {
geometry::Ray::iterator it(geometry::Ray(start, occ, dist));
glm::llvec3 point;
while (it.next(point)) {
auto it = area.second.find(glm::lvec3(point) - area_offset);
const auto buffer = solid ? it->second.first : it->second.second;
if(it != area.second.end() && buffer != NULL && done.insert(it->first).second) {
......
......@@ -61,9 +61,17 @@ int Client::connectionCallback(uint64_t stream_id, uint8_t* bytes, size_t length
case picoquic_callback_stream_fin: {
assert(stream_ctx::IsServerId(stream_id));
auto stream_ctx = (in_stream_ctx *)v_stream_ctx;
const auto is_fin = fin_or_event == picoquic_callback_stream_fin;
/* Data arrival on stream #x, maybe with fin mark */
if (stream_ctx == NULL) { // New stream from server
if (stream_ctx == NULL) {
if (is_fin) { // Single frame packet
if (length > 0) {
onPacket(data::out_view(bytes, length), PacketFlags::TINY);
}
reset(stream_id);
break;
}
// New long stream from server
stream_ctx = receive(stream_id);
}
......@@ -71,7 +79,7 @@ int Client::connectionCallback(uint64_t stream_id, uint8_t* bytes, size_t length
stream_ctx->buffer.write(bytes, length);
}
if (fin_or_event == picoquic_callback_stream_fin) {
if (is_fin) {
if (onPacket(data::out_view(stream_ctx->buffer.data.data(), stream_ctx->buffer.data.size()), PacketFlags::NONE)) {
close(stream_ctx);
} else {
......
#pragma once
#include <fstream>
#include <vector>
#include "../data/mem.hpp"
#include "../utils/logger.hpp"
namespace data {
......@@ -9,7 +9,9 @@ namespace data {
class file_content: public std::vector<char> {
public:
// Read first
file_content(const std::vector<std::string>& paths): std::vector<char>() {
file_content(const std::vector<std::string>& paths, data::out_view prefix = data::out_view(nullptr, 0)):
std::vector<char>(), prefix_size(prefix.size())
{
std::ifstream is = [&]() {
for(auto& path: paths) {
std::ifstream is(path, std::ios::in | std::ios::binary | std::ios::ate);
......@@ -22,10 +24,18 @@ public:
}();
const auto end = is.tellg();
is.seekg(0, std::ios::beg);
resize(end - is.tellg());
is.read(data(), size());
resize(end - is.tellg() + prefix_size);
memcpy(data(), prefix.ptr, prefix_size);
is.read(data() + prefix_size, size());
is.close();
}
size_t prefix_size;
/// Data after prefix
data::out_view content() const {
return data::out_view((const uint8_t*)data() + prefix_size, size() - prefix_size);
}
};
}
\ No newline at end of file
......@@ -2,6 +2,7 @@
#include <vector>
#include <cassert>
#include <cstring>
#include <memory>
namespace data {
......
......@@ -83,6 +83,55 @@ namespace geometry {
}
points.push_back(current);
}
/// Iterator implementation of grid
struct iterator {
enum class axis { X, Y, Z };
iterator(const Ray& r): current(r.from.as_voxel()),
d(r.dir * r.dist), l(glm::abs(d)),
dir((l.x >= l.y) && (l.x >= l.z) ? axis::X : ((l.y >= l.x) && (l.y >= l.z) ? axis::Y : axis::Z)),
count(dir == axis::X ? l.x : (dir == axis::Y ? l.y : l.z)),
inc(swap(glm::llvec3((d.x < 0) ? -1 : 1, (d.y < 0) ? -1 : 1, (d.z < 0) ? -1 : 1), dir)),
delta(swap(l << 1ll, dir)), err_1(delta.y - count), err_2(delta.z - count) { }
static constexpr inline glm::llvec3 swap(const glm::llvec3& in, const axis dir) { return dir == axis::X ? in :
(dir == axis::Y ? glm::llvec3(in.y, in.z, in.x) : glm::llvec3(in.z, in.x, in.y)); }
static constexpr inline long long& get(glm::llvec3& in, const axis dir, const axis target) {
const axis v = (axis)(((int)dir + (int)target) % 3);
return v == axis::X ? in.x : (v == axis::Y ? in.y : in.z);
}
bool next(glm::llvec3& out) {
if (count < 0)
return false;
count--;
out = current;
if (err_1 > 0) {
get(current, dir, axis::Y) += inc.y;
err_1 -= delta.x;
}
if (err_2 > 0) {
get(current, dir, axis::Z) += inc.z;
err_2 -= delta.x;
}
err_1 += delta.y;
err_2 += delta.z;
get(current, dir, axis::X) += inc.x;
return true;
}
glm::llvec3 current;
const glm::llvec3 d;
const glm::llvec3 l;
const axis dir;
glm::llvec3::value_type count;
const glm::llvec3 inc;
const glm::llvec3 delta;
int err_1;
int err_2;
};
IBox::ContainmentType intersect(const IBox& box) const {
const glm::llvec3 start = from.as_voxel();
......
......@@ -31,6 +31,7 @@ struct in_stream_ctx: stream_ctx {
enum class PacketFlags {
NONE = 0,
DATAGRAM = 1 << 0,
TINY = 1 << 1,
};
/// Abstract QUIC context
......
......@@ -6,6 +6,8 @@
namespace net {
//TODO: preallocate static data pool
/// Write allocated packets
class PacketWriter final {
public:
PacketWriter(size_t size): buffer((uint8_t*)malloc(size), size) { }
......@@ -27,6 +29,37 @@ public:
write(&d, sizeof(d));
}
struct varying_part {
varying_part(data::in_view &buffer): buffer(buffer), visible_size(0) { }
~varying_part() {
buffer.siz = buffer.cur + visible_size;
buffer.cur = buffer.siz;
}
data::in_view &buffer;
size_t visible_size;
constexpr size_t size() const { return visible_size; }
void* data() { return buffer.writeTo(0); }
void reserve(size_t target) {
if (target >= buffer.siz - buffer.cur) {
auto old = buffer.ptr;
buffer.ptr = (uint8_t*)malloc(target);
memcpy(buffer.ptr, old, buffer.siz);
free(old);
buffer.siz = target;
}
}
void resize(size_t target) {
reserve(target);
visible_size = target;
}
};
/// Only from resize, write, resize down
varying_part varying() {
return varying_part(buffer);
}
bool isFull() const {
return buffer.isDone();
}
......
#pragma once
#include <zstd.h>
#include <vector>
#include <cassert>
#include "../data/mem.hpp"
#include "logger.hpp"
namespace zstd {
......@@ -73,6 +72,7 @@ namespace zstd {
class dict_set {
public:
dict_set(const std::vector<char>& data) { load(data.data(), data.size()); }
dict_set(const data::out_view& data) { load(data.data(), data.size()); }
~dict_set() {
ZSTD_freeCDict(c);
ZSTD_freeDDict(d);
......
......@@ -7,20 +7,19 @@ namespace world {
template<class Areas>
Universe::ray_result Raycast(const geometry::Ray& ray, const Areas& areas) {
//TODO: iterator
//MAYBE: ray + offset to get float precision
std::vector<voxel_pos> points;
ray.grid(points);
Universe::ray_result target;
size_t dist = points.size();
size_t dist = UINT32_MAX - 1;
for(auto& area: areas) {
if(ray.intersect(area.second->getBounding()) != geometry::IBox::ContainmentType::Disjoint) {
const auto &offset = area.second->getOffset().as_voxel();
const auto &chunks = area.second->getChunks();
std::shared_ptr<world::Chunk> chunk = nullptr;
chunk_pos chunk_vec(INT_MAX);
for (size_t i = 0; i < dist; i++) {
const auto pos = points[i] - offset;
geometry::Ray::iterator it(ray);
glm::llvec3 point;
for (size_t i = 0; i < dist && it.next(point); i++) {
const auto pos = point - offset;
const chunk_pos cPos = glm::divide(pos);
if(cPos != chunk_vec) {
if (const auto it = chunks.find(cPos); it != chunks.end()) {
......
......@@ -58,9 +58,17 @@ int Server::connectionCallback(Peer* peer, uint64_t stream_id, uint8_t* bytes, s
case picoquic_callback_stream_fin: {
assert(stream_ctx::IsClientId(stream_id));
auto stream_ctx = (in_stream_ctx *)v_stream_ctx;
const auto is_fin = fin_or_event == picoquic_callback_stream_fin;
/* Data arrival on stream #x, maybe with fin mark */
if (stream_ctx == NULL) { // New stream from peer
if (stream_ctx == NULL) {
if (is_fin) { // Single frame packet
if (length > 0) {
onPacket(peer, data::out_view(bytes, length), PacketFlags::TINY);
}
peer->reset(stream_id);
break;
}
// New long stream from server
stream_ctx = peer->receive(stream_id);
}
......@@ -68,7 +76,7 @@ int Server::connectionCallback(Peer* peer, uint64_t stream_id, uint8_t* bytes, s
stream_ctx->buffer.write(bytes, length);
}
if (fin_or_event == picoquic_callback_stream_fin) {
if (is_fin) {
if (onPacket(peer, data::out_view(stream_ctx->buffer.data.data(), stream_ctx->buffer.data.size()), PacketFlags::NONE)) {
peer->close(stream_ctx);
} else {
......
......@@ -14,12 +14,14 @@
using namespace world::server;
const auto AREAS_FILE = "/areas.idx";
const auto COMPRESSION_PREFIX = (uint8_t)net::server_packet_type::COMPRESSION;
Universe::Universe(const Universe::options &options): host(options.connection,
[&](net::server::Peer* peer) { return onConnect(peer); },
[&](net::server::Peer* peer, bool is_app, uint16_t reason) { return onDisconnect(peer, is_app, reason); },
[&](net::server::Peer* peer, const data::out_view &buf, net::PacketFlags flags) { return onPacket(peer, buf, flags); }
), dict_content({options.folderPath + "/zstd.dict", "content/zstd.dict"}), dicts(dict_content), dict_write_ctx(dicts.make_writer())
), dict_content({options.folderPath + "/zstd.dict", "content/zstd.dict"}, data::out_view(&COMPRESSION_PREFIX, sizeof(COMPRESSION_PREFIX))),
dicts(dict_content.content()), dict_write_ctx(dicts.make_writer())
{
setOptions(options);
folderPath = options.folderPath;
......@@ -453,9 +455,7 @@ std::optional<uint16_t> Universe::onConnect(net::server::Peer* peer) {
peer->send(net::PacketWriter::Of(net::server_packet_type::CAPABILITIES, loadDistance));
//TODO: lock while not received
//MAYBE: add net::server_packet_type::COMPRESSION to dict_content: zero copy
peer->send(net::PacketWriter::Of(net::server_packet_type::COMPRESSION, dict_content.data(), dict_content.size()), net::server::queue::CHUNK);
peer->send(data::out_buffer(data::out_view((uint8_t*)dict_content.data(), dict_content.size()), nullptr), net::server::queue::CHUNK);
{
auto player = findEntity(PLAYER_ENTITY_ID, client->instanceId);
auto packet = net::PacketWriter(net::server_packet_type::TELEPORT, sizeof(size_t) + sizeof(voxel_pos));
......@@ -582,12 +582,12 @@ data::out_buffer Universe::serializeChunk(area_<chunk_pos> id, const std::shared
ZoneScopedN("Chunk");
std::ostringstream out;
data->write(out);
std::vector<char> buffer;
//FIXME: avoid buffer copy
dict_write_ctx.compress(out.str(), buffer);
auto packet = net::PacketWriter(net::server_packet_type::CHUNK, sizeof(id) + buffer.size());
auto packet = net::PacketWriter(net::server_packet_type::CHUNK, sizeof(id));
packet.write(id);
packet.write(buffer.data(), buffer.size());
{
auto vec = packet.varying();
dict_write_ctx.compress(out.str(), vec);
}
return packet.finish();
}
void Universe::broadcastMessage(const std::string& text) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment