Fixed some bugs & added some optimizations for single threaded
Removed old run_tests.sh & added benchmark.sh
This commit is contained in:
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
ARCHIVE="testing/LinuxPATest.sfs"
|
||||
|
||||
REF_EXT_LOC="testing/LinuxPAReference"
|
||||
PROG_EXT_LOC="testing/LinuxPABinTest"
|
||||
|
||||
echo "Testing Multi-threaded Performance"
|
||||
echo ""
|
||||
|
||||
hyperfine --warmup 5 --prepare "rm -rf $REF_EXT_LOC && rm -rf $PROG_EXT_LOC" "unsquashfs -d $REF_EXT_LOC $ARCHIVE" "zig-out/bin/unsquashfs -d $PROG_EXT_LOC $ARCHIVE"
|
||||
|
||||
echo ""
|
||||
echo "Testing Single-threaded Performance"
|
||||
echo ""
|
||||
|
||||
hyperfine --warmup 5 --prepare "rm -rf $REF_EXT_LOC && rm -rf $PROG_EXT_LOC" "unsquashfs -p 1 -d $REF_EXT_LOC $ARCHIVE" "zig-out/bin/unsquashfs -p 1 -d $PROG_EXT_LOC $ARCHIVE"
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
zig test \
|
||||
-lc \
|
||||
-lz \
|
||||
-llzma \
|
||||
-lminilzo \
|
||||
-llz4 \
|
||||
-lzstd \
|
||||
src/test.zig
|
||||
+4
-3
@@ -83,7 +83,8 @@ pub fn extract(self: *Archive, alloc: std.mem.Allocator, io: Io, ext_loc: []cons
|
||||
self.super.block_size,
|
||||
self.super.root_ref,
|
||||
);
|
||||
return Extract.extract(alloc, io, root_inode, &self.cache, self.super, ext_loc, options);
|
||||
|
||||
return Extract.extractSingleThreaded(alloc, io, root_inode, &self.cache, self.super, ext_loc, options);
|
||||
}
|
||||
|
||||
// Superblock
|
||||
@@ -126,12 +127,12 @@ pub const Superblock = extern struct {
|
||||
pub fn validate(self: Superblock) !void {
|
||||
if (self.magic != std.mem.readInt(u32, "hsqs", .little))
|
||||
return error.BadMagic;
|
||||
if (self.flags.check)
|
||||
return error.BadCheckFlag;
|
||||
if (self.ver_maj != 4 or self.ver_min != 0)
|
||||
return error.InvalidVersion;
|
||||
if (self.block_log != std.math.log2(self.block_size))
|
||||
return error.BadBlockLog;
|
||||
if (self.flags.check)
|
||||
return error.BadCheckFlag;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -48,7 +48,7 @@ pub fn init(io: Io, cache: *DecompCache, block_size: u32, size: u64, start: u64,
|
||||
};
|
||||
}
|
||||
pub fn deinit(self: Reader) void {
|
||||
self.cache.finished(self.io);
|
||||
self.cache.finished(self.io, self.cur_offset);
|
||||
}
|
||||
|
||||
pub fn addFragment(self: *Reader, data: []u8, offset: u32) void {
|
||||
@@ -98,7 +98,7 @@ fn advance(self: *Reader) Io.Reader.Error!void {
|
||||
self.interface.end = size;
|
||||
return;
|
||||
}
|
||||
const data = self.cache.get(self.io, self.cur_offset, block.size, size);
|
||||
const data = self.cache.get(self.io, self.cur_offset, block.size, @truncate(size)) catch return error.ReadFailed;
|
||||
if (data.len != size) {
|
||||
std.debug.print("Size of decompression at {} is {} and should be {}\n", .{ self.cur_offset, data.len, size });
|
||||
return Io.Reader.Error.ReadFailed;
|
||||
|
||||
@@ -87,7 +87,7 @@ pub fn get(self: *DecompCache, io: Io, offset: u64, compressed_size: u32, max_si
|
||||
pub fn finished(self: *DecompCache, io: Io, offset: u64) void {
|
||||
const cache = self.cache.getPtr(offset);
|
||||
if (cache == null) {
|
||||
std.debug.print("Finished using cache, but cache does not exist: {}\n", .{offset});
|
||||
// std.debug.print("Finished using cache, but cache does not exist: {}\n", .{offset});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+29
-67
@@ -2,7 +2,6 @@ const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const Atomic = std.atomic.Value;
|
||||
|
||||
const DataExtractor = @import("data/extractor.zig");
|
||||
const DataReader = @import("data/reader.zig");
|
||||
const DecompCache = @import("decomp_cache.zig");
|
||||
const Directory = @import("directory.zig");
|
||||
@@ -12,7 +11,7 @@ const Lookup = @import("lookup.zig");
|
||||
const Superblock = @import("archive.zig").Superblock;
|
||||
const XattrTable = @import("xattr.zig");
|
||||
|
||||
pub fn extract(alloc: std.mem.Allocator, io: Io, inode: Inode, cache: *DecompCache, super: Superblock, ext_loc: []const u8, options: ExtractionOptions) !void {
|
||||
pub fn extractSingleThreaded(alloc: std.mem.Allocator, io: Io, inode: Inode, cache: *DecompCache, super: Superblock, ext_loc: []const u8, options: ExtractionOptions) !void {
|
||||
const path = std.mem.trim(u8, ext_loc, "/");
|
||||
|
||||
var id_table: Lookup.Table(u16) = .init(alloc, cache, super.id_start, super.id_count);
|
||||
@@ -72,7 +71,7 @@ fn extractDir(
|
||||
options: ExtractionOptions,
|
||||
path: []const u8,
|
||||
inode: Inode,
|
||||
) Error!DirReturn(false) {
|
||||
) Error!DirReturn {
|
||||
try Io.Dir.cwd().createDirPath(io, path);
|
||||
|
||||
const dir = inode.directory(alloc, io, cache, super.dir_start) catch |err| switch (err) {
|
||||
@@ -81,7 +80,7 @@ fn extractDir(
|
||||
};
|
||||
defer dir.deinit(alloc);
|
||||
|
||||
const ret: DirReturn(false) = .{
|
||||
const ret: DirReturn = .{
|
||||
.hdr = inode.hdr,
|
||||
.path = path,
|
||||
|
||||
@@ -122,18 +121,18 @@ fn extractFile(
|
||||
frag_table: *Lookup.Table(Lookup.FragmentEntry),
|
||||
path: []const u8,
|
||||
inode: Inode,
|
||||
) Error!FileReturn(false) {
|
||||
) Error!FileReturn {
|
||||
var atomic = try Io.Dir.cwd().createFileAtomic(io, path, .{});
|
||||
defer atomic.deinit(io);
|
||||
|
||||
var ret: FileReturn(false) = .{
|
||||
var ret: FileReturn = .{
|
||||
.hdr = inode.hdr,
|
||||
.path = path,
|
||||
};
|
||||
|
||||
const data: DataExtractor = switch (inode.data) {
|
||||
var data: DataReader = switch (inode.data) {
|
||||
.file => |f| blk: {
|
||||
var data: DataExtractor = .init(cache, block_size, f.size, f.data_start, f.blocks);
|
||||
var data: DataReader = .init(io, cache, block_size, f.size, f.data_start, f.blocks);
|
||||
if (f.frag_idx != 0xFFFFFFFF) {
|
||||
const entry: Lookup.FragmentEntry = try frag_table.get(io, f.frag_idx);
|
||||
if (entry.size.uncompressed) {
|
||||
@@ -146,7 +145,7 @@ fn extractFile(
|
||||
break :blk data;
|
||||
},
|
||||
.ext_file => |f| blk: {
|
||||
var data: DataExtractor = .init(cache, block_size, f.size, f.data_start, f.blocks);
|
||||
var data: DataReader = .init(io, cache, block_size, f.size, f.data_start, f.blocks);
|
||||
if (f.frag_idx != 0xFFFFFFFF) {
|
||||
const entry: Lookup.FragmentEntry = try frag_table.get(io, f.frag_idx);
|
||||
if (entry.size.uncompressed) {
|
||||
@@ -162,7 +161,12 @@ fn extractFile(
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
try data.asyncExtract(io, atomic.file);
|
||||
defer data.deinit();
|
||||
|
||||
var wrt_buf: [1024]u8 = undefined;
|
||||
var wrt = atomic.file.writer(io, &wrt_buf);
|
||||
_ = try data.interface.streamRemaining(&wrt.interface);
|
||||
try wrt.flush();
|
||||
|
||||
try atomic.link(io);
|
||||
|
||||
@@ -177,8 +181,8 @@ fn extractSymlink(io: Io, path: []const u8, inode: Inode) Error!void {
|
||||
|
||||
try Io.Dir.cwd().symLink(io, target, path, .{});
|
||||
}
|
||||
fn extractNod(alloc: std.mem.Allocator, path: []const u8, inode: Inode) Error!FileReturn(false) {
|
||||
var ret: FileReturn(false) = .{
|
||||
fn extractNod(alloc: std.mem.Allocator, path: []const u8, inode: Inode) Error!FileReturn {
|
||||
var ret: FileReturn = .{
|
||||
.hdr = inode.hdr,
|
||||
.path = path,
|
||||
};
|
||||
@@ -259,67 +263,25 @@ fn setMetadata(alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), x
|
||||
}
|
||||
|
||||
const Error = error{ Canceled, MknodError, SetXattrError } || Directory.Error || Io.Dir.CreateFileAtomicError || Io.File.Atomic.LinkError ||
|
||||
DataExtractor.Error || Io.Dir.SymLinkError || Io.Dir.CreateDirPathError;
|
||||
Io.Dir.SymLinkError || Io.Dir.CreateDirPathError || Io.Reader.StreamError || Io.File.SetPermissionsError;
|
||||
|
||||
const ReturnUnion = union(enum) {
|
||||
file: Error!FileReturn,
|
||||
dir: Error!DirReturn(true),
|
||||
void: Error!void,
|
||||
const FileReturn = struct {
|
||||
hdr: Inode.Header,
|
||||
path: []const u8,
|
||||
|
||||
xattr_idx: ?u32 = null,
|
||||
|
||||
fn finish(self: FileReturn, alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xattr_table: *XattrTable, options: ExtractionOptions) Error!void {
|
||||
return setMetadata(alloc, io, id_table, xattr_table, options, self.hdr, self.xattr_idx, self.path);
|
||||
}
|
||||
};
|
||||
|
||||
fn FileReturn(comptime async: bool) type {
|
||||
return if (async)
|
||||
struct {
|
||||
hdr: Inode.Header,
|
||||
path: []const u8,
|
||||
parent: ?*Atomic(u32),
|
||||
|
||||
xattr_idx: ?u32 = null,
|
||||
|
||||
fn finish(self: FileReturn(async), alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xattr_table: *XattrTable, options: ExtractionOptions) Error!void {
|
||||
defer if (self.parent != null) {
|
||||
_ = self.parent.?.fetchSub(1, .acquire);
|
||||
};
|
||||
return setMetadata(alloc, io, id_table, xattr_table, options, self.hdr, self.xattr_idx, self.path);
|
||||
}
|
||||
}
|
||||
else
|
||||
struct {
|
||||
const DirReturn = struct {
|
||||
hdr: Inode.Header,
|
||||
path: []const u8,
|
||||
|
||||
xattr_idx: ?u32 = null,
|
||||
|
||||
fn finish(self: FileReturn(async), alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xattr_table: *XattrTable, options: ExtractionOptions) Error!void {
|
||||
fn finish(self: DirReturn, alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xattr_table: *XattrTable, options: ExtractionOptions) Error!void {
|
||||
return setMetadata(alloc, io, id_table, xattr_table, options, self.hdr, self.xattr_idx, self.path);
|
||||
}
|
||||
};
|
||||
}
|
||||
fn DirReturn(comptime async: bool) type {
|
||||
return if (async)
|
||||
struct {
|
||||
hdr: Inode.Header,
|
||||
path: []const u8,
|
||||
parent: ?*Atomic(u32),
|
||||
|
||||
xattr_idx: ?u32 = null,
|
||||
|
||||
fn finish(self: DirReturn(async), alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xattr_table: *XattrTable, options: ExtractionOptions) Error!void {
|
||||
defer if (self.parent != null) {
|
||||
_ = self.parent.?.fetchSub(1, .acquire);
|
||||
};
|
||||
return setMetadata(alloc, io, id_table, xattr_table, options, self.hdr, self.xattr_idx, self.path);
|
||||
}
|
||||
}
|
||||
else
|
||||
struct {
|
||||
hdr: Inode.Header,
|
||||
path: []const u8,
|
||||
|
||||
xattr_idx: ?u32 = null,
|
||||
|
||||
fn finish(self: DirReturn(async), alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xattr_table: *XattrTable, options: ExtractionOptions) Error!void {
|
||||
return setMetadata(alloc, io, id_table, xattr_table, options, self.hdr, self.xattr_idx, self.path);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -103,5 +103,5 @@ pub fn open(self: *SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const
|
||||
}
|
||||
|
||||
pub fn extract(self: *SfsFile, alloc: std.mem.Allocator, io: Io, ext_dir: []const u8, options: ExtractionOptions) !void {
|
||||
return Extract.extract(alloc, io, self.inode, &self.archive.cache, self.archive.super, ext_dir, options);
|
||||
return Extract.extractSingleThreaded(alloc, io, self.inode, &self.archive.cache, self.archive.super, ext_dir, options);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user