Skip to content

Commit

Permalink
update slice builder
Browse files Browse the repository at this point in the history
  • Loading branch information
thatstoasty committed May 31, 2024
1 parent 1bc15b5 commit 69d7d2c
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 14 deletions.
20 changes: 15 additions & 5 deletions gojo/strings/builder.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite


@value
struct NewStringBuilder(Stringable, Sized):
struct NewStringBuilder[growth_factor: Float32 = 2](Stringable, Sized):
"""
A string builder class that allows for efficient string management and concatenation.
This class is useful when you need to build a string by appending multiple strings
Expand Down Expand Up @@ -164,6 +164,7 @@ struct NewStringBuilder(Stringable, Sized):

@always_inline
fn __init__(inout self, *, capacity: Int = 4096):
constrained[growth_factor >= 1.25]()
self.data = DTypePointer[DType.uint8]().alloc(capacity)
self.size = 0
self.capacity = capacity
Expand All @@ -177,10 +178,19 @@ struct NewStringBuilder(Stringable, Sized):
The string representation of the string builder. Returns an empty
string if the string builder is empty.
"""
var copy = DTypePointer[DType.uint8]().alloc(self.size + 1)
var copy = DTypePointer[DType.uint8]().alloc(self.size)
memcpy(copy, self.data, self.size)
copy[self.size] = 0
return StringRef(copy, self.size + 1)
return StringRef(copy, self.size)

@always_inline
fn render(self: Reference[Self]) -> StringSlice[self.is_mutable, self.lifetime]:
"""
Return a StringSlice view of the data owned by the builder.
Returns:
The string representation of the string builder. Returns an empty string if the string builder is empty.
"""
return StringSlice[self.is_mutable, self.lifetime](unsafe_from_utf8_strref=StringRef(self[].data, self[].size))

@always_inline
fn __del__(owned self):
Expand Down Expand Up @@ -212,7 +222,7 @@ struct NewStringBuilder(Stringable, Sized):
src: The byte array to append.
"""
if len(src) > self.capacity - self.size:
self._resize(self.capacity * 2)
self._resize(int(self.capacity * growth_factor))

memcpy(self.data.offset(self.size), src._data, len(src))
self.size += len(src)
Expand Down
2 changes: 1 addition & 1 deletion goodies/std.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct STDWriter(Copyable, io.Writer, io.StringWriter):
)

if write_count == -1:
return 0, Error("Failed to write to file descriptor " + String(self.fd))
return 0, Error("Failed to write to file descriptor " + str(self.fd))

return write_count, Error()

Expand Down
17 changes: 12 additions & 5 deletions tests/test_performance.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fn test_string_builder() raises:
# Create a string from the buffer
var builder_write_start_time = now()
var builder = StringBuilder()
for _ in range(100):
for _ in range(10000):
_ = builder.write_string(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod"
" tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim"
Expand All @@ -30,7 +30,7 @@ fn test_string_builder() raises:
# Create a string from the buffer
var new_builder_write_start_time = now()
var new_builder = NewStringBuilder()
for _ in range(100):
for _ in range(10000):
_ = new_builder.write_string(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod"
" tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim"
Expand All @@ -47,10 +47,16 @@ fn test_string_builder() raises:
var new_builder_execution_time = now() - new_builder_start_time
print("NewStringBuilder buffer len", len(new_output), "\n")

var new_builder_render_start_time = now()
var new_output_render = str(new_builder.render())
var new_builder_render_execution_time = now() - new_builder_render_start_time
print("NewStringBuilder buffer len", len(new_output_render), "\n")
# print(new_output_render)

# Create a string using the + operator
print("Testing string concatenation performance")
var vec = List[String]()
for i in range(100):
for i in range(10000):
vec.append(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod"
" tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim"
Expand All @@ -72,7 +78,7 @@ fn test_string_builder() raises:
var buffer_write_start_time = now()
print("Testing bytes buffer performance")
var buf = buffer.new_buffer()
for i in range(100):
for i in range(10000):
_ = buf.write_string(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod"
" tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim"
Expand All @@ -92,11 +98,12 @@ fn test_string_builder() raises:
print("\nWrite times:")
print("StringBuilder:", "(", builder_write_execution_time, "ns)")
print("NewStringBuilder:", "(", new_builder_write_execution_time, "ns)")
print("Bytes buffer write time:", "(", buffer_write_execution_time, "ns)", "\n")
print("Bytes buffer write time:", "(", buffer_write_execution_time, "ns)")

print("\nExecution times:")
print("StringBuilder:", "(", builder_execution_time, "ns)")
print("NewStringBuilder:", "(", new_builder_execution_time, "ns)")
print("NewStringBuilder Render:", "(", new_builder_render_execution_time, "ns)")
print("String concat:", "(", concat_execution_time, "ns)")
print("Bytes Buffer:", "(", buffer_execution_time, "ns)")

Expand Down
6 changes: 3 additions & 3 deletions tests/test_strings_stringbuilder.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn test_write_string() raises:
_ = builder.write_string("Lorem ipsum dolor sit amet ")

test.assert_equal(
String(builder),
str(builder),
"Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet ",
)

Expand All @@ -24,7 +24,7 @@ fn test_write() raises:
# Create a string from the builder by writing bytes to it.
var builder = StringBuilder()
_ = builder.write(String("Hello").as_bytes())
test.assert_equal(String(builder), "Hello")
test.assert_equal(str(builder), "Hello")


fn test_write_byte() raises:
Expand All @@ -33,7 +33,7 @@ fn test_write_byte() raises:
# Create a string from the builder by writing bytes to it.
var builder = StringBuilder()
_ = builder.write_byte(32)
test.assert_equal(String(builder), " ")
test.assert_equal(str(builder), " ")


fn main() raises:
Expand Down

0 comments on commit 69d7d2c

Please sign in to comment.