Skip to content

Commit d430755

Browse files
authored
Merge pull request #3061 from armanbilge/topic/native-no-more-zones
Native "`Array`-pointer" optimizations
2 parents 3878dca + 8f0a44b commit d430755

13 files changed

+312
-139
lines changed

build.sbt

+3
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ ThisBuild / mimaBinaryIssueFilters ++= Seq(
171171
),
172172
ProblemFilters.exclude[DirectMissingMethodProblem]( // something funky in Scala 3.2.0 ...
173173
"fs2.io.net.SocketGroupCompanionPlatform#AsyncSocketGroup.this"
174+
),
175+
ProblemFilters.exclude[DirectMissingMethodProblem](
176+
"fs2.io.net.tls.S2nConnection#RecvCallbackContext.readBuffer"
174177
)
175178
)
176179

core/native/src/main/scala/fs2/ChunkRuntimePlatform.scala

+13-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@
2121

2222
package fs2
2323

24+
import scala.scalanative.libc.string._
25+
import scala.scalanative.unsafe._
26+
import scala.scalanative.unsigned._
27+
2428
private[fs2] trait ChunkRuntimePlatform[+O]
2529

26-
private[fs2] trait ChunkCompanionRuntimePlatform
30+
private[fs2] trait ChunkCompanionRuntimePlatform {
31+
32+
def fromBytePtr(ptr: Ptr[Byte], length: Int): Chunk[Byte] = {
33+
val bytes = new Array[Byte](length)
34+
memcpy(bytes.at(0), ptr, length.toULong)
35+
Chunk.ArraySlice(bytes, 0, length)
36+
}
37+
38+
}

flake.lock

+120
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
inputs = {
3+
typelevel-nix.url = "github:typelevel/typelevel-nix";
4+
nixpkgs.follows = "typelevel-nix/nixpkgs";
5+
flake-utils.follows = "typelevel-nix/flake-utils";
6+
};
7+
8+
outputs = { self, nixpkgs, flake-utils, typelevel-nix }:
9+
flake-utils.lib.eachDefaultSystem (system:
10+
let
11+
pkgs = import nixpkgs {
12+
inherit system;
13+
overlays = [ typelevel-nix.overlay ];
14+
};
15+
in
16+
{
17+
devShell = pkgs.devshell.mkShell {
18+
imports = [ typelevel-nix.typelevelShell ];
19+
name = "fs2-shell";
20+
typelevelShell = {
21+
jdk.package = pkgs.jdk17;
22+
nodejs.enable = true;
23+
native.enable = true;
24+
native.libraries = [ pkgs.zlib pkgs.s2n-tls pkgs.openssl ];
25+
};
26+
};
27+
}
28+
);
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2013 Functional Streams for Scala
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
* this software and associated documentation files (the "Software"), to deal in
6+
* the Software without restriction, including without limitation the rights to
7+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8+
* the Software, and to permit persons to whom the Software is furnished to do so,
9+
* subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16+
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18+
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
*/
21+
22+
package fs2.io.internal
23+
24+
import cats.effect.kernel.Resource
25+
import cats.effect.kernel.Sync
26+
import cats.syntax.all._
27+
28+
import scala.scalanative.libc.errno._
29+
import scala.scalanative.libc.stdlib._
30+
import scala.scalanative.unsafe._
31+
import scala.scalanative.unsigned._
32+
33+
private[io] final class ResizableBuffer[F[_]] private (
34+
private var ptr: Ptr[Byte],
35+
private[this] var size: Int
36+
)(implicit F: Sync[F]) {
37+
38+
def get(size: Int): F[Ptr[Byte]] = F.delay {
39+
if (size <= this.size)
40+
F.pure(ptr)
41+
else {
42+
ptr = realloc(ptr, size.toUInt)
43+
this.size = size
44+
if (ptr == null)
45+
F.raiseError[Ptr[Byte]](new RuntimeException(s"realloc: ${errno}"))
46+
else F.pure(ptr)
47+
}
48+
}.flatten
49+
50+
}
51+
52+
private[io] object ResizableBuffer {
53+
54+
def apply[F[_]](size: Int)(implicit F: Sync[F]): Resource[F, ResizableBuffer[F]] =
55+
Resource.make {
56+
F.delay {
57+
val ptr = malloc(size.toUInt)
58+
if (ptr == null)
59+
throw new RuntimeException(s"malloc: ${errno}")
60+
else new ResizableBuffer(ptr, size)
61+
}
62+
}(buf => F.delay(free(buf.ptr)))
63+
64+
}

io/native/src/main/scala/fs2/io/net/tls/CertChainAndKey.scala

+8-10
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,14 @@ final class CertChainAndKey private (chainPem: ByteVector, privateKeyPem: ByteVe
3939
)
4040
.evalTap { certChainAndKey =>
4141
F.delay {
42-
Zone { implicit z =>
43-
guard_ {
44-
s2n_cert_chain_and_key_load_pem_bytes(
45-
certChainAndKey,
46-
chainPem.toPtr,
47-
chainPem.length.toUInt,
48-
privateKeyPem.toPtr,
49-
privateKeyPem.length.toUInt
50-
)
51-
}
42+
guard_ {
43+
s2n_cert_chain_and_key_load_pem_bytes(
44+
certChainAndKey,
45+
chainPem.toArray.at(0),
46+
chainPem.length.toUInt,
47+
privateKeyPem.toArray.at(0),
48+
privateKeyPem.length.toUInt
49+
)
5250
}
5351
}
5452
}

io/native/src/main/scala/fs2/io/net/tls/S2nConfig.scala

+3-9
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,7 @@ object S2nConfig {
9595

9696
_ <- pems.traverse_ { pem =>
9797
F.delay {
98-
Zone { implicit z =>
99-
guard_(s2n_config_add_pem_to_trust_store(cfg, toCString(pem)))
100-
}
98+
guard_(s2n_config_add_pem_to_trust_store(cfg, toCStringArray(pem).at(0)))
10199
}
102100
}.toResource
103101

@@ -123,17 +121,13 @@ object S2nConfig {
123121

124122
_ <- dhParams.traverse_ { pem =>
125123
F.delay {
126-
Zone { implicit z =>
127-
guard_(s2n_config_add_dhparams(cfg, toCString(pem)))
128-
}
124+
guard_(s2n_config_add_dhparams(cfg, toCStringArray(pem).at(0)))
129125
}
130126
}.toResource
131127

132128
_ <- cipherPreferences.traverse_ { version =>
133129
F.delay {
134-
Zone { implicit z =>
135-
guard_(s2n_config_set_cipher_preferences(cfg, toCString(version)))
136-
}
130+
guard_(s2n_config_set_cipher_preferences(cfg, toCStringArray(version).at(0)))
137131
}
138132
}.toResource
139133
} yield new S2nConfig(cfg)

0 commit comments

Comments
 (0)