개발모음집

TechEmpower Source code & Requirements 한글 번역 본문

Benchmark

TechEmpower Source code & Requirements 한글 번역

void 2017. 9. 22. 09:00


TechEmpower


GitHub repository

All of the code used to produce the comparison of web frameworks seen here can be found in the project's GitHub repository. If you have any corrections or contributions, please submit a pull request!


여기서 보여지는 웹 프레임워크의 비교를 위해 사용되는 모든 코드는 프로젝트의 GitHub저장소에서 찾을 수 있습니다.

만약 수정하거나 기역하고 싶다면, pull request를 해주세요.


Forum / mailing list

Join the conversation about this project on the framework-benchmarks Google Group.


이 프로젝트에 대한 대화하기 위해 프레임 워크 - 벤치 마크 Google 그룹 에 가입하세요.


Test requirements

We invite fans of frameworks and especially authors or maintainers of frameworks to join us in expanding the coverage of this project by implementing tests and contributing to the GitHub repository. The following are specifications for each of the test types we have included to-date in this project. Do not be alarmed; the specifications read quite verbose, but that's because they are specifications. The implementations tend to be quite easy in practice.

패스

This project is evolving and we will periodically add new test types. As new test types are added, we encourage but do not require contributors of previous implementations to implement tests for the new test types. Wholly new test implementations are also encouraged to include all test types but are not required to do so. If you have limited time, we recommend you start with the easiest test types (1, 2, 3, and 6) and then continue beyond those as time permits.


패스

General requirements

The following requirements apply to all test types below.



  1. All test implementations should be production-grade. The particulars of this will vary by framework and platform, but the general sentiment is that the code and configuration should be suitable for a production deployment. The word should is used here because production-grade is our goal, but we don't want this to be a roadblock. If you're submitting a new test and uncertain whether your code is production-grade, submit it anyway and then solicit input from other subject-matter experts.



2. This project intends to measure performance of production-grade deployments of real-world web application frameworks and platforms. All implementations are expected (but not required) to be based on robust implementations of the HTTP protocol. Implementations that are not based on a realistic HTTP implementation will be marked as Stripped (see Questions section for more detail on the Stripped classification). Rather than stipulate a rigid specification of HTTP requirements, we defer to common sense: the implementation should provide a viable subset of HTTP to reasonably unbiased outsiders familiar with HTTP.



3. All test implementations must disable all disk logging. For many reasons, we expect all tests will run without writing logs to disk. Most importantly, the volume of requests is sufficiently high to fill up disks even with only a single line written to disk per request. Please disable all forms of disk logging. We recommend but do not require disabling console logging as well.



4. Specific characters and character case matter. Assume the client consuming your service's JSON responses will be using a case-sensitive language such as JavaScript. In other words, if a test specifies that a map's key is id, use id. Do not use Id or ID. This strictness is required not only because it's sensible but also because our automated validation checks are picky.



5. All test types require Server and Date HTTP response headers. We expect the Server header to be whatever is normal for the platform or framework. If the framework does not normally provide a Server response header, we nevertheless require that you provide one as this roughly normalizes network load across all implementations. For Date, we expect that the rendered date be accurate. However, it does not need to be rendered from the system clock to a byte buffer for each request. Re-rendering once per second is an acceptable tactical optimization (and is an optimization baked into many frameworks).



6. Some form of request routing is required, even if only a single test type (e.g., Plaintext) is implemented. In most cases, the framework's canonical router or a mainstream router library will be used. In some cases, it is considered normal and sufficiently production-grade to use hand-crafted minimalist routing using control structures such as if/else branching. This is acceptable where it is considered canonical for the framework.



Test type 1: JSON serialization

This test exercises the framework fundamentals including keep-alive support, request routing, request header parsing, object instantiation, JSON serialization, response header generation, and request count throughput.

Requirements

  1. For each request, an object mapping the key message to Hello, World! must be instantiated.



2. The recommended URI is /json.



3. A JSON serializer must be used to convert the object to JSON.



4. The response text must be {"message":"Hello, World!"}, but white-space variations are acceptable.




5. The response content length should be approximately 28 bytes.


6. The response content type must be set to application/json. Note that specifying the character encoding is unnecessary for this content type.


7. The response headers must include either Content-Length or Transfer-Encoding.


8. The response headers must include Server and Date.


9. gzip compression is not permitted.


10. Server support for HTTP Keep-Alive is strongly encouraged but not required.


11. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.


12. The request handler will be exercised at concurrency levels ranging from 8 to 256.


13. The request handler will be exercised using GET requests.


Example request

GET /json HTTP/1.1 Host: server User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00 Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive

Example response

HTTP/1.1 200 OK Content-Type: application/json Content-Length: 28 Server: Example Date: Wed, 17 Apr 2013 12:00:00 GMT {"message":"Hello, World!"}


Test type 2: Single database query

This test exercises the framework's object-relational mapper (ORM), random number generator, database driver, and database connection pool.



Requirements

  1. For every request, a single row from a World table must be retrieved from a database table.

2. The recommended URI is /db.



3. The schema for World is id (int, primary key) and randomNumber (int), except for MongoDB, wherein the identity column is _id, with the leading underscore.



4. The World table is known to contain 10,000 rows.



5. The row retrieved must be selected by its id using a random number generator (ids range from 1 to 10,000).



6. The row should be converted to an object using an object-relational mapping (ORM) tool. Tests that do not use an ORM will be classified as "raw" meaning they use the platform's raw database connectivity.



7. The object (or database row, if an ORM is not used) must be serialized to JSON.



8. The response content length should be approximately 32 bytes.



9. The response content type must be set to application/json. Note that specifying the character encoding is unnecessary for this content type.



10. The response headers must include either Content-Length or Transfer-Encoding.



11. The response headers must include Server and Date.



12. Use of an in-memory cache of World objects or rows by the application is not permitted.



13. Use of prepared statements for SQL database tests (e.g., for MySQL) is encouraged but not required.



14. gzip compression is not permitted.



15. Server support for HTTP Keep-Alive is strongly encouraged but not required.



16. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.



17. The request handler will be exercised at concurrency levels ranging from 8 to 256.



18. The request handler will be exercised using GET requests.



Example request

GET /db HTTP/1.1 Host: server User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00 Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive

Example response

HTTP/1.1 200 OK Content-Length: 32 Content-Type: application/json Server: Example Date: Wed, 17 Apr 2013 12:00:00 GMT {"id":3217,"randomNumber":2149}


Test type 3: Multiple database queries

This test is a variation of Test #2 and also uses the World table. Multiple rows are fetched to more dramatically punish the database driver and connection pool. At the highest queries-per-request tested (20), this test demonstrates all frameworks' convergence toward zero requests-per-second as database activity increases.

Requirements

  1. For every request, an integer query string parameter named queries must be retrieved from the request. The parameter specifies the number of database queries to execute in preparing the HTTP response (see below).

2. The recommended URI is /queries.



3.The queries parameter must be bounded to between 1 and 500. If the parameter is missing, is not an integer, or is an integer less than 1, the value should be interpreted as 1; if greater than 500, the value should be interpreted as 500.



4. The request handler must retrieve a set of World objects, equal in count to the queries parameter, from the World database table.


5. Each row must be selected randomly in the same fashion as the single database query test (Test #2 above).


6. This test is designed to exercise multiple queries, each requiring a round-trip to the database server, and with each resulting row selected individually. It is not acceptable to use batches. It is not acceptable to execute multiple SELECTs within a single statement. It is not acceptable to retrieve all required rows using a SELECT ... WHERE id IN (...) clause.



7. Each World object must be added to a list or array.



8. The list or array must be serialized to JSON and sent as a response.



9.The response content type must be set to application/json. Note that specifying the character encoding is unnecessary for this content type.



10. The response headers must include either Content-Length or Transfer-Encoding.



11. The response headers must include Server and Date.



12. Use of an in-memory cache of World objects or rows by the application is not permitted.



13. Use of prepared statements for SQL database tests (e.g., for MySQL) is encouraged but not required.



14. gzip compression is not permitted.



15. Server support for HTTP Keep-Alive is strongly encouraged but not required.



16. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.



17. The request handler will be exercised at 256 concurrency only.



18. The request handler will be exercised with query counts of 1, 5, 10, 15, and 20.



19. The request handler will be exercised using GET requests.



Example request

GET /queries?queries=10 HTTP/1.1 Host: server User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00 Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive

Example response

HTTP/1.1 200 OK Content-Length: 315 Content-Type: application/json Server: Example Date: Wed, 17 Apr 2013 12:00:00 GMT [{"id":4174,"randomNumber":331},{"id":51,"randomNumber":6544},{"id":4462,"randomNumber":952},{"id":2221,"randomNumber":532},{"id":9276,"randomNumber":3097},{"id":3056,"randomNumber":7293},{"id":6964,"randomNumber":620},{"id":675,"randomNumber":6601},{"id":8414,"randomNumber":6569},{"id":2753,"randomNumber":4065}]


Test type 4: Fortunes

This test exercises the ORM, database connectivity, dynamic-size collections, sorting, server-side templates, XSS countermeasures, and character encoding.

Requirements

  1. The recommended URI is /fortunes.



2.  A Fortune database table contains a dozen Unix-style fortune-cookie messages.



3. The schema for Fortune is id (int, primary key) and message (varchar), except for MongoDB, wherein the identity column is _id, with the leading underscore.



4. Using an ORM, all Fortune objects must be fetched from the Fortune table, and placed into a list data structure. Tests that do not use an ORM will be classified as "raw" meaning they use the platform's raw database connectivity.



5. The list data structure must be a dynamic-size or equivalent and should not be dimensioned using foreknowledge of the row-count of the database table.



6. Within the scope of the request, a new Fortune object must be constructed and added to the list. This confirms that the data structure is dynamic-sized. The new fortune is not persisted to the database; it is ephemeral for the scope of the request.



7. The new Fortune's message must be "Additional fortune added at request time."



8. The list of Fortune objects must be sorted by the order of the message field. No ORDER BY clause is permitted in the database query (ordering within the query would be of negligible value anyway since a newly instantiated Fortune is added to the list prior to sorting).



9. The sorted list must be provided to a server-side template and rendered to simple HTML (see below for minimum template). The resulting HTML table displays each Fortune's id number and message text.



10. This test does not include external assets (CSS, JavaScript); a later test type will include assets.



11. The HTML generated by the template must be sent as a response.



12. Be aware that the message text fields are stored as UTF-8 and one of the fortune cookie messages is in Japanese.



13. The resulting HTML must be delivered using UTF-8 encoding.



14. The Japanese fortune cookie message must be displayed correctly.



15. Be aware that at least one of the message text fields includes a <script> tag.



16. The server-side template must assume the message text cannot be trusted and must escape the message text properly.



17. The implementation is encouraged to use best practices for templates such as layout inheritence, separate header and footer files, and so on. However, this is not required. We request that implementations do not manage assets (JavaScript, CSS, images). We are deferring asset management until we can craft a more suitable test.



18. The response content type must be set to text/html.



19. The response headers must include either Content-Length or Transfer-Encoding.



20. The response headers must include Server and Date.



21. Use of an in-memory cache of Fortune objects or rows by the application is not permitted.



22. Use of prepared statements for SQL database tests (e.g., for MySQL) is encouraged but not required.



23. gzip compression is not permitted.



24. Server support for HTTP Keep-Alive is strongly encouraged but not required.



25. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.



26. The request handler will be exercised at concurrency levels ranging from 8 to 256.



27. The request handler will be exercised using GET requests.



Example request

GET /fortunes HTTP/1.1 Host: server User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00 Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive

Example response

HTTP/1.1 200 OK Content-Length: 1196 Content-Type: text/html; charset=UTF-8 Server: Example Date: Wed, 17 Apr 2013 12:00:00 GMT <!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><tr><td>11</td><td>&lt;script&gt;alert(&quot;This should not be displayed in a browser alert box.&quot;);&lt;/script&gt;</td></tr><tr><td>4</td><td>A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1</td></tr><tr><td>5</td><td>A computer program does what you tell it to do, not what you want it to do.</td></tr><tr><td>2</td><td>A computer scientist is someone who fixes things that aren&apos;t broken.</td></tr><tr><td>8</td><td>A list is only as strong as its weakest link. — Donald Knuth</td></tr><tr><td>0</td><td>Additional fortune added at request time.</td></tr><tr><td>3</td><td>After enough decimal places, nobody gives a damn.</td></tr><tr><td>7</td><td>Any program that runs right is obsolete.</td></tr><tr><td>10</td><td>Computers make very fast, very accurate mistakes.</td></tr><tr><td>6</td><td>Emacs is a nice operating system, but I prefer UNIX. — Tom Christaensen</td></tr><tr><td>9</td><td>Feature: A bug with seniority.</td></tr><tr><td>1</td><td>fortune: No such file or directory</td></tr><tr><td>12</td><td>フレームワークのベンチマーク</td></tr></table></body></html>

Minimum template

Along with the example response above, the following Mustache template illustrates the minimum requirements for the server-side template. White-space can be optionally eliminated.



<!DOCTYPE html> <html> <head><title>Fortunes</title></head> <body> <table> <tr><th>id</th><th>message</th></tr> {{#.}} <tr><td>{{id}}</td><td>{{message}}</td></tr> {{/.}} </table> </body> </html>


Test type 5: Database updates

This test is a variation of Test #3 that exercises the ORM's persistence of objects and the database driver's performance at running UPDATEstatements or similar. The spirit of this test is to exercise a variable number of read-then-write style database operations.



Requirements

  1. The recommended URI is /updates.



2. For every request, an integer query string parameter named queries must be retrieved from the request. The parameter specifies the number of rows to fetch and update in preparing the HTTP response (see below).



3. The queries parameter must be bounded to between 1 and 500. If the parameter is missing, is not an integer, or is an integer less than 1, the value should be interpreted as 1; if greater than 500, the value should be interpreted as 500.



4.The request handler must retrieve a set of World objects, equal in count to the queries parameter, from the World database table.



5. Each row must be selected randomly using one query in the same fashion as the single database query test (Test #2 above). As with the read-only multiple-query test type (#3 above), use of IN clauses or similar means to consolidate multiple queries into one operation is not permitted. Similarly, use of a batch or multiple SELECTs within a single statement are not permitted.



6.  At least the randomNumber field must be read from the database result set.



7. Each World object must have its randomNumber field updated to a new random integer between 1 and 10000.



8. Each World object must be persisted to the database with its new randomNumber value.



9. Use of batch updates is acceptable but not required. To be clear: batches are not permissible for selecting/reading the rows, but batches are acceptable for writing the updates.



10. Use of transactions is acceptable but not required. If transactions are used, a transaction should only encapsulate a single iteration, composed of a single read and single write. Transactions should not be used to consolidate multiple iterations into a single operation.



11. All updates should be completed prior to returning the HTTP response.



12. For raw tests (that is, tests without an ORM), each updated row must receive a unique new randomNumber value. It is not acceptable to change the randomNumber value of all rows to the same random number using an UPDATE ... WHERE id IN (...) clause.



13. Each World object must be added to a list or array.



14. The list or array must be serialized to JSON and sent as a response.



15. The response content type must be set to application/json. Note that specifying the character encoding is unnecessary for this content type.



16. The response headers must include either Content-Length or Transfer-Encoding.



17. The response headers must include Server and Date.



18. Use of an in-memory cache of World objects or rows by the application is not permitted.



19. Use of prepared statements for SQL database tests (e.g., for MySQL) is encouraged but not required.



20. gzip compression is not permitted.



21. Server support for HTTP Keep-Alive is strongly encouraged but not required.



22. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.



23. The request handler will be exercised at 256 concurrency only.



24. The request handler will be exercised with query counts of 1, 5, 10, 15, and 20.



25. The request handler will be exercised using GET requests.



Example request

GET /updates?queries=10 HTTP/1.1 Host: server User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00 Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive

Example response

HTTP/1.1 200 OK Content-Length: 315 Content-Type: application/json Server: Example Date: Wed, 17 Apr 2013 12:00:00 GMT [{"id":4174,"randomNumber":331},{"id":51,"randomNumber":6544},{"id":4462,"randomNumber":952},{"id":2221,"randomNumber":532},{"id":9276,"randomNumber":3097},{"id":3056,"randomNumber":7293},{"id":6964,"randomNumber":620},{"id":675,"randomNumber":6601},{"id":8414,"randomNumber":6569},{"id":2753,"randomNumber":4065}]



Test type 6: Plaintext



This test is an exercise of the request-routing fundamentals only, designed to demonstrate the capacity of high-performance platforms in particular. Requests will be sent using HTTP pipelining. The response payload is still small, meaning good performance is still necessary in order to saturate the gigabit Ethernet of the test environment.


The General Requirements section above applies to all test types, including Plaintext. Importantly, implementations should be production-grade deployments of real-world web application frameworks or platforms. The Plaintext test type is historically highly competitive, leading to some implementations being highly tuned to the express and narrow requirements identified below. We will usually accept such implementations, but they are subject to being classified as Stripped.


Requirements

  1. The recommended URI is /plaintext.


2. The response content type must be set to text/plain.



3. The response body must be Hello, World!.



4. This test is not intended to exercise the allocation of memory or instantiation of objects. Therefore it is acceptable but not required to re-use a single buffer for the response text (Hello, World). However, the response must be fully composed from the response text and response headers within the scope of each request and it is not acceptable to store the entire payload of the response, or an unnaturally large subset of the response, headers inclusive, as a pre-rendered buffer. "Buffer" here refers to a byte array, byte buffer, character array, character buffer, string, or string-like data structure. The spirit of the test is to require the construction of the HTTP response as is typically done by a framework or platform via concatenation of strings or similar. For example, pre-rendering a buffer with HTTP/1.1 200 OK<cr>Content-length: 15<cr>Server: Example<cr> would not be acceptable.


5. The response headers must include either Content-Length or Transfer-Encoding.


6. The response headers must include Server and Date.


7. gzip compression is not permitted.



8. Server support for HTTP Keep-Alive is strongly encouraged but not required.



9. Server support for HTTP/1.1 pipelining is assumed. Servers that do not support pipelining may be included but 



10. should downgrade gracefully. If you are unsure about your server's behavior with pipelining, test with the wrk load generation tool used in our tests.



11. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.



12. The request handler will be exercised at 256, 1024, 4096, and 16,384 concurrency.



13. The request handler will be exercised using GET requests.



Example request

GET /plaintext HTTP/1.1 Host: server User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00 Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive

Example response

HTTP/1.1 200 OK Content-Length: 15 Content-Type: text/plain; charset=UTF-8 Server: Example Date: Wed, 17 Apr 2013 12:00:00 GMT Hello, World!