This topic describes how both built-in plugins of AI Gateway and custom plugins developed with different programming languages affect request latencies.
Platform plugin performance
Plugins provided by the platform introduce microsecond-level latency. For example, the key-auth and basic-auth plugins respectively add approximately 20 and 30 microseconds per request.
Custom plugin performance
The following benchmarks compare the respective performances of plugins developed using different programming languages. All plugins implement the same processing logic: 20 loop iterations of header setting, header retrieval, and header removal, respectively.
C++ implementation:
FilterHeadersStatus PluginContext::onRequestHeaders(uint32_t, bool) { std::string fake_header_key_prefix = "fake_key_"; std::string fake_header_value_prefix = "fake_value_"; // Inject 20 synthetic headers for (size_t i = 0; i < 20; i++) { addRequestHeader(fake_header_key_prefix + std::to_string(i), fake_header_value_prefix + std::to_string(i)); } // Validate header existence 20 times for (size_t i = 0; i < 20; i++) { getRequestHeader(fake_header_key_prefix + std::to_string(i)); } // Cleanup injected headers for (size_t i = 0; i < 20; i++) { removeRequestHeader(fake_header_key_prefix + std::to_string(i)); } return FilterHeadersStatus::Continue; }Go implementation:
func (ctx *httpContext) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action { fake_header_key_prefix := "fake_key_" fake_header_value_prefix := "fake_value_" for i := 0; i < 20; i++ { proxywasm.AddHttpRequestHeader(fake_header_key_prefix+strconv.Itoa(i), fake_header_value_prefix+strconv.Itoa(i)) } for i := 0; i < 20; i++ { proxywasm.GetHttpRequestHeader(fake_header_key_prefix + strconv.Itoa(i)) } for i := 0; i < 20; i++ { proxywasm.RemoveHttpRequestHeader(fake_header_key_prefix + strconv.Itoa(i)) } return types.ActionContinue }Rust implementation:
fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action { for i in 0..20 { let key = "fake_key_".to_string() + &i.to_string(); let value = "fake_value_".to_string() + &i.to_string(); self.set_http_request_header(&key, Some(&value)); } for i in 0..20 { let key = "fake_key_".to_string() + &i.to_string(); self.get_http_request_header(&key); } for i in 0..20 { let key = "fake_key_".to_string() + &i.to_string(); self.set_http_request_header(&key, None); } Action::Continue }AssemblyScript implementation:
function onRequestHeaders(a: u32, end_of_stream: bool): FilterHeadersStatusValues { let fake_header_key_prefix: string = "fake_key_"; let fake_header_value_prefix: string = "fake_value_"; for (let i = 0; i < 20; i++) { stream_context.headers.request.add(fake_header_key_prefix + i.toString(), fake_header_value_prefix + i.toString()) } for (let i = 0; i < 20; i++) { stream_context.headers.request.get(fake_header_key_prefix + i.toString()) } for (let i = 0; i < 20; i++) { stream_context.headers.request.remove(fake_header_key_prefix + i.toString()) } return FilterHeadersStatusValues.Continue; }
Language performance comparison
Language | Additional latency (ms) |
C++ | 0.19 |
Go | 0.20 |
Rust | 0.21 |
AssemblyScript | 0.21 |
The comparison results show that minimal performance variation exists across plugins developed with different programming languages.