Pyruvate, a reasonably fast, non-blocking, multithreaded WSGI server
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 72 | |
Author | ||
Contributors | ||
License | CC Attribution 3.0 Germany: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/54778 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Production Year | 2020 |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
Plone Conference 202029 / 72
1
3
6
9
13
14
18
23
34
35
39
40
43
46
50
51
56
58
60
63
66
71
00:00
Thread (computing)Server (computing)Plane (geometry)Axiom of choiceDefault (computer science)Computer configurationWrapper (data mining)Thread (computing)Electronic mailing listLimit (category theory)CASE <Informatik>Connectivity (graph theory)Point (geometry)Endliche ModelltheorieUser interfaceExpected valueSoftwareLatent heatBitSoftware developerParameter (computer programming)Different (Kate Ryan album)PlastikkarteHigh-level programming languageRun time (program lifecycle phase)Device driverBijectionAxiom of choiceLevel (video gaming)Server (computing)ImplementationLibrary (computing)MehrprozessorsystemDefault (computer science)Computer configurationCartesian coordinate systemKey (cryptography)Integrated development environmentComputer fileProjective planeConnected spaceWrapper (data mining)DatabaseSingle-precision floating-point formatInterface (computing)Web 2.0Electronic signatureMessage passingSystem callPauli exclusion principleGateway (telecommunications)Client (computing)Cache (computing)Slide ruleDependent and independent variablesEmailSet (mathematics)IterationModule (mathematics)WordMusical ensembleTwin primeUniverse (mathematics)Computer animation
08:03
Hand fanHill differential equationZoom lensMemory managementUniqueness quantificationRule of inferenceControl flowImplementationDefault (computer science)Drop (liquid)Variable (mathematics)SpeicherbereinigungAssociative propertyCore dumpLeakRead-only memoryInterface (computing)Pattern matchingCompilerMessage passingPerspective (visual)Module (mathematics)Plane (geometry)Instance (computer science)Server (computing)Data structureSource codeExtension (kinesiology)Computer scienceHigh-level programming languageCore dumpSystem programmingProgramming languageStapeldateiBit rateProjective planeSet (mathematics)Multiplication signResultantLatent heatLibrary (computing)Object (grammar)HTTP cookieTemplate (C++)Modal logicSocial classInterface (computing)Socket-SchnittstelleComputer configurationBitEquivalence relationSheaf (mathematics)Point (geometry)Compilation albumSpeicherbereinigungPattern matchingMemory managementCorrespondence (mathematics)NumberSemiconductor memoryInstance (computer science)Extension (kinesiology)Module (mathematics)Graph (mathematics)Online helpError messageType theoryLeakStudent's t-testSoftwareRun time (program lifecycle phase)Perspective (visual)Device driverSlide ruleCompilerPlastikkarteMessage passingCartesian coordinate systemFunctional (mathematics)Default (computer science)Computer filePerfect groupSource codeSubject indexingData structureGoodness of fitLevel (video gaming)Revision controlRule of inferenceCountingDrop (liquid)Principle of maximum entropyImplementationMacro (computer science)Uniqueness quantificationFormal languagePiWrapper (data mining)Network topologyMereologyServer (computing)HypothesisTask (computing)Computer animation
16:05
Data structureSource codePhysical systemExtension (kinesiology)Modul <Datentyp>Execution unitSoftware testingDisintegrationBinary fileError messageRevision controlSocket-SchnittstelleTime domainInterface (computing)Message passingConfiguration spaceMathematical analysisCodeFluid staticsRead-only memoryResource allocationCodeLibrary (computing)Sinc functionUnit testingCovering spaceMultiplication signSoftware testingRevision controlFile formatProjective planeINTEGRALCompilerComputing platformForm (programming)Error messageTraffic reportingMemory managementComputer fileInterface (computing)Different (Kate Ryan album)System callMessage passingChainDomain nameLink (knot theory)Default (computer science)Thread (computing)Socket-SchnittstelleInstallation artInstance (computer science)NumberPhysical systemExecution unitPrincipal ideal domainModule (mathematics)CASE <Informatik>Mathematical analysisRight angleMereologyFluid staticsReading (process)LoginCuboidPoint (geometry)Server (computing)Level (video gaming)Configuration spaceStandard deviationFunctional (mathematics)Wrapper (data mining)Binary codeBuildingPauli exclusion principleOnline chatJSONXML
24:08
Mathematical analysisCodeFluid staticsSocket-SchnittstelleRead-only memoryResource allocationGraph (mathematics)Software testingLink (knot theory)Interpreter (computing)Event horizonThread (computing)AbstractionInstance (computer science)IterationDependent and independent variablesLoop (music)Electric currentLimit (category theory)BefehlsprozessorColor managementSimultaneous localization and mappingData storage deviceInheritance (object-oriented programming)Bellman equationConvex hullPointer (computer programming)Time zoneFirewall (computing)CompilerProxy serverPlane (geometry)WebsiteStructural loadMusical ensembleFunctional (mathematics)System callDependent and independent variablesWeb pageError messageDifferent (Kate Ryan album)Loop (music)Uniform resource locatorInstance (computer science)Connected spaceEvent horizonCartesian coordinate systemModal logicRight angleInterpreter (computing)Block (periodic table)Computer configurationLoginCASE <Informatik>ResultantServer (computing)Software testingOperating systemThread (computing)CodeBuffer solutionVacuumGrass (card game)AbstractionMultiplication signCuboidSocket-SchnittstelleLaptopWebsiteLimit (category theory)BefehlsprozessorDatabaseComputer fileNumberDemo (music)Bit rateCombinational logicBitWeb browserVideo game consoleMenu (computing)WritingPhysical systemLenovo GroupComputer animation
32:10
User profileFiber bundleConvex hullSurjective functionMenu (computing)Maxima and minimaComputer wormInformationAnnulus (mathematics)Content management systemOpen setPlane (geometry)System administratorLine (geometry)Interior (topology)Zoom lensComputer programmingRange (statistics)Programming languageMusical ensembleMultiplication signProbability density functionSource codeXMLComputer animation
32:42
Mobile appCommon Language InfrastructureMaizeCodeFormal languageComputer programmingDomain nameVariety (linguistics)Mach's principleConcurrency (computer science)Drag (physics)Read-only memoryTerm (mathematics)Crash (computing)Vulnerability (computing)Control flowComputer programRepresentation (politics)Memory managementSystem programmingClassical physicsPlane (geometry)SchwerpunktsystemInformationCache (computing)NumberObject (grammar)DatabaseTotal S.A.Data managementMenu (computing)WebsiteError messageMaß <Mathematik>DatabaseMusical ensembleConnected spaceMoment (mathematics)Cartesian coordinate systemThread (computing)BitStructural loadSoftware testingMultiplication signClient (computing)Computer animation
34:11
Term (mathematics)Rule of inferenceArithmetic meanInformationHost Identity Protocol2 (number)Pairwise comparisonClient (computing)Moment (mathematics)Web pageBitInstance (computer science)Cache (computing)Computer animation
35:29
Rule of inferencePhysical lawTotal S.A.Dean numberConcurrency (computer science)19 (number)Binary fileServer (computing)QuicksortNumber2 (number)Correspondence (mathematics)Instance (computer science)Different (Kate Ryan album)Server (computing)Uniform resource locatorDemo (music)ResultantPairwise comparisonComputer animation
36:59
Thread (computing)Software testingBinary fileBranch (computer science)FeedbackBranch (computer science)Software testingRevision controlThread (computing)Musical ensembleTraffic reportingMedical imagingSoftware bugMultiplication signBinary codeBitJSONXMLComputer animation
39:01
Link (knot theory)Open sourceContent management systemPlane (geometry)FingerprintSimulationWeb 2.0Time zoneLemma (mathematics)Streaming mediaDifferent (Kate Ryan album)Product (business)Musical ensembleProjective planeTrailControl flowLattice (order)WeightExterior algebraSoftware testingWebsiteLink (knot theory)Software developerComputer animation
Transcript: English(auto-generated)
00:08
So, hello and welcome to track two of the Plone Conference 2020. Shortly we will have the talk about pyruvate, a reasonable fast non-blocking multi-thread
00:30
WYSI-GI server from Thomas Schorr and I will give this to our talker, speaker, sorry.
00:46
Hello everybody and thank you very much for having me here today. My name is Thomas Schorr, I'm a freelance software developer from Freiburg in Germany and I'm working with Python since over 15 years. I'm also a contributor to both Plone and Soap but
01:09
about 10 months ago I started a Rust project that I want to present in my talk today and the title of the project, the project name is pyruvate and it's a
01:31
Python Enhancement Proposal 3333 which is specifying the Python web server gateway interface aka WYSI. The basic message of the PEP is that you can define a Python call level
01:48
with a specific signature that will be called by a server software, the WYSI server. Once for each HTTP request this server receives from a client or upstream web server.
02:00
And this Python callable, the WYSI application, returns a set of headers along with an iterable response that will be rendered into an HTTP response by the WYSI server and what we can see on this slide is the simplest possible WYSI application and of course it returns a hello
02:22
word message in plain text. Instead of a list it could also return some other iterable. Now when we look at the server side then the server invokes the application call level
02:41
once for each HTTP request it receives. I've already said that but there is actually many possibilities for handling those requests. The server could be implemented as a single-threaded server, it could spawn a thread for each incoming request, it could use one-to-one
03:04
threading or one-to-n aka clean threading for doing that, it could maintain a pool of worker threads and or it could do Python multi-processing using the Python multi-processing module from the standard library and it could do other things. The WYSI server can give hints
03:28
on how it's actually handling the request through the environment dictionary. There are some keys related to request handling but whether the application makes use of those
03:41
hints is totally up to the application and for example in SOAP I could not find any hints that SOAP is making use of those handling hints. On the other hand, on the application
04:00
side we normally don't have that simple hello world application. We often have a need to connect to components that outlive the single request like databases or caches and those database or cache connections might not actually be thread safe and setting them up
04:21
might be expensive and all of the above is true for SOAP because wdb connections are not thread safe and they're also quite expensive to set up. So now there's a recipe for disaster when choosing a WYSI server that uses an inappropriate worker model, so one that
04:40
does not fit your application and your application connections. As a consequence, although there are quite a lot of WYSI servers around, we have a fairly limited choice for WYSI servers that are actually suitable for SOAP and Bloom. So there's Waitress which is the
05:01
default that has a very good overall performance and it's a pure Python implementation. Then there's Bjorn that some of you might have heard of and it's a C implementation. It's quite fast. It's using non-blocking IO and it's single-threaded. Then there's maybe
05:23
some new WYSI options that could work with blown and so and yes there are some other options described in the SOAP documentation but that don't have a very good performance. So eventually I wanted more options. So more options please for WYSI servers that are
05:45
suitable for using with SOAP and Bloom. So I put up my personal wish list and I wanted a multi-threaded server doing one-to-one threading using a worker pool because that is the threading model that is working with SOAP. I wanted a paste deploy entry point because
06:03
I like that on Waitress. It's very cool because it makes WYSI servers a pluggable component that you can exchange easily. I wanted it of course to handle the SOAP blown use case. I have other use cases for WYSI servers as well but I wanted it to handle
06:22
SOAP and Bloom. I wanted a non-blocking IO and I wanted a file wrapper supporting send file which is two features that Waitress doesn't support. Of course I wanted it to be
06:41
performing well. This is not about creating the fastest WYSI server around but I wanted competitive performance so that it's actually usable. Non-goals of the project are Python 2 because Python 2 is out of support and then another non-goal is currently ASCII, not yet at least. So maybe in a couple of months
07:08
it might be an interesting feature and Windows is also a non-goal. I decided to use Rust for the implementation because I was interested in trying Rust for a while
07:24
and I had some naive expectations. I expected it to be faster than Python so in runtime performance I expected it to be better than Python and I expected it to be easier to use than C. Let me elaborate a bit on Rust's performance. At the end of 2018 I've seen a talk by Paul
07:47
Emmerich from Technical University of Munich and he was comparing network device drivers for specific network card implemented in different high-level programming languages. His argument was
08:01
that high-level languages are safer but he also wanted to assess the performance penalties that are coming with runtime safety checks and garbage collection. So computer science students could apply for implementing a user-space network card driver in a specific high-level language and that would be their thesis.
08:24
And in the project they benchmark each driver and the chart you can see on this slide is one such benchmark result and what you can actually see is that there is of course the very fast native C implementation and then next it's Rust that is following. So here we can see
08:49
a packet rate so batch size and packet rate benchmarking but there is a couple of other benchmarking results and they all look quite the same so Rust's always very much on top of when it comes to performance.
09:06
There's one very specific feature of Rust making it both a safe and a fast language and that is called ownership. So Rust has its own unique very unique implementation of memory management and it's basically a set of rules that the compiler checks at compile time
09:25
and these there are three rules so each value in Rust has a variable that's called its owner and there can only be one owner at a time and when the owner goes out of scope the value will be dropped and now a drop dropping actually is a trade so a trade being the Rust version of a
09:47
interface and there is a default implementation for drop for dropping a value and you can override it. And also you can still control in Rust where your data is stored. It's a systems
10:04
programming language so it allows you to do low level tasks and you can control what kind of memory you are using for your data. And how is that relevant for
10:22
safety and performance and as an example I want to quickly look at building a Rust extension for Python so it's about interfacing with Python. When we look at Python memory management there's reference counting and garbage collection so whenever you assign an object then you increase
10:46
its ref count and internally in the C API there is a macro called pi-inkref that is invoked for increasing the object's memory reference count and these pi-inkref invocations have to match
11:01
with pi-decref invocations so decrementing the reference count and garbage collection occurs when an object's ref count goes to zero and if pi-inkref and pi-decref invocations do not match you'll see memory leaks or and eventually coredoms. Now as an example if we look at
11:23
well-known Python C extensions that we all use then we have 63 occurrences of pi-inkref in b-trees which is part of the subdb and we have 19 invocations in soap interface and if we compare that to the Rust C Python crate Rust crate that is implementing the Rust C Python
11:49
interface then we only have one pi-inkref invocation and the corresponding pi-decref is implemented in the drop trait for the Python object wrapper and as a result it is
12:06
very hard to create a mismatch of pi-inkref and pi-decref invocations in when doing a Rust extension so you're very well set up to create memory safe extensions
12:25
and it's getting harder to create memory leaks or coredoms. Of course it's still possible to create more references that you actually need and of course you can still create coredoms by for example not fetching Python errors from the from the error stack.
12:46
Well other Rust features that are cool include strict typing that is meaning you will find many problems at compile time and pattern matching is really cool Rust documentation is very good and there are very helpful compiler messages
13:04
and yeah there's there's a couple of other good stuff about Rust. So let's start having a closer look at pyroovate from a user perspective. So from a user perspective at first it's a package that is available from pi pi from the python packaging
13:24
index and so you could do pip install pyroovate and then it's an importable python module so writing your whiskey application you would do import pyroovate then you define your application callable and then there's basically one single function that you can use
13:46
from this module it's called serve and you pass in your application you pass in a socket to use and you mandate you have to mandatorily pass in the number of workers that you want.
14:01
So now since this is soap and blown most of you will want to use blown recipe soap2 instance with setc buildout and so in your buildout.cfg if you want to use pyroovate instead of the
14:22
and then you basically use a specific whiskey in a template and you that you can pass to blown recipe soap2 instance and essentially in this template you have a server section so server colon main and you specify the pyroovate paste deploy entry point you specify the socket and the
14:49
number of workers you want to you want to use and that's it let's have a look a bit at the project structure pyroovate is hosted on gitlab i initially created it with cargo new dash dash
15:06
slip so cargo new being the equivalent of cookie cutter or op templates and with dash dash slip you will create a rust library so you end up having a shared object file in linux
15:24
then there's a src folder containing the rust sources then there's this cargo.toml that's created by cargo new which pulls in all the necessary rust dependencies there's a setup.py
15:40
that you have to add yourself when writing a rust extension and you you need to use a package called setup tools underscore rust and you it's very easy when you use it you get a class named rust extension it's very easy to define your rust extension entry points and and main
16:02
essential compilation options and then and and it also defines the paste deploy entry point then there's a pyproject.toml file to specify the build system requirements which you would you can look this up in PEP 518 and there's a tests folder which is currently containing mostly
16:25
python tests so these are tox tests these are these are yeah i'm using py.test and tox to run the python tests and the unit tests they are in the rust modules so they are in module
16:42
unit tests which is one standard of writing unit tests in rust then there is a underscore init underscore underscore py file in the pyrate folder which is actually the the function definition of the paste deploy entry point and you import the file wrapper that you need for
17:03
file wrapper feature and yes i'm running a gitlab pipeline for the project with two stages there's testing and there's a build stage for building binary packages
17:22
part of the test is linting so i'm doing a rust format which is opinionated code formatting in rust making rust code formatting very simple because you just use rust form and then your code is formatted the way it should look like i'm sorry for that and then there's clippy which
17:42
is a rust linter giving you hints on how to improve your code then i'm running the actual unit tests um and i'm creating a coverage report using kcov which is a coverage tool coverage creation tool working for compiled languages and i'm uploading the the coverage to codecuff.io
18:06
because at the time when i started that project codecuff.io was the platform that explicitly supported rust coverage and coveralls.io didn't didn't say so at that time
18:27
at least then it's running the python integration tests with talks as i said before for all available python versions and finally if all tests pass and i'm building wheels
18:43
so binary packages i'm currently building many linux 2010 wheels for python 3.6 through 3.9 and i switched to many linux 2010 after many linux one
19:02
after after the stable rust that i'm using to build the wheels stopped supporting the old abi so there was a there was a an error when loading the rust chat libraries since rust version 47 i think and so i switched to many linux 2010
19:23
because i did not want did not want to go through compiling my own tool chain in a in a many linux one docker docker container
19:41
important thing to note about many links to talk 2010 is that it needs you will need recent pip and setup tool versions to make the package work so pip version greater than 19 so if you see if you're doing a pip install pyruvate and pip refers
20:01
as dist over real which you which you will find out when it tries to invoke the rust compiler and then there's no rust in your platform then you need to upgrade to upgrade pip same for setup tools when you're using it with setc build out you need setup tools version crater 42 and yes and what's what's wanted is as for binary
20:27
packages mac os i don't have a mac myself so if anybody is interested in sending me a pull request um actually uh there should not be much difference compared to linux maybe the send file
20:43
call is is different on on the mac okay so let's let's do a quick run through the features um it's a rusty python based python interface so a rusty python is one of i think three
21:00
currently available python interface python interfaces and i found it to be very suitable for this project then i'm doing and then i'm using a crate called rust crate called metal io so mio which is part of a bigger project called tokyo rs and it's providing
21:25
non-blocking io and pyruvate is giving you non-blocking read in all cases and then optional optionally blocking or non-blocking right the default is non-blocking right i'm using a worker pool based on thread pool which is another rust crate doing one-to-one
21:42
threading uh i said before that i'm having a paste deploy entry point pyruvate is integrating with python logging so i'm doing asynchronous logging which means when pyruvate is creating a log message it doesn't need to hold the global interpreter log and it also means for you that
22:04
you can specify the logging configuration for pyruvate in your whiskey.ini if you're using blown and soap or or just any other way that is by specified in the python logging
22:23
documentation you can use tcp or unix domain sockets so ipv4 or ipv6 sockets and unix domain sockets and it also supports systemd socket activation that's not easy that's not easy to use use out of the box with soap and blown because
22:46
you need the pid the whiskey server pid to to look up the sockets and that's not quite easy to do with us with a blown recipe soap2 instance
23:01
um yes i started to look at performance and it and it turned it turned out to be a rabbit hole so performance in as in number of requests and amount of data transferred by per unit of time and i wanted of course to test it and eventually improve it um so my approach was
23:27
for static code analysis and refactoring that was very helpful because pyruvate really started as a hello rust project and so i found out for example that memory allocations are pretty expensive which is which everybody might might everybody else might already know
23:46
um then i struggled a lot with how to actually induce socket blocking so um on a normal uh on a normal uh linux it's it's not quite easy to to um to to induce
24:06
to to see a as a socket that is blocking them right so if i eventually resolve to limiting socket buffer sizes on a vagrant box for testing purposes purposes um then it would be
24:21
good to have that uh with uh docker but um i couldn't find a way yet to do that because socket buffer sizes are um basically specified on the hosts um and it would be good to have to to uh to be able to menu manipulate them on on the on the container of course
24:43
um i've been looking at flame crafts from perf data perf data is a cool a tool that is collecting um performance data on on linux so it's actually looking at the time that function spent uh on a stack and uh that's that proved very very good it's very good to
25:06
a very good way of assessing performance issues uh so for example i found out uh stuff like as i found out that uh the cold two lower is much more expensive than a call to two ascii
25:21
uppercase so and i could eventually uh switch that um and i'm doing um i started doing some load testing with uh ch with and ab so apache benchmarking which is a very old uh performance testing tool um ab will always ever fetch one url where uh ch will will download the whole page
25:49
so yes it's quite it's quite different approach of uh testing and uh yeah let's
26:01
i want to a quick glance at some design considerations that are affecting performance so um first there's the python global interpreter lock so python code can only run when holding the this global interpreter lock it's like it's like a baton in a relay race
26:20
so if you have multiple workers they really need to acquire the global interpreter lock in turn and the approach is of course to acquire the global interpreter lock only for application execution and dropping it when doing uh io and there's there's actually
26:40
more than one possible way to do this so um yeah i'm not i'm not quite sure yet what is what is the best the best way of doing it um another um another important issue is io event polling so the this miocrate that i mentioned earlier is presenting an abstraction
27:07
called poll instance which will do the necessary system calls um and so whenever the accepts a connection uh those it gets it's gets uh this these connections get registered for read
27:24
events with a port with such a poll instance in the main thread and so we are doing non-blocking right so uh it could take multiple turns to read the entire request but eventually
27:42
we'll pass the completely read requests plus the connection to the worker pool and the free worker will pick up the connection along with the request and it will invoke the whiskey application it will iterate over the whiskey response chunks which will need the global
28:01
interpreter lock and now if you if you do if you're doing blocking right you can simply loop until the response is completely written which is easy but in the non-blocking case you can you will you will be able to write until the there is a e would block or e again
28:23
error raised by the operating system and i'm resolving to when that happens i register the connection for write events with a per worker poll instance so there is actually not one poll instance but there is two one is for reading for read events in the main thread
28:45
and then each worker's got got its own poll instance for write events um they are not very big so this isn't i'd say overly expensive but there could also be other options for doing that
29:01
and yeah once i'm um i receive uh e again error uh the the worker drops the global interpreter lock and will stash the response for a later write until it receives a write write writable events from from the per worker poll instance um yes so first performance
29:26
um results on my Lenovo x390 and a vagrant box uh so so i'm doing it both on natively on the on the laptop and a vagrant box with two CPUs two gigs of ram and 8k write buffer size limits
29:44
which is really small um so it's it's a lot faster than waitress on a hello world whiskey application and it's still faster than waitress when downloading uh slash url so so in this case
30:03
looking at the at the test criteria for benchmarking whiskey service from the soap documentation but it's currently slower than on on slash blown that's interesting i'm still
30:23
so i i there's definitely more performance testing needed and there's a lot of different situations and still a lot of different combination possible combinations of setting up like number of threads and so on and yes i'm only starting to to assess that
30:44
okay um let's um do a little live demo um i've um i've prepared a build out that i've already run which is defining um a a pyrograde
31:04
a blown instance using pyrograde uh so there's a co server that's a blown instance using pyrograde and then there's another instance using uh waitress um they are um running on different ports so the pyrate instance is running on 78 78 and waitress is running on 78 79
31:24
co server is already running and i'm starting pyrograde um tell it's telling me it's ready um and i've prepared a browser tab for running this and
31:44
database is empty so i'm prompted for a new blown website i'm creating a german site because i'm german i'm used to german um yeah looking at the console it's running that i got i get blown
32:02
i can browse a bit i can upload a file i'm uploading the rest programming language documentation it's taking some time because
32:31
it's it's rather big but eventually it gets uploaded i can download it i could open it
32:40
yeah in a pdf reader um let's maybe have a quick look quick look at the cmi so going to the control panel and going to the databases control panel i can see that there's
33:04
two database connections at the moment which is corresponding with the two worker threads that define in the build out um when i reload i see that these are always the same two connections because the application the whiskey application gets copied to each worker thread
33:25
and then once upon startup the connection will the the sudb connection will be opened and it will be reused all the time um yes that's basically
33:41
all there is to see it's it's just it's just blown this is blown five two latest so it should be five two three i've built it on saturday um and what i can do now after browsing a bit is i can do um i can do some load testing like specify it in uh the soap doc i'm doing
34:07
it like specified in the in the soap documentation so 100 concurrent concurrent clients accessing so i'm not running it for 100 seconds because that would take too long i'm running it for 30 seconds and uh yes while i'm doing that we could actually already i think i'm going to do
34:29
the same thing with uh waitress later on uh just to get a comparison but while i'm doing that we could maybe already have uh questions if there are any no at the moment there are
34:51
no questions okay so i'm starting the waitress instance you see we are seeing waiters starting
35:12
up and uh to be fair uh sorry that was the wrong wrong page and to be fair i'm going to
35:22
browse a bit on the on this page just to warm the caches of course and then i'll do the same thing for the waitress instance so we can get a comparison on
35:43
performance which is of course i am i am biased of course and as i said before there's different results for different urls so you you definitely have to do your your own benchmarking if you
36:01
want if you want to to to pick a whiskey server so what we can see here is that um hang on where are we so there is 5809 complete requests in 30 seconds
36:25
and here we got 8171 so this is i will wait and it's got a couple more completed requests uh none of the none of the service uh had failed requests and uh corresponding with a
36:41
bigger number of completed requests there's there's more data that has actually been transferred yes okay so that so much for the demo um yeah that's basically what i wanted to tell you
37:02
i'm planning a 1.0 release for end of this year um there's a couple of things that i that i still want to do currently we are on version 0.8.3 on pi pi it's still a better version so it will have bugs but yeah i'm yeah i'd be happy if uh if you want to you want to give
37:28
it a try um there's a there's a feature branch on gitlab that needs some work which is implementing keep alive and junk transport and then i want to integrate in the 1.0 release
37:41
and as i said before i want mac os support um it's still open and i want to optimize a bit the pipeline for example i'm currently compiling the cake of binary each time i am running uh the coverage reporting because there is no cake of binary package available available for a Debian
38:03
buster which is the base image for rust nightly and then i want to fix an issue with the thread id not that is not reported correctly when doing async logging and of course i'm doing more testing and i hope that i can fix a couple more more bugs yeah that's it um thank you very
38:30
much for your attention and yes i if you want to give it a try i'd be i'd be happy for for
38:40
for feedback for your feedback i'm looking forward to your feedback feedback thank you very much um thank you thomas um there was one question in um in the slido um i guess it's kind of answered um the question was uh is it a
39:08
project to keep an eye on or is it ready for production yet um it's better um i'm using it in production on a couple of smaller sites and you can definitely use it for
39:27
for development as a drop-in replacement for waitress and i think you also can use it for testing and i i think it's it's it's not a it's not a replacement for waitress it's an alternative
39:40
so it's got it's got a couple of features that are the same which are the features that you you need to to make it suitable for use with soap and blow and then you've got a couple of different features like non-blocking io um yeah and um and that makes it makes it
40:04
a bit different from from waitress so so you might want to try it in different situations or you might just want to compare it but i think you can start yeah start yeah start i started using it in production okay then thank you from winston for this uh answer and uh thank you
40:29
thomas for um the talk um i would um encourage everyone to come to the uh face-to-face you can
40:41
find the link down below under the stream just by click on join face to face and yeah we have a break on this track i guess for nearly an hour
41:04
um so see you back in an hour hopefully thank you thank you