icicle
Icicle is a PHP library for writing asynchronous code using synchronous coding techniques
Top Related Projects
A non-blocking concurrency framework for PHP applications. 🐘
Event-driven, non-blocking I/O with PHP.
🚀 Coroutine-based concurrency library for PHP
Cross-platform asynchronous I/O
Node.js JavaScript runtime ✨🐢🚀✨
PPM is a process manager, supercharger and load balancer for modern PHP applications.
Quick Overview
Icicle is a high-performance, asynchronous, and concurrent I/O library for the Rust programming language. It provides a set of tools and abstractions for building scalable network applications, including a TCP/UDP server, a WebSocket server, and a HTTP client and server.
Pros
- High Performance: Icicle is built on top of the Tokio runtime, which is known for its efficiency and scalability.
- Asynchronous and Concurrent: Icicle leverages Rust's async/await syntax and the Tokio runtime to enable asynchronous and concurrent I/O operations.
- Modular Design: Icicle is designed with a modular architecture, allowing developers to use only the components they need for their specific use case.
- Extensive Documentation: The Icicle project has detailed documentation, including examples and guides, making it easier for developers to get started.
Cons
- Steep Learning Curve: Icicle, like many Rust libraries, has a steeper learning curve compared to some other programming languages and their libraries.
- Limited Community: Icicle is a relatively new project, and its community is smaller compared to more established Rust libraries.
- Dependency on Tokio: Icicle is heavily dependent on the Tokio runtime, which may be a limitation for developers who prefer to use a different asynchronous runtime.
- Limited Ecosystem: The Icicle ecosystem is not as extensive as some other Rust libraries, with fewer third-party packages and integrations available.
Code Examples
Here are a few code examples demonstrating the usage of Icicle:
- TCP Server:
use icicle::server::tcp::TcpServer;
#[tokio::main]
async fn main() {
let mut server = TcpServer::new("127.0.0.1:8080");
server.on_connect(|conn| {
println!("New connection: {:?}", conn.remote_addr());
conn.write_all(b"Hello, client!").await.unwrap();
});
server.run().await.unwrap();
}
- WebSocket Server:
use icicle::server::websocket::WebSocketServer;
#[tokio::main]
async fn main() {
let mut server = WebSocketServer::new("127.0.0.1:8080");
server.on_connect(|conn| {
println!("New WebSocket connection: {:?}", conn.remote_addr());
conn.send_text("Hello, client!").await.unwrap();
});
server.run().await.unwrap();
}
- HTTP Client:
use icicle::client::http::HttpClient;
#[tokio::main]
async fn main() {
let client = HttpClient::new();
let response = client.get("https://www.example.com").await.unwrap();
println!("Status: {}", response.status());
println!("Body: {}", response.text().await.unwrap());
}
Getting Started
To get started with Icicle, you can follow these steps:
- Add the Icicle dependency to your Cargo.toml file:
[dependencies]
icicle = "0.6.0"
- Import the necessary modules and create a new Icicle server or client:
use icicle::server::tcp::TcpServer;
#[tokio::main]
async fn main() {
let mut server = TcpServer::new("127.0.0.1:8080");
// Set up your server logic here
server.run().await.unwrap();
}
- Refer to the Icicle documentation for more detailed information on how to use the various components, such as the TCP server, WebSocket server, and HTTP client.
Competitor Comparisons
A non-blocking concurrency framework for PHP applications. 🐘
Pros of Amp
- More active development and maintenance
- Larger community and ecosystem of extensions
- Better documentation and examples
Cons of Amp
- Steeper learning curve for beginners
- More complex API compared to Icicle
- Potentially higher overhead for simple use cases
Code Comparison
Amp:
Loop::run(function () {
$response = yield $http->request("http://example.com/");
$body = yield $response->getBody();
echo $body;
});
Icicle:
Coroutine\run(function () {
$response = yield $http->request("http://example.com/");
$body = yield $response->getBody();
echo $body;
});
Both Amp and Icicle are asynchronous PHP frameworks, but Amp has gained more traction in recent years. Amp offers a more comprehensive set of features and better long-term support, while Icicle provides a simpler API that may be easier for newcomers to grasp. The code examples show similar syntax for handling asynchronous HTTP requests, with minor differences in function names and structure. Ultimately, the choice between the two depends on project requirements, team expertise, and desired level of community support.
Event-driven, non-blocking I/O with PHP.
Pros of ReactPHP
- Larger community and ecosystem, with more contributors and third-party packages
- More mature project with a longer history and established stability
- Better documentation and more comprehensive examples
Cons of ReactPHP
- Slightly more complex API, which may have a steeper learning curve
- Less focus on performance optimization compared to Icicle
- Slower adoption of newer PHP features and language constructs
Code Comparison
ReactPHP example:
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server('127.0.0.1:8080', $loop);
$socket->on('connection', function (React\Socket\ConnectionInterface $conn) {
$conn->write("Hello World!\n");
});
$loop->run();
Icicle example:
$socket = yield Server::listen('127.0.0.1:8080');
while ($conn = yield $socket->accept()) {
yield $conn->write("Hello World!\n");
}
Both ReactPHP and Icicle are asynchronous PHP frameworks, but they differ in their approach and syntax. ReactPHP uses a more traditional event-driven model, while Icicle leverages PHP generators for a more synchronous-looking code style. Icicle's approach may be more intuitive for developers familiar with synchronous programming, but ReactPHP's larger ecosystem and community support make it a more popular choice for many projects.
🚀 Coroutine-based concurrency library for PHP
Pros of Swoole
- Written in C, offering better performance and lower resource usage
- Provides a more comprehensive set of features, including HTTP server, WebSocket server, and task workers
- Larger community and more extensive documentation
Cons of Swoole
- Requires compilation and installation as a PHP extension, which can be more complex
- Less portable across different environments due to its C-based nature
- Steeper learning curve for developers not familiar with low-level programming concepts
Code Comparison
Swoole example:
$server = new Swoole\HTTP\Server('127.0.0.1', 9501);
$server->on('request', function ($request, $response) {
$response->end('<h1>Hello World</h1>');
});
$server->start();
Icicle example:
$server = new Server(Socket\listen('127.0.0.1:9501'));
$server->on('connect', function (Connection $connection) {
$connection->write("HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\nHello World\r\n");
});
Loop\run();
Both examples create a simple HTTP server, but Swoole's API is more high-level and abstracted, while Icicle's approach is more low-level and requires manual HTTP response construction.
Cross-platform asynchronous I/O
Pros of libuv
- Widely adopted and battle-tested in production environments
- Extensive cross-platform support, including Windows
- Comprehensive documentation and large community
Cons of libuv
- C-based API, which may be less intuitive for some developers
- Steeper learning curve compared to higher-level abstractions
- Requires manual memory management
Code Comparison
libuv example:
uv_loop_t *loop = malloc(sizeof(uv_loop_t));
uv_loop_init(loop);
uv_tcp_t server;
uv_tcp_init(loop, &server);
Icicle example:
$loop = Loop\create();
$socket = Socket\listen($loop, '0.0.0.0', 8080);
$server = new Server($socket);
Summary
libuv is a mature, low-level library with broad platform support and extensive documentation. It's widely used in production environments but requires more manual management and has a steeper learning curve. Icicle, on the other hand, offers a higher-level PHP-based API, which may be more accessible to PHP developers but lacks the widespread adoption and extensive platform support of libuv.
Node.js JavaScript runtime ✨🐢🚀✨
Pros of Node.js
- Massive ecosystem with npm, providing access to a vast array of packages and libraries
- Extensive community support and documentation
- Well-established and battle-tested in production environments
Cons of Node.js
- Single-threaded event loop can be a bottleneck for CPU-intensive tasks
- Callback-based asynchronous programming can lead to "callback hell"
- Lack of built-in support for true multithreading
Code Comparison
Node.js (using callbacks):
const fs = require('fs');
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
Icicle (using coroutines):
use Icicle\Coroutine\Coroutine;
use Icicle\Filesystem\Filesystem;
$coroutine = new Coroutine(function () {
$data = yield Filesystem::read('file.txt');
echo $data;
});
While Node.js is more widely adopted and has a larger ecosystem, Icicle offers a coroutine-based approach that can simplify asynchronous code. Node.js excels in its maturity and community support, but Icicle's design may provide better performance for certain use cases, especially those involving concurrent I/O operations.
PPM is a process manager, supercharger and load balancer for modern PHP applications.
Pros of PHP-PM
- Designed specifically for PHP, offering optimized performance for PHP applications
- Supports popular PHP frameworks like Symfony and Laravel out of the box
- Provides a simple configuration process for easy integration into existing projects
Cons of PHP-PM
- Limited to PHP applications, lacking the language-agnostic approach of Icicle
- May require more manual configuration for non-standard PHP setups
- Less focus on asynchronous programming patterns compared to Icicle
Code Comparison
PHP-PM example:
$app = new Symfony\Component\HttpKernel\HttpKernelInterface();
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server('0.0.0.0:8080', $loop);
$http = new React\Http\Server($socket, function ($request, $response) use ($app) {
$app->handle($request)->then(function ($res) use ($response) {
$response->writeHead($res->getStatusCode(), $res->getHeaders());
$response->end($res->getBody());
});
});
Icicle example:
$server = new Icicle\Http\Server\Server($socket, function ($request, $response) {
yield $response->write("Hello, World!");
yield $response->end();
});
Icicle\Loop\run(function () use ($server) {
yield $server->start();
});
Both examples demonstrate setting up an HTTP server, but Icicle's approach emphasizes coroutines and asynchronous programming, while PHP-PM focuses on integrating with existing PHP frameworks.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Icicle is now deprecated in favor of Amp v2.0. This version is is currently under development, but close to release. The v2.0 branches are amp_v2 in all packages except the main Amp package, loop package, and postgres package, where v2.0 is the master branch.
Icicle
Icicle is a PHP library for writing asynchronous code using synchronous coding techniques.
Icicle uses Coroutines built with Awaitables and Generators to facilitate writing asynchronous code using techniques normally used to write synchronous code, such as returning values and throwing exceptions, instead of using nested callbacks typically found in asynchronous code.
Library Components
- Coroutines are interruptible functions for building asynchronous code using synchronous coding patterns and error handling.
- Awaitables act as placeholders for future values of asynchronous operations. Awaitables can be yielded in coroutines to define interruption points. Callbacks registered with awaitables may return values and throw exceptions.
- Observables represent asynchronous sets of values, providing operations usually associated with sets such as map, filter, and reduce. Observables also can be iterated over asynchronously within a coroutine.
- Loop (event loop) is used to schedule functions, run timers, handle signals, and poll sockets for pending data or await for space to write.
Available Packages
- Stream: Common coroutine-based interface for reading and writing data.
- Socket: Asynchronous stream socket server and client.
- Concurrent: Provides an easy to use interface for parallel execution with non-blocking communication and task execution.
- DNS: Asynchronous DNS query executor, resolver and connector.
- Filesystem: Asynchronous filesystem access.
- HTTP: Asynchronous HTTP server and client.
- WebSocket: Asynchronous WebSocket server and client.
- React Adapter: Adapts the event loop and awaitables of Icicle to interfaces compatible with components built for React.
Documentation and Support
Requirements
- PHP 5.5+ for v0.9.x branch (current stable) and v1.x branch (mirrors current stable)
- PHP 7 for v2.0 (master) branch supporting generator delegation and return expressions
Installation
The recommended way to install Icicle is with the Composer package manager. (See the Composer installation guide for information on installing and using Composer.)
Run the following command to use Icicle in your project:
composer require icicleio/icicle
You can also manually edit composer.json
to add Icicle as a project requirement.
// composer.json
{
"require": {
"icicleio/icicle": "^0.9"
}
}
Suggested
- pcntl extension: Enables custom signal handling.
- ev extension: Extension providing the most performant event loop implementation.
- uv extension (PHP 7 only): Another extension providing a more performant event loop implementation (experimental).
Example
The example script below demonstrates how awaitables can be yielded in a coroutine to create interruption points. Fulfillment values of awaitables are sent to the coroutine and rejection exceptions are thrown into the coroutine.
#!/usr/bin/env php
<?php
require dirname(__DIR__) . '/vendor/autoload.php';
use Icicle\Awaitable;
use Icicle\Coroutine\Coroutine;
use Icicle\Loop;
$generator = function () {
try {
// Sets $start to the value returned by microtime() after approx. 1 second.
$start = (yield Awaitable\resolve(microtime(true))->delay(1));
echo "Sleep time: ", microtime(true) - $start, "\n";
// Throws the exception from the rejected promise into the coroutine.
yield Awaitable\reject(new Exception('Rejected promise'));
} catch (Exception $e) { // Catches promise rejection reason.
echo "Caught exception: ", $e->getMessage(), "\n";
}
yield Awaitable\resolve('Coroutine completed');
};
$coroutine = new Coroutine($generator());
$coroutine->done(function ($data) {
echo $data, "\n";
});
Loop\run();
Top Related Projects
A non-blocking concurrency framework for PHP applications. 🐘
Event-driven, non-blocking I/O with PHP.
🚀 Coroutine-based concurrency library for PHP
Cross-platform asynchronous I/O
Node.js JavaScript runtime ✨🐢🚀✨
PPM is a process manager, supercharger and load balancer for modern PHP applications.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot