我正在尝试创建一个Scala应用程序,包括一个库项目(让我们称之为common
),一个Thrift服务器项目(让我们称之为server
)和一个Play Web应用程序项目(以下称为web
).这三个都是用Scala编写的,并用sbt构建.
我的项目结构如下所示:
myproject/
-common/
...
-server/
...
-web/
-app/
-conf/
...
-project/
-Build.scala
-build.properties
-build.sbt
Run Code Online (Sandbox Code Playgroud)
我的build.sbt
文件(简化了一下)看起来像这样:
import play.Project._
name := "myproject"
version := "1.0-SNAPSHOT"
lazy val common = project
lazy val web = project
.settings(playScalaSettings: _*)
.dependsOn(common)
lazy val server = project
.dependsOn(common)
lazy val root = project.in(file("."))
.aggregate(common, web, server)
Run Code Online (Sandbox Code Playgroud)
这个问题是根项目不是Play项目,所以play
命令不起作用(它出错了
java.lang.RuntimeException: */*:playRunHooks is undefined.
at scala.sys.package$.error(package.scala:27)
Run Code Online (Sandbox Code Playgroud)
如果我在SBT文件中的行playScalaSettings
之后插入行,我可以通过使根项目看起来像Play项目来解决这个version
问题,但是我有另一个问题:该play run
命令尝试运行根项目,而不是web
子项目.显然,该play …
我是Scala的新手,并不熟悉Java的最新发展,所以我认为我认为这是一个基本问题.
我正在编写一些Scala代码,并使用ScalaTest和TestNG使用测试夹具进行测试.正在测试的代码使用slf4s执行其日志记录,由logback支持.
在我的'build.sbt'文件中,我有我需要的所有库的依赖项:
scalaVersion := "2.9.1"
// Add test dependencies on scalatest and testng
libraryDependencies ++= Seq("org.scalatest" %% "scalatest" % "1.6.1" % "test", "org.testng" % "testng" % "6.1.1" % "test")
// Use the slf4j logging facade for logging
libraryDependencies += "org.slf4j" % "slf4j-api" % "1.6.3"
//use the slf4j connectors to implement the JCL logging facade in terms of slf4j (which in turn is implemented in terms of logback)
//confused yet?
libraryDependencies += "org.slf4j" % "jcl-over-slf4j" % "1.6.3"
//use logback for …
Run Code Online (Sandbox Code Playgroud) 我正在构建一个工具,可以从一台服务器向另一台服务器传输非常大的流数据集(可能在单个流中的数量级为TB,通常为几十千兆字节).该工具的客户端部分将从源磁盘读取块,并通过网络发送它们.服务器端将从网络中读取这些块并将其写入服务器磁盘上的文件.
现在我正在尝试决定使用哪种传输方式.选项是原始TCP和HTTP.
我真的,真的希望能够使用HTTP.HttpListener(或WCF,如果我想去那条路线)可以很容易地插入HTTP Server API(http.sys),我可以免费获得身份验证和SSL之类的东西.现在的问题是表现.
我编写了一个简单的测试工具,使用BeginWrite/EndWrite异步I/O惯用法,在服务器端使用异步BeginRead/EndRead发送128K块空字节.我已经修改了这个测试工具,所以我可以通过HttpWebRequest
/ 使用HTTP PUT操作HttpListener
,或使用TcpClient
/进行普通的旧套接字写操作TcpListener
.要排除网卡或网络路径的问题,客户端和服务器都在一台计算机上并通过localhost进行通信.
在我的12核Windows 2008 R2测试服务器上,此测试工具的TCP版本可以以450MB/s的速度推送字节,并且CPU使用率最低.在同一个盒子上,测试工具的HTTP版本在130MB/s和200MB/s之间运行,具体取决于我如何调整它.
在这两种情况下,CPU使用率都很低,并且CPU使用的绝大部分是内核时间,所以我很确定我对C#和.NET运行时的使用不是瓶颈.这个盒子有两个6核Xeon X5650处理器,24GB单排DDR3内存,我自己专门用于自己的性能测试.
我已经知道HTTP客户端的调整一样ServicePointManager.MaxServicePointIdleTime
,ServicePointManager.DefaultConnectionLimit
,ServicePointManager.Expect100Continue
,和HttpWebRequest.AllowWriteStreamBuffering
.
有没有人对如何使HTTP.sys性能超过200MB/s有任何想法?有没有人看到它在任何环境下表现都很好?
更新:
下面是关于我与看到的表现更多的细节TcpListener
VS HttpListener
:
首先,我写了一个TcpClient/TcpListener测试.在我的测试盒上,能够推动450MB/s.
然后使用反射器我想出了如何获取HttpWebRequest底层的原始Socket对象,并修改了我的HTTP客户端测试以使用它.仍然没有快乐; 差不多200MB/s.
我目前的理论是http.sys针对典型的IIS用例进行了优化,这是一个很多并发的小请求,以及大量并发和可能很大的响应.我假设为了实现这种优化,MSFT必须以牺牲我正在努力实现的目标为代价,这是一个非常大的请求的非常高的吞吐量,响应非常小.
为了它的价值,我还尝试了多达32个并发HTTP PUT操作,看它是否可以扩展,但仍然没有乐趣; 大约200MB/s.
有趣的是,在我的开发工作站上,运行64位Windows 7的四核Xeon Precision T7400,我的TcpClient实现大约200MB/s,HTTP版本也大约200MB/s.一旦我将它带到运行Server 2008 R2的高端服务器级机器,TcpClient代码就会达到450MB/s,而HTTP.sys代码则保持在200左右.
在这一点上,我遗憾地得出结论,HTTP.sys不是我需要完成的工作的正确工具,并且将不得不继续使用我们一直使用的手动插槽协议.
我正在将一些C代码移植到Scala,后者广泛使用浮点运算.我在Scala中根据C版本的复制/粘贴编写了以下代码:
val complimentaryTerms = 2640.96e-6 * sin (f5)
+ 63.52e-6 * sin (2.0 * f5)
+ 11.75e-6 * sin (2.0 * f3 - 2.0 * f4 + 3.0 * f5)
+ 11.21e-6 * sin (2.0 * f3 - 2.0 * f4 + f5)
- 4.55e-6 * sin (2.0 * f3 - 2.0 * f4 + 2.0 * f5)
+ 2.02e-6 * sin (2.0 * f3 + 3.0 * f5)
+ 1.98e-6 * sin (2.0 * f3 + f5)
- 1.72e-6 …
Run Code Online (Sandbox Code Playgroud) 我正在研究我的第一个Rust程序,并且与Rust所有权语义相冲突.我声明了一个struct
将封装SQLite数据库连接,以便它维护一个Connection
成员.出于性能原因,我还想保留一个准备好的语句,由Statement
类型表示.这是我的代码的简化版本:
extern crate rusqlite; // 0.14.0
use rusqlite::{Connection, Statement};
pub struct Foo<'a> {
conn: Connection,
statement: Statement<'a>,
}
impl<'a> Foo<'a> {
pub fn new() -> Foo<'a> {
let conn = Connection::open(&":memory:").unwrap();
let statement = conn
.prepare("INSERT INTO Foo(name, hash) VALUES($1, $2)")
.unwrap();
Foo { conn, statement }
}
}
Run Code Online (Sandbox Code Playgroud)
我试图通过将conn
变量的所有权存储在成员中来将变量的所有权转移给被调用者Foo
,但是当我尝试编译此代码时,它失败了:
error[E0597]: `conn` does not live long enough
--> src/main.rs:13:25
|
13 | let statement = conn
| ^^^^ borrowed value …
Run Code Online (Sandbox Code Playgroud) 我一直在强迫自己使用gvim for Windows来满足我的大部分文本编辑需求.我逐渐变得越来越舒服,但是一个问题让我很烦.
我使用项目插件在我的gVim屏幕的左侧保持一个窗口,列出我的项目.它很方便,让我不能进入IDE退出.以下是它的外观:
然后我用<Leader>]调用右侧的NERDTree [:
然后我浏览NERDTree以找到我要找的任何东西,并用<Leader>]解散NERDTree [.这使得NERDTree窗口消失,但不是将主窗口恢复到原来的大小,而是增加项目窗口:
现在我手动调整项目窗口的大小,但这确实打断了我试图用vim实现的流程.
我正在使用gvim 7.2,NERDTree 3.1.1和项目1.4.1.任何人有任何想法如何解决这个问题?
更新:基于Steve K的回答,我找到了解决方案.运行该:Project
命令并创建项目窗口时,项目窗口是活动窗口.所以我只是添加set winfixwidth
到我的.vimrc
后面:Project
,这解决了问题.现在我可以显示和隐藏NERDtree到我心中的内容,没有烦人的窗口调整大小.
我正试着在Play 2.2.x中找到Iteratee库.我正在编写一个生成数据流的函数,计算成本很高.这是基本的想法,用方块替换昂贵的计算部分:
def expensiveFunction(x: Int): Future[Int] = Future.successful(x * x)
def expensiveRange(start: Int, end: Int): Enumerator[Future[Int]] = {
Enumerator.enumerate(start to end).map(i => expensiveFunction(i))
}
Run Code Online (Sandbox Code Playgroud)
如果我打电话给expensiveRange
我得到一个Enumerator[Future[Int]]
,这不是我想要的,因为它似乎没有利用Iteratee模式的显式异步.看来我应该能够把它变成一个Enumerator[Int]
封底使用我返回的期货而不是创造另一层的Future
.
我认为将结果转化Enumerator[Int]
为可取的是正确的吗?如果是这样,这样做的惯用方法是什么?
我们正在使用WCF构建一个简单的Web服务,我们的产品用它来通过WAN链接上传大文件.它应该是一个简单的HTTP PUT,它在大多数情况下工作正常.
这是服务合同的简化版本:
[ServiceContract, XmlSerializerFormat]
public interface IReplicationWebService
{
[OperationContract]
[WebInvoke(Method = "PUT", UriTemplate = "agents/{sourceName}/epoch/{guid}/{number}/{type}")]
ReplayResult PutEpochFile(string sourceName, string guid, string number, string type, Stream stream);
}
Run Code Online (Sandbox Code Playgroud)
在执行此合同时,我们从中读取数据stream
并将其写入文件.这很好用,所以我们在没有足够的磁盘空间来存储文件的情况下添加了一些错误处理.这大致是它的样子:
public ReplayResult PutEpochFile(string sourceName, string guid, string number, string type, Stream inStream)
{
//Stuff snipped
try
{
//Read from the stream and write to the file
}
catch (IOException ioe)
{
//IOException may mean no disk space
try
{
inStream.Close();
}
// if instream caused the IOException, close may …
Run Code Online (Sandbox Code Playgroud) 我有一些高性能的文件传输代码,我在C#中使用异步编程模型(APM)习语(例如BeginRead
/ EndRead
)编写.此代码从本地磁盘读取文件并将其写入套接字.
为了在现代硬件上获得最佳性能,尽可能在飞行中保留多个出色的I/O操作非常重要.因此,我BeginRead
在文件上发布了几个操作,然后当一个完成时,我BeginSend
在套接字上调用一个,当完成时我BeginRead
在文件上做另一个操作.细节有点复杂,但在高层次上就是这个想法.
我有基于APM的代码工作,但它很难遵循,可能有微妙的并发错误.我很乐意为此使用TPL.我认为Task.Factory.FromAsync
只是这样做,但有一个问题.
我见过的所有I/O示例(特别StreamExtensions
是Parallel Extensions Extras中的类)假定一次读取后跟一次写入.这不会按我需要的方式执行.
我不能使用简单的东西Parallel.ForEach
或Extras扩展,Task.Factory.Iterate
因为异步I/O任务不会在工作线程上花费太多时间,因此Parallel只启动另一个任务,导致可能有数十或数百个挂起的I/O操作; 方式太多了!您可以通过Wait
执行任务来解决这个问题,但这会导致创建事件句柄(内核对象),以及阻塞等待工作线程的任务等待句柄等待.我的基于APM的实现避免了这两件事.
我一直在玩不同的方法来保持飞行中的多个读/写操作,我已经设法使用延续调用一个创建另一个任务的方法,但它感觉很尴尬,并且肯定不喜欢惯用的TPL.
还有其他人在使用TPL时遇到过这样的问题吗?有什么建议?
我正在为公司内部使用编写一个 Rust 板条箱,它包装了优秀的 Tokiotracing
板条箱,并带有一些附加功能。我不仅重新导出了 中的宏tracing
,而且还添加了一些我自己的在内部调用tracing
宏的宏。我的目标是让我们所有的其他内部 crate 仅依赖于我的包装 crate,而不必tracing
在每个 crate 中明确引入依赖项。
这非常有效,直到我今天遇到一个问题,我花了几个小时来隔离。我做了一个最小的例子来展示这里的行为。
在这个例子中,我有一个带有两个 crate 的工作区:my-logger-crate
它包装tracing
和公开一个 macro print_trace!
,一个二进制 cratemy-binary-crate
依赖于my-logger-crate
,并在main
函数内调用宏。
该Cargo.toml
用于my-logger-crate
非常简单; 我添加到自动生成的骨架中的唯一内容是tracing
依赖项:
[package]
name = "my-logger-crate"
version = "0.1.0"
authors = ["Adam Nelson <anelson@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tracing = "0.1.12"
Run Code Online (Sandbox Code Playgroud)
这是my-logger-crate
宏:
[package]
name = …
Run Code Online (Sandbox Code Playgroud) 我在我的应用程序中使用任务并行库.我有一个任务(让我们称之为"DoSomething")可能被取消.无论任务是故障,取消还是成功完成,我都会继续执行该任务,执行一些清理工作.
在启动此任务的代码中,我想返回一个Task对象,其状态(出错,取消,运行完成)反映了DoSomething任务的状态,但重要的是我返回的这个任务不会反映这个状态,直到继续任务执行.
这是一个例子:
public Task Start(CancellationToken token)
{
var doSomethingTask = Task.Factory.StartNew(DoSomething
, token);
var continuationTask = doSomethingTask.ContinueWith
(
(antecedent) =>
{
if (antecedent.IsFaulted || antecedent.IsCanceled)
{
//Do failure-specific cleanup
}
//Do general cleanup without regard to failure or success
}
);
//TODO: How do I return a Task obj which Status reflect the status of doSomethingTask,
//but will not transition to that status until continuationTask completes?
}
Run Code Online (Sandbox Code Playgroud)
我可以使用TaskCompletionSource,但这看起来很糟糕.还有其他想法吗?
scala ×3
.net-4.0 ×2
c# ×2
rust ×2
.net ×1
asynchronous ×1
c#-4.0 ×1
http.sys ×1
logback ×1
performance ×1
project ×1
rust-cargo ×1
rust-tokio ×1
sbt ×1
slf4j ×1
streaming ×1
testng ×1
trace ×1
vim ×1
wcf ×1