diff --git a/.github/agents/SamsungDisplayManager.txt b/.github/agents/SamsungDisplayManager.txt new file mode 100644 index 0000000..403fdf9 --- /dev/null +++ b/.github/agents/SamsungDisplayManager.txt @@ -0,0 +1,122 @@ +Samsung Display Manager Opensource license use notice + + +OpenSSL License + +Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)" +4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org. +5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project. +6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)" +THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com). + +Original SSLeay License + +Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) +All rights reserved. + +This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). The implementation was written so as to conform with Netscapes SSL. + +This library is free for commercial and non-commercial use as long as the following conditions are aheared to. The following conditions apply to all code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. The SSL documentation included with this distribution is covered by the same copyright terms except that the holder is Tim Hudson (tjh@cryptsoft.com). + +Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of the parts of the library used. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software must display the following acknowledgement: +"This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)" +The word 'cryptographic' can be left out if the rouines from the library being used are not cryptographic related :-). +4. If you include any Windows specific code (or a derivative thereof) from the apps directory (application code) you must include an acknowledgement: "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" +THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The licence and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distribution licence [including the GNU Public Licence.] + +Standard License Header +There is no standard license header for the license + + +Apache License, Version 2.0 + +Foundation Projects People Get Involved Download Support Apache Home ≫ Licenses + +Apache License Version 2.0, January 2004 + +http://www.apache.org/licenses/ + + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/.github/agents/my-agent.agent.md b/.github/agents/my-agent.agent.md new file mode 100644 index 0000000..39a8426 --- /dev/null +++ b/.github/agents/my-agent.agent.md @@ -0,0 +1,13 @@ +--- +# Fill in the fields below to create a basic custom agent for your repository. +# The Copilot CLI can be used for local testing: https://gh.io/customagents/cli +# To make this agent available, merge this file into the default repository branch. +# For format details, see: https://gh.io/customagents/config + +name: +description: +--- + +# My Agent + +Describe what your agent does here... diff --git a/PERFORMANCE.md b/PERFORMANCE.md new file mode 100644 index 0000000..05fa04c --- /dev/null +++ b/PERFORMANCE.md @@ -0,0 +1,321 @@ +# Performance Optimization Guide for Functions Framework Implementations + +This document provides performance optimization guidelines and best practices for implementing and using the Functions Framework across all supported languages. + +## Table of Contents +- [Startup Performance](#startup-performance) +- [Request Handling Optimization](#request-handling-optimization) +- [Concurrency and Parallelism](#concurrency-and-parallelism) +- [Memory Management](#memory-management) +- [Caching Strategies](#caching-strategies) +- [Common Performance Anti-Patterns](#common-performance-anti-patterns) + +## Startup Performance + +### Cold Start Optimization + +Functions Frameworks are deployed to stateless compute environments where containers may be instantiated from scratch. Minimizing cold start time is critical for performance. + +**Best Practices:** + +1. **Lazy Loading**: Load dependencies and initialize resources only when needed, not during framework startup + - Load heavy libraries only when the function is first invoked + - Defer initialization of external service clients until first use + +2. **Minimize Dependencies**: Reduce the number and size of dependencies + - Use lightweight alternatives when possible + - Avoid importing entire libraries when only small portions are needed + - Consider tree-shaking for JavaScript implementations + +3. **Pre-compilation**: For compiled languages, pre-compile code during build phase + - Avoid runtime compilation or code generation + - Use Ahead-of-Time (AOT) compilation where available + +4. **Efficient Imports**: Structure imports to minimize load time + - Use selective imports (e.g., `from module import specific_function` vs `import module`) + - Avoid circular dependencies + +### Framework Initialization + +**Recommendation**: Complete all framework initialization before listening on the HTTP port to ensure the framework is ready to receive traffic. + +``` +# Good: Initialize before listening +framework = initialize_framework() +load_function(FUNCTION_TARGET) +start_http_server(PORT) + +# Bad: Listen first, then initialize +start_http_server(PORT) +framework = initialize_framework() # May receive requests before ready +``` + +## Request Handling Optimization + +### HTTP Request Processing + +1. **Avoid Unnecessary Parsing**: Only parse HTTP body when needed + - Check content-type before parsing + - For CloudEvent functions, use streaming parsers for large payloads + +2. **Minimize Allocations**: Reuse objects and buffers where possible + - Use object pooling for frequently created objects + - Pre-allocate buffers for common payload sizes + +3. **Efficient Header Handling**: + - Use case-insensitive header lookups efficiently + - Avoid iterating through all headers multiple times + +### Response Generation + +1. **Streaming Responses**: Support streaming for large responses + - Don't buffer entire response in memory + - Send response headers as soon as available + +2. **Compression**: Consider supporting response compression + - Compress large text responses (JSON, HTML) + - Make compression opt-in to avoid CPU overhead for small payloads + +## Concurrency and Parallelism + +### Concurrent Request Handling + +As specified in the contract, frameworks **must** handle multiple concurrent invocations of the developer's function. + +**Implementation Strategies:** + +1. **Thread Pool / Worker Pool**: Maintain a pool of workers to handle concurrent requests + - Size pool based on expected concurrency and resource constraints + - Avoid creating new threads/processes for each request + +2. **Async I/O**: Use non-blocking I/O for I/O-bound operations + - Leverage event loops (Node.js, Python asyncio, etc.) + - Avoid blocking the event loop with CPU-intensive operations + +3. **Connection Pooling**: Reuse connections to external services + - Maintain connection pools for database and API clients + - Configure appropriate pool sizes and timeouts + +### Resource Sharing + +1. **Global State**: Be careful with global state in concurrent environments + - Use thread-safe data structures + - Avoid race conditions with proper synchronization + +2. **Function Isolation**: Ensure function invocations don't interfere with each other + - Isolate per-request state + - Clean up resources after each invocation + +## Memory Management + +### Memory Efficiency + +1. **Limit Memory Buffering**: Don't load entire request/response bodies into memory + - Stream large payloads + - Set reasonable limits on payload sizes + +2. **Garbage Collection**: Optimize GC for runtime environment + - For GC languages, tune GC parameters for request-response patterns + - Release references to large objects as soon as possible + +3. **Memory Leaks**: Prevent memory leaks + - Clean up event listeners and callbacks + - Close file handles and network connections + - Clear caches periodically + +### Resource Cleanup + +``` +# Ensure resources are cleaned up even on errors +try: + handle_request(request) +finally: + cleanup_resources() +``` + +## Caching Strategies + +### ETag Header Handling + +Per the specification, frameworks should **not** send an `etag` header by default to prevent unintended caching. However, implementers can: + +1. **Allow Opt-in Caching**: Provide mechanisms for developers to enable caching when appropriate +2. **Cache Framework Objects**: Cache parsed function code, configuration, etc. +3. **Connection Caching**: Cache connections to external services (as mentioned above) + +### Configuration Caching + +1. **Parse Configuration Once**: Don't re-parse environment variables or configuration on each request +2. **Cache Function References**: Load and cache the target function on startup + +## Common Performance Anti-Patterns + +### ❌ Anti-Pattern 1: Synchronous Blocking in Async Contexts + +```python +# Bad: Blocking call in async function +async def handle_cloudevent(event): + result = sync_http_call() # Blocks event loop + return result + +# Good: Use async version +async def handle_cloudevent(event): + result = await async_http_call() + return result +``` + +### ❌ Anti-Pattern 2: Creating Resources Per Request + +```javascript +// Bad: New client per request +function handleRequest(req, res) { + const client = new DatabaseClient(); + const result = await client.query(); + res.send(result); +} + +// Good: Reuse client +const client = new DatabaseClient(); +function handleRequest(req, res) { + const result = await client.query(); + res.send(result); +} +``` + +### ❌ Anti-Pattern 3: Unnecessary Serialization/Deserialization + +```go +// Bad: Multiple serialization steps +func handleRequest(w http.ResponseWriter, r *http.Request) { + data := parseJSON(r.Body) + jsonStr := toJSON(data) // Unnecessary + processedData := parseJSON(jsonStr) + // ... use processedData +} + +// Good: Work with parsed data directly +func handleRequest(w http.ResponseWriter, r *http.Request) { + data := parseJSON(r.Body) + // ... use data directly +} +``` + +### ❌ Anti-Pattern 4: Inefficient CloudEvent Parsing + +```java +// Bad: Parse entire body upfront +public void handleCloudEvent(HttpRequest request) { + String body = readEntireBody(request); + CloudEvent event = parseCloudEvent(body); + // ... use only small portion of event +} + +// Good: Parse lazily or stream +public void handleCloudEvent(HttpRequest request) { + CloudEventReader reader = new CloudEventReader(request.getInputStream()); + String eventType = reader.getType(); // Parse only what's needed + if (needsData(eventType)) { + Object data = reader.getData(); + } +} +``` + +### ❌ Anti-Pattern 5: Not Handling Timeouts Properly + +```ruby +# Bad: No timeout handling +def handle_http(request) + result = external_api_call() # May hang indefinitely + request.response.write(result) +end + +# Good: Set timeouts +def handle_http(request) + result = external_api_call(timeout: 30) + request.response.write(result) +rescue TimeoutError + request.response.status = 504 # Gateway Timeout +end +``` + +## Observability and Performance Monitoring + +### Built-in Performance Metrics + +Frameworks should consider providing: + +1. **Request Latency Metrics**: Track time to process requests +2. **Cold Start Metrics**: Measure initialization time +3. **Concurrent Request Count**: Monitor active requests +4. **Error Rates**: Track function errors and framework errors + +### Tracing Support + +As mentioned in the specification, frameworks may add `traceparent` property to CloudEvent objects. Implement this efficiently: + +1. **Parse Once**: Parse traceparent header only once per request +2. **Propagate Efficiently**: Pass trace context without excessive copying + +## Language-Specific Recommendations + +### Python +- Use `uvicorn` or `gunicorn` with async workers for better concurrency +- Avoid global imports in function code +- Use `asyncio` for I/O-bound operations + +### Node.js +- Leverage the event loop, avoid blocking operations +- Use clustering for CPU-bound operations +- Keep dependencies minimal (check `node_modules` size) + +### Go +- Use goroutines for concurrent request handling +- Set appropriate `GOMAXPROCS` +- Reuse buffers with `sync.Pool` + +### Java +- Use virtual threads (Java 21+) for high concurrency +- Configure JVM heap size appropriately +- Use non-blocking I/O frameworks (Netty, etc.) + +### .NET +- Use async/await throughout the stack +- Configure thread pool sizes +- Use `Span` and `Memory` to reduce allocations + +## Testing Performance + +### Load Testing + +Implementers should: + +1. **Test Concurrent Load**: Verify framework handles concurrent requests efficiently +2. **Measure Cold Start**: Track cold start times and optimize +3. **Profile Under Load**: Use profiling tools to identify bottlenecks +4. **Test Resource Limits**: Verify behavior at resource limits (memory, file descriptors, etc.) + +### Benchmarking + +Maintain benchmarks for: +- Request throughput (requests/second) +- Latency (p50, p95, p99) +- Cold start time +- Memory usage + +## Summary + +Key principles for high-performance Functions Framework implementations: + +1. **Start fast**: Minimize cold start time +2. **Handle concurrency**: Support multiple simultaneous requests efficiently +3. **Use resources wisely**: Pool connections, reuse objects, manage memory +4. **Avoid blocking**: Use async I/O for I/O-bound operations +5. **Monitor and measure**: Track performance metrics to identify issues + +By following these guidelines, Functions Framework implementations can provide excellent performance for serverless workloads. + +## Related Documentation + +- **[Performance Checklist](PERFORMANCE_CHECKLIST.md)** - Quick-reference implementation checklist +- **[Specification Improvements](SPECIFICATION_IMPROVEMENTS.md)** - Suggested enhancements to the core specification +- **[Functions Framework Specification](README.md#functions-framework-contract)** - Core contract and requirements diff --git a/PERFORMANCE_CHECKLIST.md b/PERFORMANCE_CHECKLIST.md new file mode 100644 index 0000000..61da8d8 --- /dev/null +++ b/PERFORMANCE_CHECKLIST.md @@ -0,0 +1,217 @@ +# Performance Checklist for Functions Framework Implementers + +This quick-reference checklist helps Functions Framework implementers ensure they've addressed key performance considerations. + +## 🚀 Startup Performance + +- [ ] Framework initialization completes **before** listening on HTTP port +- [ ] Target function is loaded and validated during startup (not on first request) +- [ ] Heavy dependencies are loaded lazily (only when needed) +- [ ] Framework startup overhead is **< 100ms** on standard hardware +- [ ] Configuration is parsed once at startup (not per-request) +- [ ] For compiled languages: code is pre-compiled during build phase + +**Test**: Measure cold start time from process start to ready-to-serve + +## ⚡ Request Handling + +- [ ] Request bodies are **not** fully buffered in memory by default +- [ ] Response streaming is supported for large payloads (>1MB) +- [ ] CloudEvent parsing is lazy (attributes parsed before data payload) +- [ ] HTTP headers are parsed efficiently (case-insensitive lookup without iteration) +- [ ] No unnecessary serialization/deserialization steps +- [ ] Request body parsing is on-demand (for HTTP functions) + +**Test**: Profile request handling with 1MB, 10MB, and 100MB payloads + +## 🔄 Concurrency + +- [ ] Framework can handle **at least 10 concurrent requests** without degradation +- [ ] Worker pool or event loop is used (not thread-per-request) +- [ ] Thread/worker pool is pre-allocated and reused +- [ ] Non-blocking I/O is used for I/O-bound operations +- [ ] Function invocations are properly isolated (no state leakage) +- [ ] Concurrent requests don't cause race conditions + +**Test**: Load test with 10, 50, and 100 concurrent requests + +## 💾 Memory Management + +- [ ] Memory buffering is bounded and configurable +- [ ] Request/response size limits are enforced +- [ ] Resources are cleaned up after each request +- [ ] No memory leaks (verify with long-running tests) +- [ ] Large objects are released promptly after use +- [ ] File handles and connections are closed properly + +**Test**: Run extended load test and monitor memory usage over time + +## 🔌 Resource Pooling + +- [ ] Connection pools are used for database clients +- [ ] HTTP client connections are reused +- [ ] Connection pool sizes are configurable +- [ ] Idle connections are cleaned up +- [ ] Pool exhaustion is handled gracefully +- [ ] Connections are validated before reuse + +**Test**: Monitor connection creation rate under load + +## ⚠️ Error Handling + +- [ ] Error paths are as fast or faster than success paths +- [ ] Timeouts are implemented for: + - [ ] Function execution (default: 60s) + - [ ] Request body read (default: 30s) + - [ ] External service calls +- [ ] Full request/response bodies are **not** logged on every error +- [ ] Error handling doesn't allocate excessive memory +- [ ] Framework returns appropriate HTTP status codes (4xx/5xx) + +**Test**: Inject errors and measure error response time + +## 📦 Caching + +- [ ] Configuration is cached (not re-parsed per request) +- [ ] Parsed function code is cached +- [ ] Connection pools serve as connection cache +- [ ] No `ETag` header is sent by default +- [ ] Framework **doesn't** cache request-specific data +- [ ] Caches are cleared when appropriate + +**Test**: Verify configuration is parsed only once + +## 📊 Observability + +- [ ] Basic metrics (request count, latency) add **< 1% overhead** +- [ ] Expensive tracing/profiling is opt-in +- [ ] Logging is asynchronous (doesn't block requests) +- [ ] Sampling is supported for high-volume scenarios +- [ ] `traceparent` header parsing is efficient +- [ ] Observability features can be disabled + +**Test**: Measure performance with/without observability enabled + +## 🎯 CloudEvent Processing + +- [ ] Both binary and structured content modes are supported +- [ ] Binary mode is optimized (lower overhead) +- [ ] CloudEvent attributes are parsed before data payload +- [ ] Large data payloads (>1MB) are streamed +- [ ] Schema validation is opt-in (due to overhead) +- [ ] Parsing errors return appropriate 400 status + +**Test**: Benchmark both content modes with various payload sizes + +## 🛣️ Routing + +- [ ] Static paths (`/robots.txt`, `/favicon.ico`) are handled without function invocation +- [ ] Path matching is efficient (hash lookup or trie) +- [ ] Health check endpoint (if provided) responds in **< 10ms** +- [ ] Routing adds minimal overhead +- [ ] All other paths route to the function + +**Test**: Measure routing overhead (request to function invocation) + +## 🧪 Testing + +- [ ] Performance benchmarks exist and are tracked +- [ ] Load testing is performed regularly +- [ ] Metrics tracked: + - [ ] Requests per second (throughput) + - [ ] Latency (p50, p95, p99) + - [ ] Cold start time + - [ ] Memory usage +- [ ] Performance regressions are detected in CI +- [ ] Concurrent load testing is performed +- [ ] Resource limits are tested (memory, file descriptors) + +## 🏗️ Language-Specific Optimizations + +### Python +- [ ] Use async WSGI/ASGI servers (`uvicorn`, `gunicorn` with async workers) +- [ ] Avoid global imports in function code +- [ ] Use `asyncio` for I/O operations + +### Node.js +- [ ] Event loop is never blocked +- [ ] Clustering is used for CPU-bound operations +- [ ] Dependencies are minimized (small `node_modules`) + +### Go +- [ ] Goroutines are used for concurrency +- [ ] `GOMAXPROCS` is set appropriately +- [ ] `sync.Pool` is used for buffer reuse + +### Java +- [ ] Virtual threads are used (Java 21+) or thread pool is configured +- [ ] JVM heap size is configured appropriately +- [ ] Non-blocking I/O is used (Netty, etc.) + +### .NET +- [ ] `async`/`await` is used throughout +- [ ] Thread pool is configured +- [ ] `Span` and `Memory` are used to reduce allocations + +### C++ +- [ ] RAII is used for resource management +- [ ] Move semantics are used to avoid copies +- [ ] Memory pools are used for allocations + +## 📈 Performance Targets + +Based on standard hardware (2 CPU cores, 2GB RAM): + +| Metric | Target | +|--------|--------| +| Cold start (framework overhead) | < 100ms | +| Request latency (empty function, p50) | < 5ms | +| Request latency (empty function, p99) | < 50ms | +| Throughput (empty function) | > 1000 req/s | +| Concurrent requests | ≥ 10 without degradation | +| Memory overhead (idle) | < 50MB | + +## 🔍 Profiling + +- [ ] CPU profiling is performed under load +- [ ] Memory profiling identifies leaks and allocations +- [ ] I/O profiling reveals blocking operations +- [ ] Flame graphs are generated for bottleneck identification +- [ ] Profiling is done for both cold start and steady state + +## 📚 Documentation + +- [ ] Performance characteristics are documented +- [ ] Configuration options affecting performance are documented +- [ ] Known performance limitations are documented +- [ ] Benchmarking methodology is documented +- [ ] Performance tuning guide exists for users + +## ✅ Final Validation + +Before releasing: + +1. **Benchmark** against previous version +2. **Profile** under realistic load +3. **Test** resource limits (what happens at max memory/connections?) +4. **Verify** no performance regressions +5. **Document** any performance changes + +--- + +## How to Use This Checklist + +1. **During Development**: Check items as you implement features +2. **During Review**: Use as code review checklist +3. **Before Release**: Ensure all items are addressed +4. **Regular Audits**: Revisit periodically to ensure compliance + +## References + +- [Performance Optimization Guide](PERFORMANCE.md) - Detailed best practices +- [Specification Improvements](SPECIFICATION_IMPROVEMENTS.md) - Suggested spec enhancements +- [Functions Framework Specification](README.md#functions-framework-contract) - Core requirements + +--- + +**Note**: This checklist represents best practices. Some items may not be applicable to all implementation languages or deployment environments. Use judgment based on your specific context. diff --git a/README.md b/README.md index 22f15d0..844032c 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,13 @@ Legend: - **Lint**: Tests code style. - **Conformance**: Tests adherence to the Functions Framework contract. +## Performance and Best Practices + +For optimal performance in serverless environments, see: +- **[Performance Optimization Guide](PERFORMANCE.md)** - Comprehensive best practices for implementing high-performance Functions Frameworks +- **[Performance Checklist](PERFORMANCE_CHECKLIST.md)** - Quick-reference checklist for implementers +- **[Specification Improvements](SPECIFICATION_IMPROVEMENTS.md)** - Suggested enhancements to this specification for better performance guidance + ## Specification Summary A Functions Framework instantiates web server and invokes function code in response to an **HTTP** (`http`) or **CloudEvent** (`cloudevent`) request depending on the function's signature type. A Functions Framework may also optionally support functions with signature type `event` for legacy-style events. diff --git a/SPECIFICATION_IMPROVEMENTS.md b/SPECIFICATION_IMPROVEMENTS.md new file mode 100644 index 0000000..d002cca --- /dev/null +++ b/SPECIFICATION_IMPROVEMENTS.md @@ -0,0 +1,325 @@ +# Specification Improvements for Performance + +This document suggests improvements to the Functions Framework specification to better address performance concerns and guide implementers toward efficient solutions. + +## Current Specification Analysis + +After analyzing the current README.md specification, the following areas could benefit from additional performance guidance: + +## 1. Concurrency Requirements - Enhancement Needed + +### Current State (Line 104) +> "For performance, efficiency and correctness reasons, the framework must be able to handle multiple concurrent invocations of the developer's function." + +### Issue +The specification states that frameworks **must** handle concurrent invocations but doesn't provide: +- Guidance on implementation strategies +- Minimum concurrency requirements +- Best practices for different runtime environments + +### Suggested Enhancement +Add a dedicated section on concurrency with specific guidance: + +```markdown +### Concurrency Requirements + +The framework must efficiently handle multiple concurrent invocations. Implementation strategies include: + +- **Event Loop Based**: For single-threaded runtimes (Node.js, Python asyncio) + - Use non-blocking I/O + - Avoid blocking the event loop with CPU-intensive operations + +- **Thread/Process Pool**: For multi-threaded runtimes (Java, Go, .NET) + - Maintain a worker pool sized appropriately for the environment + - Reuse threads/processes to minimize creation overhead + +- **Minimum Requirement**: Frameworks should support at least 10 concurrent requests without degradation +``` + +## 2. Startup Performance - Missing Guidance + +### Current State (Line 93) +> "The framework should be able to gracefully handle these dynamics, for example, by minimizing container and framework startup times." + +### Issue +- Uses "should" instead of "must" for startup time minimization +- No concrete guidance on what constitutes acceptable startup time +- No recommendations for lazy loading or initialization strategies + +### Suggested Enhancement +Add specific startup performance requirements: + +```markdown +### Startup Performance Requirements + +To minimize cold start times, frameworks MUST: + +1. **Initialization Order**: Complete all initialization before listening on the HTTP port +2. **Lazy Loading**: Defer loading of optional features until first use +3. **Startup Time Target**: Framework overhead should not exceed 100ms on standard hardware +4. **Function Loading**: Load and validate the target function during startup, not on first request + +Frameworks MAY: +- Provide configuration to pre-warm connections +- Support ahead-of-time compilation where applicable +- Implement lazy dependency loading mechanisms +``` + +## 3. Resource Cleanup - Not Specified + +### Issue +The specification doesn't address: +- Resource cleanup between requests +- Connection pooling and reuse +- Memory management strategies + +### Suggested Addition +Add a new section on resource management: + +```markdown +### Resource Management + +To ensure efficient resource utilization: + +1. **Connection Pooling**: Frameworks SHOULD maintain connection pools for reusable resources +2. **Resource Cleanup**: Frameworks MUST clean up per-request resources after response is sent +3. **Memory Limits**: Frameworks SHOULD respect container memory limits and avoid unbounded buffering +4. **File Handles**: Frameworks MUST close file handles and network connections promptly +``` + +## 4. Request/Response Body Handling - Efficiency Not Addressed + +### Issue +The specification doesn't provide guidance on: +- Streaming large request/response bodies +- Memory limits for body buffering +- Efficient parsing strategies + +### Suggested Addition + +```markdown +### Efficient Request/Response Handling + +To handle requests efficiently: + +1. **Streaming Support**: Frameworks SHOULD support streaming for request and response bodies larger than 1MB +2. **Memory Buffering**: Frameworks SHOULD NOT buffer entire request bodies in memory by default +3. **Lazy Parsing**: For HTTP functions, frameworks SHOULD parse request bodies lazily or on-demand +4. **Size Limits**: Frameworks SHOULD enforce configurable limits on request body sizes to prevent memory exhaustion + +Example: For CloudEvent functions, parse the CloudEvent envelope without fully parsing data payloads until accessed. +``` + +## 5. Caching and ETag Headers - Incomplete Guidance + +### Current State (Line 176) +> "To prevent caching, by default, the Functions Framework should *not* send an `etag` header in the HTTP response." + +### Issue +- Focuses only on preventing caching +- Doesn't address framework-internal caching opportunities +- No guidance on when caching is appropriate + +### Suggested Enhancement + +```markdown +### Caching Strategy + +#### HTTP Response Caching +To prevent unintended caching, frameworks MUST NOT send `etag` or `cache-control` headers by default. + +Frameworks MAY: +- Provide opt-in mechanisms for developers to enable response caching +- Allow developers to set cache headers explicitly + +#### Framework Internal Caching +To improve performance, frameworks SHOULD cache: +- Parsed configuration (environment variables, flags) +- Loaded function code and metadata +- Connection pools to external services +- Parsed CloudEvent schemas + +Frameworks MUST NOT cache: +- Request-specific data +- User function state (unless explicitly managed by the user) +``` + +## 6. Error Handling Performance - Not Addressed + +### Issue +The specification defines HTTP status codes but doesn't address: +- Performance of error paths +- Avoiding expensive operations in error handlers +- Circuit breaker patterns for failing external services + +### Suggested Addition + +```markdown +### Error Handling Performance + +To maintain performance during error conditions: + +1. **Fast Failure**: Error paths SHOULD be as fast or faster than success paths +2. **Avoid Expensive Logging**: Don't log full request/response bodies on every error +3. **Rate Limiting**: Frameworks MAY implement rate limiting to protect against request floods +4. **Timeout Handling**: Frameworks MUST implement timeouts to prevent indefinite hangs: + - Function execution timeout (configurable, default: 60s) + - Request body read timeout (default: 30s) +``` + +## 7. CloudEvent Processing - Optimization Opportunities + +### Current State (Line 148-149) +> "The framework must handle unmarshalling HTTP requests into the CloudEvents object that is passed to the developer's function, and should support both binary and structured content modes" + +### Issue +- Doesn't address performance implications of different content modes +- No guidance on efficient CloudEvent parsing +- Missing recommendations for large event payloads + +### Suggested Enhancement + +```markdown +### CloudEvent Processing Optimization + +For efficient CloudEvent processing: + +1. **Content Mode Selection**: + - Binary mode has lower parsing overhead (recommended for high-throughput scenarios) + - Structured mode is easier to debug (recommended for development) + +2. **Lazy Parsing**: Parse CloudEvent attributes (id, type, source) before parsing data payload +3. **Large Payloads**: For data payloads larger than 1MB: + - Consider streaming access to data field + - Use lazy deserialization of structured data + +4. **Schema Validation**: If schema validation is supported, make it opt-in due to performance overhead +``` + +## 8. Observability Performance Impact - Not Addressed + +### Current State (Line 190) +> "The framework may provide built-in observability support... they must be clearly documented and users must be able to enable or disable them." + +### Issue +- Doesn't address performance overhead of observability features +- No guidance on efficient implementation of tracing/logging + +### Suggested Enhancement + +```markdown +### Observability Performance + +To minimize performance impact of observability features: + +1. **Opt-In by Default**: Expensive observability features (detailed tracing, profiling) SHOULD be opt-in +2. **Sampling**: For high-volume scenarios, support sampling rather than full instrumentation +3. **Async Logging**: Log and metric writes SHOULD be asynchronous to avoid blocking request handling +4. **Minimal Overhead**: Basic observability (request count, latency) SHOULD add less than 1% overhead + +#### Traceparent Performance +When adding `traceparent` to CloudEvent objects: +- Parse the header once per request +- Use efficient string operations (avoid regex when possible) +- Don't create trace spans if tracing is disabled +``` + +## 9. Function Loading and Validation - Performance Not Considered + +### Issue +The specification requires loading the function on startup but doesn't address: +- Validation performance +- Module import optimization +- Code compilation overhead + +### Suggested Addition + +```markdown +### Function Loading Performance + +To minimize startup time: + +1. **Load Once**: Load and validate the target function during framework initialization +2. **Validate Eagerly**: Validate function signature and exports at startup, not at first request +3. **Compilation**: For JIT languages, trigger function compilation at startup +4. **Import Optimization**: + - Use selective imports to minimize dependency loading + - Consider lazy loading of optional function dependencies + +Error cases: +- If function fails to load, fail fast at startup (don't wait for first request) +- Provide clear error messages that don't require function invocation to diagnose +``` + +## 10. URL Routing - Efficiency Consideration + +### Current State (Line 124-127) +> "Note that the framework must listen to all inbound paths (`.*`) and route these requests to the function, with the following exceptions: +> - `/robots.txt` - must respond with 404 without invoking function +> - `/favicon.ico` - must response with 404 without invoking function" + +### Issue +- No guidance on efficient path matching +- Could be extended with more performance-oriented exceptions + +### Suggested Enhancement + +```markdown +### URL Routing Performance + +For efficient request routing: + +1. **Fast Path Matching**: Use efficient path matching (hash lookup for exact matches, trie for patterns) +2. **Static Resource Handling**: The following paths MUST return 404 without invoking the function: + - `/robots.txt` + - `/favicon.ico` + - `/.well-known/*` (optional, framework-specific) + +3. **Health Check Endpoint**: Frameworks MAY provide a lightweight health check endpoint (e.g., `/_health`) that: + - Responds without invoking the function + - Checks framework readiness only + - Returns within 10ms + +This allows load balancers to perform health checks without function invocation overhead. +``` + +## Summary of Recommended Specification Changes + +### High Priority (Performance Critical) +1. ✅ Add specific concurrency requirements and implementation guidance +2. ✅ Define startup performance targets and best practices +3. ✅ Add resource management and cleanup requirements +4. ✅ Specify efficient request/response body handling + +### Medium Priority (Important for Optimization) +5. ✅ Enhance caching guidance (both external and internal) +6. ✅ Add error handling performance requirements +7. ✅ Provide CloudEvent processing optimization guidance +8. ✅ Address observability performance impact + +### Lower Priority (Nice to Have) +9. ✅ Add function loading performance guidance +10. ✅ Enhance URL routing efficiency recommendations + +## Implementation Checklist for Framework Authors + +When implementing a Functions Framework, ensure: + +- [ ] Cold start time is measured and optimized (target: <100ms framework overhead) +- [ ] Concurrent request handling is implemented and tested (minimum: 10 concurrent requests) +- [ ] Connection pooling is used for external resources +- [ ] Request/response streaming is supported for large payloads +- [ ] Memory buffering is bounded and configurable +- [ ] Resource cleanup happens after each request +- [ ] Function is loaded and validated at startup, not on first request +- [ ] Error paths are optimized and don't have higher latency than success paths +- [ ] Observability features are opt-in or have minimal overhead +- [ ] Performance benchmarks are maintained and tracked over time + +These improvements would make the specification more actionable for implementers and result in more performant Functions Framework implementations across all languages. + +## Related Documentation + +- **[Performance Optimization Guide](PERFORMANCE.md)** - Comprehensive best practices and anti-patterns +- **[Performance Checklist](PERFORMANCE_CHECKLIST.md)** - Quick-reference implementation checklist +- **[Functions Framework Specification](README.md#functions-framework-contract)** - Current specification